使用Python发送带有文件附件的电子邮件所需的MIMEMultipart、MIMEText、MIMEBase和有效载荷。

43

在对MIME没有太多先前了解的情况下,我尝试学习如何编写Python脚本以发送带有文件附件的电子邮件。经过交叉参考Python文档、Stack Overflow问题和一般网络搜索,我最终采用了以下代码[1]并测试其可行。

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email import encoders

fromaddr = "YOUR EMAIL"
toaddr = "EMAIL ADDRESS YOU SEND TO"

msg = MIMEMultipart()

msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "SUBJECT OF THE EMAIL"

body = "TEXT YOU WANT TO SEND"

msg.attach(MIMEText(body, 'plain'))

filename = "NAME OF THE FILE WITH ITS EXTENSION"
attachment = open("PATH OF THE FILE", "rb")

part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

msg.attach(part)

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "YOUR PASSWORD")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
  1. I have a rough idea of how this script works now, and worked out the following workflow. Please let me know how accurate my flowchart(?) is.

     as.string()  
     |
     +------------MIMEMultipart  
                  |                                                |---content-type  
                  |                                   +---header---+---content disposition  
                  +----.attach()-----+----MIMEBase----|  
                                     |                +---payload (to be encoded in Base64)
                                     +----MIMEText
    
  2. How do I know when to use MIMEMultipart, MIMEText and MIMEBase? This seems like a complicated question, so maybe just offer some general rules-of-thumb to me?

  3. I read that MIME has a tree-like structure[2] , does that mean MIMEMultipart is always at the top?
  4. In the first code block, MIMEMultipart encodes ['From'], ['To'], and ['Subject'], but in the Python documentation, MIMEText can also be used to encode ['From'], ['To'], and ['Subject']. How to do I decide one to use?
  5. What exactly is a "payload"? Is it some content to be transported? If so, what kind of content does this include (I noticed that body text and attachment are treated as payloads)? I thought this would be an easy question but I just could not find a satisfying, reliable, and simple answer.
  6. Is is true that although MIME can attach file formats much simpler than just some texts, at the end all the encoding, header information, and payloads are all turned into strings so that they can be passed into .sendmail()?

[1]http://naelshiab.com/tutorial-send-email-python/
[2]http://blog.magiksys.net/generate-and-send-mail-with-python-tutorial


你好,我有一个问题,为什么['From']、['To']和['Subject']要用方括号括起来?这样做的必要性和目的是什么? - Mech_Saran
1个回答

35

电子邮件消息

一封电子邮件消息由头部(例如“发件人”,“收件人”,“主题”等)和正文组成(请参见RFC 822,第3.1节)。

默认情况下,消息的正文被视为纯ASCII文本。MIME(RFC 2045RFC 2046RFC 2047RFC 2048RFC 2049)定义了扩展,允许指定不同类型的电子邮件内容。

MIME非常有用的一点是可以指定Content-Type(例如text/htmlapplication/octet-stream)。

另一个有用的功能是可以创建具有多个部分的消息(例如,如果您想在HTML中同时包含HTML和图像)。这是通过指定multipart Content-Type(RFC 2046,第5.1节)来完成的。

多部分消息

如果一条消息具有multipart Content-Type,这意味着它由多个消息组成,每个消息都定义了自己的Content-Type(可以再次是multipart或其他内容类型)。在Python中,多部分消息由MIMEMultipart类表示。
因此,回答问题3:当使用MIMEMultipart时,它是一个树状结构,但如果仅使用MIMEText,则它不是一个树形结构。 问题4询问应该在哪个类上设置标题(“To”,“From”等) - 这是通过Message类完成的,但所有MIME类都继承自Message,因此可以在任何一个类上完成,但这些标题仅对多部分消息的根部分有意义。
换句话说,如果一条消息仅包含一个MIME部分,请在该部分上指定标题。如果它包含多个部分,则根部分是MIMEMultipart - 请在该部分上指定标题。 问题2“何时使用MIMEMultipart、MIMEText和MIMEBase”
  • MIMEBase只是一个基类。正如规范所说: "通常你不会专门创建MIMEBase的实例"
  • MIMEText用于文本(例如text/plaintext/html),如果整个消息是以文本格式编写的,或者其中一部分是。
  • MIMEMultipart用于表示"我有多个部分",然后列出这些部分——如果您有附件,则这样做,还可以提供相同内容的替代版本(例如纯文本版本加上HTML版本)

问题5 "什么是“有效载荷”?" - 这只是消息(或消息部分)的内容的花哨说法。

问题6在SMTP中只使用7位有限制。有关更多详细信息,请参见此答案

我没有完全理解问题1,但似乎图表大致正确。顺便说一句,我不会在此处使用MIMEBase,因为有MIMEApplication看起来更适合预期的目的。


首先感谢您在此帖子中分享的详细信息和澄清。我还不明白的是,当我有一个文本正文部分和一个HTML正文部分时,它们彼此不是替代品时,层次结构会是什么样子。例如,我有一个文本段落和一个HTML表格要写在电子邮件正文部分而不是作为附件。您能建议在这种情况下使用什么层次结构吗? - simi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接