How do I send attachments using SMTP?

后端 未结 6 896
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-01 01:55

I want to write a program that sends email using Python\'s smtplib. I searched through the document and the RFCs, but couldn\'t find anything related to attachments. Thus,

6条回答
  •  旧巷少年郎
    2020-12-01 02:05

    Here's how to send e-mails with zip file attachments and utf-8 encoded subject+body.

    It was not straightforward to figure this one out, due to lack of documentation and samples for this particular case.

    Non-ascii characters in replyto needs to be encoded with, for instance, ISO-8859-1. There probably exists a function that can do this.

    Tip:
    Send yourself an e-mail, save it and examine the content to figure out how to do the same thing in Python.

    Here's the code, for Python 3:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    # vim:set ts=4 sw=4 et:
    
    from os.path import basename
    from smtplib import SMTP
    from email.mime.text import MIMEText
    from email.mime.base import MIMEBase
    from email.mime.multipart import MIMEMultipart
    from email.header import Header
    from email.utils import parseaddr, formataddr
    from base64 import encodebytes
    
    def send_email(recipients=["somebody@somewhere.xyz"],
             subject="Test subject æøå",
             body="Test body æøå",
             zipfiles=[],
             server="smtp.somewhere.xyz",
             username="bob",
             password="password123",
             sender="Bob ",
             replyto="=?ISO-8859-1?Q?M=F8=F8=F8?= "): #: bool
        """Sends an e-mail"""
        to = ",".join(recipients)
        charset = "utf-8"
        # Testing if body can be encoded with the charset
        try:
            body.encode(charset)
        except UnicodeEncodeError:
            print("Could not encode " + body + " as " + charset + ".")
            return False
    
        # Split real name (which is optional) and email address parts
        sender_name, sender_addr = parseaddr(sender)
        replyto_name, replyto_addr = parseaddr(replyto)
    
        sender_name = str(Header(sender_name, charset))
        replyto_name = str(Header(replyto_name, charset))
    
        # Create the message ('plain' stands for Content-Type: text/plain)
        try:
            msgtext = MIMEText(body.encode(charset), 'plain', charset)
        except TypeError:
            print("MIMEText fail")
            return False
    
        msg = MIMEMultipart()
    
        msg['From'] = formataddr((sender_name, sender_addr))
        msg['To'] = to #formataddr((recipient_name, recipient_addr))
        msg['Reply-to'] = formataddr((replyto_name, replyto_addr))
        msg['Subject'] = Header(subject, charset)
    
        msg.attach(msgtext)
    
        for zipfile in zipfiles:
            part = MIMEBase('application', "zip")
            b = open(zipfile, "rb").read()
            # Convert from bytes to a base64-encoded ascii string
            bs = encodebytes(b).decode()
            # Add the ascii-string to the payload
            part.set_payload(bs)
            # Tell the e-mail client that we're using base 64
            part.add_header('Content-Transfer-Encoding', 'base64')
            part.add_header('Content-Disposition', 'attachment; filename="%s"' %
                            os.path.basename(zipfile))
            msg.attach(part)
    
        s = SMTP()
        try:
            s.connect(server)
        except:
            print("Could not connect to smtp server: " + server)
            return False
    
        if username:
            s.login(username, password)
        print("Sending the e-mail")
        s.sendmail(sender, recipients, msg.as_string())
        s.quit()
        return True
    
    def main():
        send_email()
    
    if __name__ == "__main__":
        main()
    

提交回复
热议问题