Sending mail from Python using SMTP

后端 未结 13 778
半阙折子戏
半阙折子戏 2020-11-28 17:27

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 SM         


        
相关标签:
13条回答
  • 2020-11-28 18:07

    What about this?

    import smtplib
    
    SERVER = "localhost"
    
    FROM = "sender@example.com"
    TO = ["user@example.com"] # 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()
    
    0 讨论(0)
  • 2020-11-28 18:10

    You should make sure you format the date in the correct format - RFC2822.

    0 讨论(0)
  • 2020-11-28 18: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: %s\nTo: %s\nSubject: %s\n\n%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        = "xxx@gmail.com"
        , pwd         = "xxx"
        , from_       = 'xxx@gmail.com'
        , recipients  = ['yyy@gmail.com']
        , 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
    0 讨论(0)
  • 2020-11-28 18:13

    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.

    0 讨论(0)
  • 2020-11-28 18:13

    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('john@doe.net', host = 'YOUR.MAIL.SERVER', port = 26)
    

    Then it is just a one-liner:

    yag.send('foo@bar.com', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')
    

    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.

    0 讨论(0)
  • 2020-11-28 18:17

    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 = 'your_email_address@gmail.com'
    password = getpass('Enter Gmail password: ')
    
    sender = 'your_email_address@gmail.com'
    destination = 'recipient_email_address@gmail.com'
    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)))
    
    0 讨论(0)
提交回复
热议问题