I am writing a Python program to send an email. But every time when executing the clause:
smtpserver = smtplib.SMTP(\"smtp.gmail.com\",587)
For reference, cpython smtplib is blocking. That is, it blocks the GIL (ie Python) while connecting. Despite the claims the GIL is released on I/O, it is only released on some I/O, and SMTP connections are not such. To make it async, you need to hand the mail send to another process or thread, depending on your situation.
There may be some issue with the connection (maybe it is being blocked by your proxy or firewall?) and the timeout may be pretty big for you to do not see it going further.
The documentation of smtplib.SMTP says:
class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])
(...) An
SMTPConnectError
is raised if the specifiedhost
doesn’t respond correctly. The optionaltimeout
parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used).
Try specifying the timeout yourself:
smtpserver = smtplib.SMTP("smtp.gmail.com", 587, timeout=30)
Maybe I am 4 years late, but this is what worked for me and might help someone else!
server = smtplib.SMTP("smtp.gmail.com", 587, None, 30)
I ran into a similar issue and none of the answers above worked for me. My problem was that since my smtp server uses SSL. I needed to use smtplib.SMTP_SSL
instead of smtplib.SMTP
. I just posting my full working code below.
Make sure to change values of req
and email_config
before executing.
req = {
"email": "to@something.com",
"subject": "new e-mail from python",
"body": "Hi,\nI am a bot",
}
email_config = {
"server": "smtp.orange.fr",
"port": 465,
"username": "username@orange.fr",
"password": "mypassword",
"email": "fromwhichemail@orange.fr",
}
#!/usr/bin/env python3
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
class Mail(object):
def __init__(self, email_config):
self.email = email_config["email"]
self.password = email_config["password"]
self.server = email_config["server"]
self.port = email_config["port"]
print(f"Logging to {self.server}:{self.port}")
session = smtplib.SMTP_SSL(self.server, self.port)
print(f"Calling ehlo")
session.ehlo()
print(f"Calling login")
session.login(self.email, self.password)
self.session = session
def send_message(self, subject, to, body, filename):
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = self.email
message["To"] = to
message["Subject"] = subject
message["Bcc"] = ""
# Add body to email
message.attach(MIMEText(body, "plain"))
print(f"tot: {to}")
print(f"subject: {subject}")
print(f"body: {body}")
if filename is not None:
# Open PDF file in binary mode
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",)
# Add attachment to message and convert message to string
message.attach(part)
# Send e-mail
print(f"Sending e-mail...")
self.session.sendmail(self.email, to, message.as_string())
if __name__ == "__main__":
req = {
"email": "to@something.com",
"subject": "new e-mail from python",
"body": "Hi,\nI am a bot",
}
email_config = {
"server": "smtp.orange.fr",
"port": 465,
"username": "username@orange.fr",
"password": "mypassword",
"email": "fromwhichemail@orange.fr",
}
m = Mail(email_config)
if "pdf_file" in req:
m.send_message(req["subject"], req["email"], req["body"], req["pdf_file"])
else:
m.send_message(req["subject"], req["email"], req["body"], None)