<p>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 ?</p>

<pre><code>from smtplib import SMTP
import datetime

debuglevel = 0

smtp = SMTP()
smtp.set_debuglevel(debuglevel)
smtp.connect('YOUR.MAIL.SERVER', 26)
smtp.login('USERNAME@DOMAIN', 'PASSWORD')

from_addr = "John Doe &lt;john@doe.net&gt;"
to_addr = "foo@bar.com"

subj = "hello"
date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" )

message_text = "Hello\nThis is a mail from your server\n\nBye\n"

msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" 
        % ( from_addr, to_addr, subj, date, message_text )

smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()
</code></pre>

[{'answer_id': 64554, 'author': 'pjz', 'author_id': 8002, 'author_profile': 'https://Stackoverflow.com/users/8002', 'pm_score': 3, 'selected': False, 'text': '<p>The main gotcha I see is that you\'re not handling any errors: <code>.login()</code> and <code>.sendmail()</code> both have <a href="https://docs.python.org/3/library/smtplib.html#smtplib.SMTPException" rel="nofollow noreferrer">documented exceptions</a> that they can throw, and it seems like <code>.connect()</code> must have some way to indicate that it was unable to connect - probably an exception thrown by the underlying socket code.</p>\n'}, {'answer_id': 64580, 'author': 'Douglas Leeder', 'author_id': 3978, 'author_profile': 'https://Stackoverflow.com/users/3978', 'pm_score': 2, 'selected': False, 'text': '<p>You should make sure you format the date in the correct format - <a href="http://www.faqs.org/rfcs/rfc2822.html" rel="nofollow noreferrer">RFC2822</a>.</p>\n'}, {'answer_id': 64673, 'author': 'Mark Ransom', 'author_id': 5987, 'author_profile': 'https://Stackoverflow.com/users/5987', 'pm_score': 3, 'selected': False, 'text': "<p>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.</p>\n"}, {'answer_id': 64890, 'author': 'Vincent Marchetti', 'author_id': 8935, 'author_profile': 'https://Stackoverflow.com/users/8935', 'pm_score': 8, 'selected': True, 'text': '<p>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.</p>\n\n<p>I rely on my ISP to add the date time header.</p>\n\n<p>My ISP requires me to use a secure smtp connection to send mail, I rely on the smtplib module (downloadable at <a href="http://www1.cs.columbia.edu/~db2501/ssmtplib.py" rel="noreferrer">http://www1.cs.columbia.edu/~db2501/ssmtplib.py</a>)</p>\n\n<p>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.</p>\n\n<p>=======================================</p>\n\n<pre><code>#! /usr/local/bin/python\n\n\nSMTPserver = \'smtp.att.yahoo.com\'\nsender =     \'me@my_email_domain.net\'\ndestination = [\'recipient@her_email_domain.com\']\n\nUSERNAME = "USER_NAME_FOR_INTERNET_SERVICE_PROVIDER"\nPASSWORD = "PASSWORD_INTERNET_SERVICE_PROVIDER"\n\n# typical values for text_subtype are plain, html, xml\ntext_subtype = \'plain\'\n\n\ncontent="""\\\nTest message\n"""\n\nsubject="Sent from Python"\n\nimport sys\nimport os\nimport re\n\nfrom smtplib import SMTP_SSL as SMTP       # this invokes the secure SMTP protocol (port 465, uses SSL)\n# from smtplib import SMTP                  # use this for standard SMTP protocol   (port 25, no encryption)\n\n# old version\n# from email.MIMEText import MIMEText\nfrom email.mime.text import MIMEText\n\ntry:\n    msg = MIMEText(content, text_subtype)\n    msg[\'Subject\']=       subject\n    msg[\'From\']   = sender # some SMTP servers will do this automatically, not all\n\n    conn = SMTP(SMTPserver)\n    conn.set_debuglevel(False)\n    conn.login(USERNAME, PASSWORD)\n    try:\n        conn.sendmail(sender, destination, msg.as_string())\n    finally:\n        conn.quit()\n\nexcept:\n    sys.exit( "mail failed; %s" % "CUSTOM_ERROR" ) # give an error message\n</code></pre>\n'}, {'answer_id': 275124, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 5, 'selected': False, 'text': "<p>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:</p>\n\n<pre><code>...\nsmtp.connect('YOUR.MAIL.SERVER', 587)\nsmtp.ehlo()\nsmtp.starttls()\nsmtp.ehlo()\nsmtp.login('USERNAME@DOMAIN', 'PASSWORD')\n...\n</code></pre>\n"}, {'answer_id': 11228560, 'author': 'Satish', 'author_id': 1159538, 'author_profile': 'https://Stackoverflow.com/users/1159538', 'pm_score': 3, 'selected': False, 'text': '<p>What about this? </p>\n\n<pre><code>import smtplib\n\nSERVER = "localhost"\n\nFROM = "sender@example.com"\nTO = ["user@example.com"] # must be a list\n\nSUBJECT = "Hello!"\n\nTEXT = "This message was sent with Python\'s smtplib."\n\n# Prepare actual message\n\nmessage = """\\\nFrom: %s\nTo: %s\nSubject: %s\n\n%s\n""" % (FROM, ", ".join(TO), SUBJECT, TEXT)\n\n# Send the mail\n\nserver = smtplib.SMTP(SERVER)\nserver.sendmail(FROM, TO, message)\nserver.quit()\n</code></pre>\n'}, {'answer_id': 17596848, 'author': 'madman2890', 'author_id': 1813869, 'author_profile': 'https://Stackoverflow.com/users/1813869', 'pm_score': 7, 'selected': False, 'text': "<p>The method I commonly use...not much different but a little bit</p>\n\n<pre><code>import smtplib\nfrom email.MIMEMultipart import MIMEMultipart\nfrom email.MIMEText import MIMEText\n\nmsg = MIMEMultipart()\nmsg['From'] = 'me@gmail.com'\nmsg['To'] = 'you@gmail.com'\nmsg['Subject'] = 'simple email in python'\nmessage = 'here is the email'\nmsg.attach(MIMEText(message))\n\nmailserver = smtplib.SMTP('smtp.gmail.com',587)\n# identify ourselves to smtp gmail client\nmailserver.ehlo()\n# secure our email with tls encryption\nmailserver.starttls()\n# re-identify ourselves as an encrypted connection\nmailserver.ehlo()\nmailserver.login('me@gmail.com', 'mypassword')\n\nmailserver.sendmail('me@gmail.com','you@gmail.com',msg.as_string())\n\nmailserver.quit()\n</code></pre>\n\n<p>That's it</p>\n"}, {'answer_id': 26191922, 'author': 'Abdul Majeed', 'author_id': 5629004, 'author_profile': 'https://Stackoverflow.com/users/5629004', 'pm_score': 3, 'selected': False, 'text': '<p>following code is working fine for me:</p>\n<pre><code>import smtplib\n \nto = \'mkyong2002@yahoo.com\'\ngmail_user = \'mkyong2002@gmail.com\'\ngmail_pwd = \'yourpassword\'\nsmtpserver = smtplib.SMTP(&quot;smtp.gmail.com&quot;,587)\nsmtpserver.ehlo()\nsmtpserver.starttls()\nsmtpserver.ehlo()\nsmtpserver.login(gmail_user, gmail_pwd)\nheader = \'To:\' + to + \'\\n\' + \'From: \' + gmail_user + \'\\n\' + \'Subject:testing \\n\'\nprint header\nmsg = header + \'\\n this is test msg from mkyong.com \\n\\n\'\nsmtpserver.sendmail(gmail_user, to, msg)\nprint \'done!\'\nsmtpserver.quit()\n</code></pre>\n<p>Ref: <a href="http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/" rel="nofollow noreferrer">http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/</a></p>\n'}, {'answer_id': 29720511, 'author': 'PascalVKooten', 'author_id': 1575066, 'author_profile': 'https://Stackoverflow.com/users/1575066', 'pm_score': 2, 'selected': False, 'text': '<p>See all those lenghty answers? Please allow me to self promote by doing it all in a couple of lines.</p>\n\n<p>Import and Connect:</p>\n\n<pre><code>import yagmail\nyag = yagmail.SMTP(\'john@doe.net\', host = \'YOUR.MAIL.SERVER\', port = 26)\n</code></pre>\n\n<p>Then it is just a one-liner:</p>\n\n<pre><code>yag.send(\'foo@bar.com\', \'hello\', \'Hello\\nThis is a mail from your server\\n\\nBye\\n\')\n</code></pre>\n\n<p>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 <code>yagmail</code>!)</p>\n\n<p>For the package/installation, tips and tricks please look at <a href="https://github.com/kootenpv/yagmail" rel="nofollow">git</a> or <a href="https://pypi.python.org/pypi/yagmail/" rel="nofollow">pip</a>, available for both Python 2 and 3.</p>\n'}, {'answer_id': 50230501, 'author': 'Skiller Dz', 'author_id': 8808047, 'author_profile': 'https://Stackoverflow.com/users/8808047', 'pm_score': 2, 'selected': False, 'text': "<p>you can do like that</p>\n\n<pre><code>import smtplib\nfrom email.mime.text import MIMEText\nfrom email.header import Header\n\n\nserver = smtplib.SMTP('mail.servername.com', 25)\nserver.ehlo()\nserver.starttls()\n\nserver.login('username', 'password')\nfrom = 'me@servername.com'\nto = 'mygfriend@servername.com'\nbody = 'That A Message For My Girl Friend For tell Him If We will go to eat Something This Nigth'\nsubject = 'Invite to A Diner'\nmsg = MIMEText(body,'plain','utf-8')\nmsg['Subject'] = Header(subject, 'utf-8')\nmsg['From'] = Header(from, 'utf-8')\nmsg['To'] = Header(to, 'utf-8')\nmessage = msg.as_string()\nserver.sendmail(from, to, message)\n</code></pre>\n"}, {'answer_id': 51680874, 'author': 'Mark', 'author_id': 622306, 'author_profile': 'https://Stackoverflow.com/users/622306', 'pm_score': 1, 'selected': False, 'text': "<p>Here's a working example for Python 3.x</p>\n\n<pre><code>#!/usr/bin/env python3\n\nfrom email.message import EmailMessage\nfrom getpass import getpass\nfrom smtplib import SMTP_SSL\nfrom sys import exit\n\nsmtp_server = 'smtp.gmail.com'\nusername = 'your_email_address@gmail.com'\npassword = getpass('Enter Gmail password: ')\n\nsender = 'your_email_address@gmail.com'\ndestination = 'recipient_email_address@gmail.com'\nsubject = 'Sent from Python 3.x'\ncontent = 'Hello! This was sent to you via Python 3.x!'\n\n# Create a text/plain message\nmsg = EmailMessage()\nmsg.set_content(content)\n\nmsg['Subject'] = subject\nmsg['From'] = sender\nmsg['To'] = destination\n\ntry:\n    s = SMTP_SSL(smtp_server)\n    s.login(username, password)\n    try:\n        s.send_message(msg)\n    finally:\n        s.quit()\n\nexcept Exception as E:\n    exit('Mail failed: {}'.format(str(E)))\n</code></pre>\n"}, {'answer_id': 55473040, 'author': 'Hariharan AR', 'author_id': 8612590, 'author_profile': 'https://Stackoverflow.com/users/8612590', 'pm_score': 2, 'selected': False, 'text': '<p>The example code which i did for send mail using SMTP.</p>\n\n<pre><code>import smtplib, ssl\n\nsmtp_server = "smtp.gmail.com"\nport = 587  # For starttls\nsender_email = "sender@email"\nreceiver_email = "receiver@email"\npassword = "&lt;your password here&gt;"\nmessage = """ Subject: Hi there\n\nThis message is sent from Python."""\n\n\n# Create a secure SSL context\ncontext = ssl.create_default_context()\n\n# Try to log in to server and send email\nserver = smtplib.SMTP(smtp_server,port)\n\ntry:\n    server.ehlo() # Can be omitted\n    server.starttls(context=context) # Secure the connection\n    server.ehlo() # Can be omitted\n    server.login(sender_email, password)\n    server.sendmail(sender_email, receiver_email, message)\nexcept Exception as e:\n    # Print any error messages to stdout\n    print(e)\nfinally:\n    server.quit()\n</code></pre>\n'}, {'answer_id': 60511210, 'author': 'Robert Lujo', 'author_id': 565525, 'author_profile': 'https://Stackoverflow.com/users/565525', 'pm_score': 2, 'selected': False, 'text': '<p>Based on <a href="https://stackoverflow.com/questions/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439">this example</a> I made following function:</p>\n\n<pre><code>import smtplib\nfrom email.mime.multipart import MIMEMultipart\nfrom email.mime.text import MIMEText\n\ndef send_email(host, port, user, pwd, recipients, subject, body, html=None, from_=None):\n    """ copied and adapted from\n        https://stackoverflow.com/questions/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439\n    returns None if all ok, but if problem then returns exception object\n    """\n\n    PORT_LIST = (25, 587, 465)\n\n    FROM = from_ if from_ else user \n    TO = recipients if isinstance(recipients, (list, tuple)) else [recipients]\n    SUBJECT = subject\n    TEXT = body.encode("utf8") if isinstance(body, unicode) else body\n    HTML = html.encode("utf8") if isinstance(html, unicode) else html\n\n    if not html:\n        # Prepare actual message\n        message = """From: %s\\nTo: %s\\nSubject: %s\\n\\n%s\n        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)\n    else:\n                # https://stackoverflow.com/questions/882712/sending-html-email-using-python#882770\n        msg = MIMEMultipart(\'alternative\')\n        msg[\'Subject\'] = SUBJECT\n        msg[\'From\'] = FROM\n        msg[\'To\'] = ", ".join(TO)\n\n        # Record the MIME types of both parts - text/plain and text/html.\n        # utf-8 -&gt; https://stackoverflow.com/questions/5910104/python-how-to-send-utf-8-e-mail#5910530\n        part1 = MIMEText(TEXT, \'plain\', "utf-8")\n        part2 = MIMEText(HTML, \'html\', "utf-8")\n\n        # Attach parts into message container.\n        # According to RFC 2046, the last part of a multipart message, in this case\n        # the HTML message, is best and preferred.\n        msg.attach(part1)\n        msg.attach(part2)\n\n        message = msg.as_string()\n\n\n    try:\n        if port not in PORT_LIST: \n            raise Exception("Port %s not one of %s" % (port, PORT_LIST))\n\n        if port in (465,):\n            server = smtplib.SMTP_SSL(host, port)\n        else:\n            server = smtplib.SMTP(host, port)\n\n        # optional\n        server.ehlo()\n\n        if port in (587,): \n            server.starttls()\n\n        server.login(user, pwd)\n        server.sendmail(FROM, TO, message)\n        server.close()\n        # logger.info("SENT_EMAIL to %s: %s" % (recipients, subject))\n    except Exception, ex:\n        return ex\n\n    return None\n</code></pre>\n\n<p>if you pass only <code>body</code> then plain text mail will be sent, but if you pass <code>html</code> argument along with <code>body</code> argument, html email will be sent (with fallback to text content for email clients that don\'t support html/mime types).</p>\n\n<p>Example usage:</p>\n\n<pre><code>ex = send_email(\n      host        = \'smtp.gmail.com\'\n   #, port        = 465 # OK\n    , port        = 587  #OK\n    , user        = "xxx@gmail.com"\n    , pwd         = "xxx"\n    , from_       = \'xxx@gmail.com\'\n    , recipients  = [\'yyy@gmail.com\']\n    , subject     = "Test from python"\n    , body        = "Test from python - body"\n    )\nif ex: \n    print("Mail sending failed: %s" % ex)\nelse:\n    print("OK - mail sent"\n</code></pre>\n\n<p>Btw. If you want to use gmail as testing or production SMTP server, \nenable temp or permanent access to less secured apps:</p>\n\n<ul>\n<li>login to google mail/account</li>\n<li>go to: <a href="https://myaccount.google.com/lesssecureapps" rel="nofollow noreferrer">https://myaccount.google.com/lesssecureapps</a></li>\n<li>enable</li>\n<li>send email using this function or similar</li>\n<li>(recommended) go to: <a href="https://myaccount.google.com/lesssecureapps" rel="nofollow noreferrer">https://myaccount.google.com/lesssecureapps</a></li>\n<li>(recommended) disable</li>\n</ul>\n'}, {'answer_id': 65853330, 'author': 'Milovan Tomašević', 'author_id': 13155046, 'author_profile': 'https://Stackoverflow.com/users/13155046', 'pm_score': 2, 'selected': False, 'text': '<p>Or</p>\n<pre class="lang-py prettyprint-override"><code>import smtplib\n \nfrom email.message import EmailMessage\nfrom getpass import getpass\n\n\npassword = getpass()\n\nmessage = EmailMessage()\nmessage.set_content(\'Message content here\')\nmessage[\'Subject\'] = \'Your subject here\'\nmessage[\'From\'] = &quot;USERNAME@DOMAIN&quot;\nmessage[\'To\'] = &quot;you@mail.com&quot;\n\ntry:\n    smtp_server = None\n    smtp_server = smtplib.SMTP(&quot;YOUR.MAIL.SERVER&quot;, 587)\n    smtp_server.ehlo()\n    smtp_server.starttls()\n    smtp_server.ehlo()\n    smtp_server.login(&quot;USERNAME@DOMAIN&quot;, password)\n    smtp_server.send_message(message)\nexcept Exception as e:\n    print(&quot;Error: &quot;, str(e))\nfinally:\n    if smtp_server is not None:\n        smtp_server.quit()\n</code></pre>\n<p>If you want to use Port 465 you have to create an <code>SMTP_SSL</code> object.</p>\n'}, {'answer_id': 72752742, 'author': 'miksus', 'author_id': 13696660, 'author_profile': 'https://Stackoverflow.com/users/13696660', 'pm_score': 0, 'selected': False, 'text': '<p>What about <a href="https://red-mail.readthedocs.io/" rel="nofollow noreferrer">Red Mail</a>?</p>\n<p>Install it:</p>\n<pre><code>pip install redmail\n</code></pre>\n<p>Then just:</p>\n<pre><code>from redmail import EmailSender\n\n# Configure the sender\nemail = EmailSender(\n    host=&quot;YOUR.MAIL.SERVER&quot;, \n    port=26,\n    username=\'me@example.com\',\n    password=\'&lt;PASSWORD&gt;\'\n)\n\n# Send an email:\nemail.send(\n    subject=&quot;An example email&quot;,\n    sender=&quot;me@example.com&quot;,\n    receivers=[\'you@example.com\'],\n    text=&quot;Hello!&quot;,\n    html=&quot;&lt;h1&gt;Hello!&lt;/h1&gt;&quot;\n)\n</code></pre>\n<p>It has quite a lot of features:</p>\n<ul>\n<li><a href="https://red-mail.readthedocs.io/en/latest/tutorials/attachments.html" rel="nofollow noreferrer">Email attachments from various sources</a></li>\n<li><a href="https://red-mail.readthedocs.io/en/latest/tutorials/body_content.html" rel="nofollow noreferrer">Embedding images and plots to the HTML body</a></li>\n<li><a href="https://red-mail.readthedocs.io/en/latest/tutorials/jinja_support.html" rel="nofollow noreferrer">Templating emails with Jinja</a></li>\n<li><a href="https://red-mail.readthedocs.io/en/latest/tutorials/config.html" rel="nofollow noreferrer">Preconfigured Gmail and Outlook</a></li>\n<li><a href="https://red-mail.readthedocs.io/en/latest/extensions/logging.html" rel="nofollow noreferrer">Logging handler</a></li>\n<li><a href="https://red-mail.readthedocs.io/en/latest/extensions/flask.html" rel="nofollow noreferrer">Flask extension</a></li>\n</ul>\n<p>Links:</p>\n<ul>\n<li><a href="https://github.com/Miksus/red-mail" rel="nofollow noreferrer">Source code</a></li>\n<li><a href="https://red-mail.readthedocs.io/" rel="nofollow noreferrer">Documentation</a></li>\n<li><a href="https://pypi.org/project/redmail/" rel="nofollow noreferrer">Releases</a></li>\n</ul>\n'}, {'answer_id': 74403965, 'author': 'foodog123', 'author_id': 19566293, 'author_profile': 'https://Stackoverflow.com/users/19566293', 'pm_score': 0, 'selected': False, 'text': "<p>Based on madman2890, updated a few things as well as removed the need for mailserver.quit()</p>\n<pre><code>import smtplib\nfrom email.mime.multipart import MIMEMultipart\nfrom email.mime.text import MIMEText\n\nmsg = MIMEMultipart()\nmsg['From'] = 'me@gmail.com'\nmsg['To'] = 'you@gmail.com'\nmsg['Subject'] = 'simple email in python'\nmessage = 'here is the email'\nmsg.attach(MIMEText(message))\n\nwith smtplib.SMTP('smtp-mail.outlook.com',587) as mail_server:\n    # identify ourselves to smtp gmail client\n    mail_server.ehlo()\n    # secure our email with tls encryption\n    mail_server.starttls()\n    # re-identify ourselves as an encrypted connection\n    mail_server.ehlo()\n    mail_server.login('me@gmail.com', 'mypassword')\n    mail_server.sendmail('me@gmail.com','you@gmail.com',msg.as_string())\n</code></pre>\n"}]
['https://Stackoverflow.com/questions/64505', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/8206/']