Sending mail from Python using SMTP

后端 未结 13 831
半阙折子戏
半阙折子戏 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: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

提交回复
热议问题