I'm trying to send a basic email with an attached document. The example I have works fine with a google address smtp.google.com, but when I try changing it over to smtp.office365.com, I get this error: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:852).
This is a domain email that runs through the office365 SMTP server as a host for the email service. I've checked with the IT team, and they have turned on SMTP authentication on the account.
Obviously, this has been done before, so I have checked my code against this example, but don't see any obvious differences that could be causing it. I've also doubled checked the smtplib documentation, and smtp.office365.com is a valid, recognized SMTP address.
I've written this out as follows (note the confidential credentials which prevent a minimal reproducible example). I've noted where the error occurs, it's almost like smtplib is not recognizing the office365 SMTP address.
def send_email(self, html_message):
# Create a text/plain message
formatted_date = datetime.datetime.now().strftime('%Y%m%d')
msg_root = MIMEMultipart('related')
msg_root['Subject'] = self.client.client_name + 'Test Forecast'
msg_root['From'] = self.config.get_email_from
recipients = self.client.recipient_email
recipients = recipients.split(', ')
body = MIMEText(html_message, 'html')
msg_root.attach(body)
filename = self.client.city + ', ' + self.client.state
# PDF attachment
if self.client.use_pdf:
filepath = self.config.get_email_pdf_file_path
fp = open(filepath, 'rb')
att = email.mime.application.MIMEApplication(fp.read(), _subtype="pdf")
fp.close()
att.add_header('Content-Disposition', 'attachment', filename=filename + '.pdf')
msg_root.attach(att)
# SSL port config
port = 587
# Create a secure SSL context
context = ssl.create_default_context()
# Connect
with smtplib.SMTP_SSL("smtp.office365.com", port, context=context) as server: # Error on this line
server.ehlo()
server.starttls()
server.login(self.config.get_email_from, self.config.get_email_password)
print("Sending email report...")
# Send email
server.sendmail(self.config.get_email_from, recipients, msg_root.as_string())
print("Your email was sent!")
According to
error: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:852)
You should use 465 port because you are using SSL protocol and 587 port is for TLS protocol.
It appears that because Microsoft uses port 587 for SMTP and the external domain we're using doesn't communicate via SSL, I had to change the port over to 587, remove the SSL argument from the method, and remove the context. With it now using SMTP rather than SSL, starttls was also necessary.
The working version looks like this:
port = 587
# Connect
with smtplib.SMTP("smtp.office365.com", port) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login(self.config.get_email_from, self.config.get_email_password)
print("Sending email report...")
# Send email
server.sendmail(self.config.get_email_from, recipients, msg_root.as_string())
print("Your email was sent!")
Related
I am trying to send email internally within work using the smtplib package in Python. I am running this script behind a VPN using the same proxy settings for R and Spyder.
I use the following code which was adapted from mkyoung.com
import smtplib
to = 'foo#foo-corporate.com'
corp_user = 'foo#foo-corporate.com'
corp_pwd = 'password'
smtpserver = smtplib.SMTP_SSL(local_hostname="smtp://foo-corporate.com", port = 25)
smtpserver.connect()
Once i try the last line smtpserver.connect(), I get the error message:
[WinError 10061] No connection could be made because the target machine actively refused it
This would suggest that the server is not accepting SMTP requests.
However if i execute the same script in R using the Blastula package It works fine.
Can anyone suggest how I can trouble shoot this?
library(blastula)
create_smtp_creds_key(
id = "email_creds",
user = "foo#foo-corporate.com",
host = "smtp://foo-corporate.com",
port = 25,
use_ssl = TRUE
)
email <-
compose_email(
body = md(" Hello,
This is a test email
"))
# Sending email by SMTP using a credentials file
email %>%
smtp_send(
to = "foo#foo-corporate.com",
from = "foo#foo-corporate.com",
subject = "Testing the `smtp_send()` function",
credentials = creds_key("email_creds")
)
Seems like the context is not needed at all.
This is an example using TLS. Give it a try, at least in my environment, this worked.
import smtplib
smtp_server = 'mail.example.com'
port = 587 # For starttls
sender_email = "from#mail.com"
receiver_email = 'to#mail.com'
password = r'password'
message = f'''\
From: from-name <from#mail.com>
To: to-name <to#mail.com>
Subject: testmail
testmail
'''
try:
server = smtplib.SMTP(smtp_server, port)
server.ehlo()
server.starttls()
server.ehlo()
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
Hi #user99999 and #Ovski
Thank you for investigating this for me.
I managed to finally get it working with the below code
import smtplib
import ssl
to = 'foo#foo-corporate.com'
corp_user = 'foo#foo-corporate.com'
corp_pwd = 'password'
smtpserver = smtplib.SMTP_SSL("smtp://foo-corporate.com")
smtp_server.ehlo()
smtp_server.login(corp_user, corp_pwd)
msg_to_send = '''
hello world!
'''
smtp_server.sendmail(user,to,msg_to_send)
smtp_server.quit()
I would like to use Python's SMTP to send automated emails with a custom domain iCloud+ email address. However, I can't get logged into the SMTP servers. I will always either get "Mailbox does not exist" or "Authentication failed".
From the Apple support pages it seems like you need to use SSL over port 587. Additionally, they want you to generate an "app-specific password" for outside applications. This led me to the following code:
import smtplib, ssl
smtp_server = "smtp.mail.me.com"
port = 587 # For SSL
# Create a secure SSL context
context = ssl.create_default_context()
sender_email = "me#example.com" # Enter your address
receiver_email = "you#example.com" # Enter receiver address
password = "some,password" # app specific password from Apple ID settings
message = """\
To: {to}
From: {sender}
Subject: Hello There
This was sent through Python!
""".format(to=receiver_email, sender=sender_email)
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
# Send email here
server.sendmail(sender_email, receiver_email, message)
However, this was still giving me a connection error. Only when I changed the last part to use TLS instead would it connect and give me an authentication error. This was taken from this question: SMTP_SSL SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)
try:
server = smtplib.SMTP(smtp_server, port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
# Send email here
server.sendmail(sender_email, receiver_email, message)
except Exception as e:
import traceback
print(traceback.format_exc())
finally:
server.quit()
So how can I use my custom domain address with Apple's iCloud+ service with Python's SMTP?
Just before I was going to ask this question, I solved it!
After reading this reddit post, I figured that all custom domain iCloud+ accounts are actually alias of some sort to the main iCloud account. So, I tried logging into my "main" iCloud account. This worked with the above code and sent the email! However, the from was still not my custom domain email address.
This is a somewhat easy fix though, simply modify the "From: <sender>" line in the email body. I'm not sure if this should be done (since it's technicaly faking who you are) but it seems to work. If any email experts know of better ways to do this please comment/answer though! The following code is what I used:
sender_email = "me#icloud.com" # this is who we actually are
sender = "me#example.com" # this is who we appear to be (i.e. custom domain email)
receiver_email = "you#example.com" # this is to who we have sent the email
message = """\
To: {to}
From: {sender}
Subject: Hello There
This was sent through Python!
""".format(to=receiver_email, sender=sender) # this is what changed, we use an alias instead
# ...
server.sendmail(sender_email, receiver_email, message)
I am trying to send an email using a python script like so:
import smtplib, ssl
port = 465
smtp_server = "smtp.gmail.com"
sender_email = "my#gmail.com"
receiver_email = "receiver#gmail.com"
password = "123456"
message = """\
Subject: Hi there
This message is sent from Python."""
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
but unfortunately, Gmail blocks this connection, after running this code I receive an email saying that someone tried to access my account from an app that is not owned by Google, does anyone know a solution to this problem?
when I test below code with server = smtplib.SMTP('smpt.gmail.com:587') it works fine.
But when I change SMTP server to server = smtplib.SMTP('10.10.9.9: 25') - it gives me an error. This SMTP does not require any password.
So what am I missing here?
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import pandas as pd
def send_email(user, recipient, subject):
try:
d = {'Col1':[1,2], 'Col2':[3,4]}
df=pd.DataFrame(d)
df_html = df.to_html()
dfPart = MIMEText(df_html,'html')
user = "myEmail#gmail.com"
#pwd = No need for password with this SMTP
subject = "Test subject"
recipients = "some_recipientk#blabla.com"
#Container
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = user
msg['To'] = ",".join(recipients)
msg.attach(dfPart)
#server = smtplib.SMTP('smpt.gmail.com:587') #this works
server = smtplib.SMTP('10.10.9.9: 25') #this doesn't work
server.starttls()
server.login(user, pwd)
server.sendmail(user, recipients, msg.as_string())
server.close()
print("Mail sent succesfully!")
except Exception as e:
print(str(e))
print("Failed to send email")
send_email(user,"","Test Subject")
IF the server does not require authentication THEN do not use SMTP AUTH.
Remove the following line:
server.login(user, pwd)
Hi I am not entirely sure why it's not working but I have got a few things you can check.
server = smtplib.SMTP('10.10.9.9: 25')
you got a space in the ip:port string, try removing it.
The ip:port combination seems to be from a private LAN address
Try to ping this address to see if you can reach it, If you can't then talk to the person who handles the machine with given ip in your network.
If you can ping the ip, then there is a possibility that the SMTP server is not available on the given port, In that case too contact the person responsible for managing the machine with IP: 10.10.9.9
use given command on terminal
ping 10.10.9.9
Also before login and and sendmail, you should connect to server using connect(), The correct order would be.
server = smtplib.SMTP('10.10.9.9: 25')
server.starttls()
server.connect('10.10.9.9', 465)
server.login(user, pwd)
server.sendmail(user, recipients, msg.as_string())
server.close()
465 is the default port for SMTP server
Thanks,
Let me know If It helped you!
I am trying to use Python's smtplib module to send an email but I keep receiving a TimeoutError.
import smtplib
def send():
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(email, password) # Email and password are already defined
print('Enter recipient: ')
recipient = input()
print('Enter subject:')
subject = input() + '\n'
print('Enter body:')
body = input()
server.sendmail(email, recipient, body)
server.quit()
except TimeoutError as e:
print (str(e))
This code recieves a:
[WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
It looks like you have not enabled "Allow Less Secure Apps" option in your GMail account.
Here's more officially from Google,
https://support.google.com/accounts/answer/6010255?hl=en
If you are using a VPN connection, disable it first. It worked for me.
Use port 587. I was getting the same error but when I entered 587 as port it worked
smtplib.SMTP("smtp.gmail.com", 587)