I’m using the following method to send mail from Python using SMTP. Is it the right method to use or are there gotchas I’m missing ?
from smtplib import SMTP
import datetime
debuglevel = 0
smtp = SMTP()
smtp.set_debuglevel(debuglevel)
smtp.connect('YOUR.MAIL.SERVER', 26)
smtp.login('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d88d8b9d8a9699959d989c9795999196">[email protected]</a>', 'PASSWORD')
from_addr = "John Doe <<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5832373036183c373d76363d2c">[email protected]</a>>"
to_addr = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dcbab3b39cbebdaef2bfb3b1">[email protected]</a>"
subj = "hello"
date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" )
message_text = "HellonThis is a mail from your servernnByen"
msg = "From: %snTo: %snSubject: %snDate: %snn%s"
% ( from_addr, to_addr, subj, date, message_text )
smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The script I use is quite similar; I post it here as an example of how to use the email.* modules to generate MIME messages; so this script can be easily modified to attach pictures, etc.
I rely on my ISP to add the date time header.
My ISP requires me to use a secure smtp connection to send mail, I rely on the smtplib module (downloadable at http://www1.cs.columbia.edu/~db2501/ssmtplib.py)
As in your script, the username and password, (given dummy values below), used to authenticate on the SMTP server, are in plain text in the source. This is a security weakness; but the best alternative depends on how careful you need (want?) to be about protecting these.
=======================================
#! /usr/local/bin/python
SMTPserver = 'smtp.att.yahoo.com'
sender = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7f121a3f1206">[email protected]</a>_email_domain.net'
destination = ['<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="20524543495049454e5460484552">[email protected]</a>_email_domain.com']
USERNAME = "USER_NAME_FOR_INTERNET_SERVICE_PROVIDER"
PASSWORD = "PASSWORD_INTERNET_SERVICE_PROVIDER"
# typical values for text_subtype are plain, html, xml
text_subtype = 'plain'
content="""
Test message
"""
subject="Sent from Python"
import sys
import os
import re
from smtplib import SMTP_SSL as SMTP # this invokes the secure SMTP protocol (port 465, uses SSL)
# from smtplib import SMTP # use this for standard SMTP protocol (port 25, no encryption)
# old version
# from email.MIMEText import MIMEText
from email.mime.text import MIMEText
try:
msg = MIMEText(content, text_subtype)
msg['Subject']= subject
msg['From'] = sender # some SMTP servers will do this automatically, not all
conn = SMTP(SMTPserver)
conn.set_debuglevel(False)
conn.login(USERNAME, PASSWORD)
try:
conn.sendmail(sender, destination, msg.as_string())
finally:
conn.quit()
except:
sys.exit( "mail failed; %s" % "CUSTOM_ERROR" ) # give an error message
Method 2
The method I commonly use…not much different but a little bit
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
msg = MIMEMultipart()
msg['From'] = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="87eae2c7e0eae6eeeba9e4e8ea">[email protected]</a>'
msg['To'] = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="651c0a10250208040c094b060a08">[email protected]</a>'
msg['Subject'] = 'simple email in python'
message = 'here is the email'
msg.attach(MIMEText(message))
mailserver = smtplib.SMTP('smtp.gmail.com',587)
# identify ourselves to smtp gmail client
mailserver.ehlo()
# secure our email with tls encryption
mailserver.starttls()
# re-identify ourselves as an encrypted connection
mailserver.ehlo()
mailserver.login('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e18c84a1868c80888dcf828e8c">[email protected]</a>', 'mypassword')
mailserver.sendmail('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9bf6fedbfcf6faf2f7b5f8f4f6">[email protected]</a>','<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="720b1d0732151f131b1e5c111d1f">[email protected]</a>',msg.as_string())
mailserver.quit()
That’s it
Method 3
Also if you want to do smtp auth with TLS as opposed to SSL then you just have to change the port (use 587) and do smtp.starttls(). This worked for me:
...
smtp.connect('YOUR.MAIL.SERVER', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bbeee8fee9f5faf6fefbfff4f6faf2f5">[email protected]</a>', 'PASSWORD')
...
Method 4
Make sure you don’t have any firewalls blocking SMTP. The first time I tried to send an email, it was blocked both by Windows Firewall and McAfee – took forever to find them both.
Method 5
What about this?
import smtplib SERVER = "localhost" FROM = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4635232822233406233e272b362a236825292b">[email protected]</a>" TO = ["<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c1b4b2a4b381a4b9a0acb1ada4efa2aeac">[email protected]</a>"] # must be a list SUBJECT = "Hello!" TEXT = "This message was sent with Python's smtplib." # Prepare actual message message = """ From: %s To: %s Subject: %s %s """ % (FROM, ", ".join(TO), SUBJECT, TEXT) # Send the mail server = smtplib.SMTP(SERVER) server.sendmail(FROM, TO, message) server.quit()
Method 6
The main gotcha I see is that you’re not handling any errors: .login() and .sendmail() both have documented exceptions that they can throw, and it seems like .connect() must have some way to indicate that it was unable to connect – probably an exception thrown by the underlying socket code.
Method 7
following code is working fine for me:
import smtplib
to = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="573a3c2e38393065676765172e363f38387934383a">[email protected]</a>'
gmail_user = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="076a6c7e6869603537373547606a666e6b2964686a">[email protected]</a>'
gmail_pwd = 'yourpassword'
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + to + 'n' + 'From: ' + gmail_user + 'n' + 'Subject:testing n'
print header
msg = header + 'n this is test msg from mkyong.com nn'
smtpserver.sendmail(gmail_user, to, msg)
print 'done!'
smtpserver.quit()
Ref: http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/
Method 8
The example code which i did for send mail using SMTP.
import smtplib, ssl
smtp_server = "smtp.gmail.com"
port = 587 # For starttls
sender_email = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="691a0c070d0c1b290c04080005">[email protected]</a>"
receiver_email = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8dffe8eee8e4fbe8ffcde8e0ece4e1">[email protected]</a>"
password = "<your password here>"
message = """ Subject: Hi there
This message is sent from Python."""
# Create a secure SSL context
context = ssl.create_default_context()
# Try to log in to server and send email
server = smtplib.SMTP(smtp_server,port)
try:
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
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()
Method 9
You should make sure you format the date in the correct format – RFC2822.
Method 10
See all those lenghty answers? Please allow me to self promote by doing it all in a couple of lines.
Import and Connect:
import yagmail
yag = yagmail.SMTP('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1872777076587c777d36767d6c">[email protected]</a>', host = 'YOUR.MAIL.SERVER', port = 26)
Then it is just a one-liner:
yag.send('<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cdaba2a28dafacbfe3aea2a0">[email protected]</a>', 'hello', 'HellonThis is a mail from your servernnByen')
It will actually close when it goes out of scope (or can be closed manually). Furthermore, it will allow you to register your username in your keyring such that you do not have to write out your password in your script (it really bothered me prior to writing yagmail!)
For the package/installation, tips and tricks please look at git or pip, available for both Python 2 and 3.
Method 11
you can do like that
import smtplib
from email.mime.text import MIMEText
from email.header import Header
server = smtplib.SMTP('mail.servername.com', 25)
server.ehlo()
server.starttls()
server.login('username', 'password')
from = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d1bcb491a2b4a3a7b4a3bfb0bcb4ffb2bebc">[email protected]</a>'
to = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bad7c3dddcc8d3dfd4defac9dfc8ccdfc8d4dbd7df94d9d5d7">[email protected]</a>'
body = 'That A Message For My Girl Friend For tell Him If We will go to eat Something This Nigth'
subject = 'Invite to A Diner'
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
message = msg.as_string()
server.sendmail(from, to, message)
Method 12
Based on this example I made following function:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_email(host, port, user, pwd, recipients, subject, body, html=None, from_=None):
""" copied and adapted from
https://stackoverflow.com/questions/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439
returns None if all ok, but if problem then returns exception object
"""
PORT_LIST = (25, 587, 465)
FROM = from_ if from_ else user
TO = recipients if isinstance(recipients, (list, tuple)) else [recipients]
SUBJECT = subject
TEXT = body.encode("utf8") if isinstance(body, unicode) else body
HTML = html.encode("utf8") if isinstance(html, unicode) else html
if not html:
# Prepare actual message
message = """From: %snTo: %snSubject: %snn%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
else:
# https://stackoverflow.com/questions/882712/sending-html-email-using-python#882770
msg = MIMEMultipart('alternative')
msg['Subject'] = SUBJECT
msg['From'] = FROM
msg['To'] = ", ".join(TO)
# Record the MIME types of both parts - text/plain and text/html.
# utf-8 -> https://stackoverflow.com/questions/5910104/python-how-to-send-utf-8-e-mail#5910530
part1 = MIMEText(TEXT, 'plain', "utf-8")
part2 = MIMEText(HTML, 'html', "utf-8")
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
message = msg.as_string()
try:
if port not in PORT_LIST:
raise Exception("Port %s not one of %s" % (port, PORT_LIST))
if port in (465,):
server = smtplib.SMTP_SSL(host, port)
else:
server = smtplib.SMTP(host, port)
# optional
server.ehlo()
if port in (587,):
server.starttls()
server.login(user, pwd)
server.sendmail(FROM, TO, message)
server.close()
# logger.info("SENT_EMAIL to %s: %s" % (recipients, subject))
except Exception, ex:
return ex
return None
if you pass only body then plain text mail will be sent, but if you pass html argument along with body argument, html email will be sent (with fallback to text content for email clients that don’t support html/mime types).
Example usage:
ex = send_email(
host = 'smtp.gmail.com'
#, port = 465 # OK
, port = 587 #OK
, user = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4a3232320a2d272b232664292527">[email protected]</a>"
, pwd = "xxx"
, from_ = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="621a1a1a22050f030b0e4c010d0f">[email protected]</a>'
, recipients = ['<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="542d2d2d143339353d387a373b39">[email protected]</a>']
, subject = "Test from python"
, body = "Test from python - body"
)
if ex:
print("Mail sending failed: %s" % ex)
else:
print("OK - mail sent"
Btw. If you want to use gmail as testing or production SMTP server,
enable temp or permanent access to less secured apps:
- login to google mail/account
- go to: https://myaccount.google.com/lesssecureapps
- enable
- send email using this function or similar
- (recommended) go to: https://myaccount.google.com/lesssecureapps
- (recommended) disable
Method 13
Or
import smtplib
from email.message import EmailMessage
from getpass import getpass
password = getpass()
message = EmailMessage()
message.set_content('Message content here')
message['Subject'] = 'Your subject here'
message['From'] = "[email protected]"
message['To'] = "[email protected]"
try:
smtp_server = None
smtp_server = smtplib.SMTP("YOUR.MAIL.SERVER", 587)
smtp_server.ehlo()
smtp_server.starttls()
smtp_server.ehlo()
smtp_server.login("[email protected]", password)
smtp_server.send_message(message)
except Exception as e:
print("Error: ", str(e))
finally:
if smtp_server is not None:
smtp_server.quit()
If you want to use Port 465 you have to create an SMTP_SSL object.
Method 14
Here’s a working example for Python 3.x
#!/usr/bin/env python3
from email.message import EmailMessage
from getpass import getpass
from smtplib import SMTP_SSL
from sys import exit
smtp_server = 'smtp.gmail.com'
username = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="750c1a00072a1018141c192a14111107100606351218141c195b161a18">[email protected]</a>'
password = getpass('Enter Gmail password: ')
sender = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1c6573696e4379717d7570437d78786e796f6f5c7b717d7570327f7371">[email protected]</a>'
destination = '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8cfee9efe5fce5e9e2f8d3e9e1ede5e0d3ede8e8fee9ffffccebe1ede5e0a2efe3e1">[email protected]</a>'
subject = 'Sent from Python 3.x'
content = 'Hello! This was sent to you via Python 3.x!'
# Create a text/plain message
msg = EmailMessage()
msg.set_content(content)
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = destination
try:
s = SMTP_SSL(smtp_server)
s.login(username, password)
try:
s.send_message(msg)
finally:
s.quit()
except Exception as E:
exit('Mail failed: {}'.format(str(E)))
Method 15
What about Red Mail?
Install it:
pip install redmail
Then just:
from redmail import EmailSender
# Configure the sender
email = EmailSender(
host="YOUR.MAIL.SERVER",
port=26,
username='<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="14797154716c75796478713a777b79">[email protected]</a>',
password='<PASSWORD>'
)
# Send an email:
email.send(
subject="An example email",
sender="<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f49991b4918c9599849891da979b99">[email protected]</a>",
receivers=['<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e59c8a90a5809d8488958980cb868a88">[email protected]</a>'],
text="Hello!",
html="<h1>Hello!</h1>"
)
It has quite a lot of features:
- Email attachments from various sources
- Embedding images and plots to the HTML body
- Templating emails with Jinja
- Preconfigured Gmail and Outlook
- Logging handler
- Flask extension
Links:
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0