【问题标题】:MIMEMultipart, MIMEText, MIMEBase, and payloads for sending email with file attachment in PythonMIMEMultipart、MIMEText、MIMEBase 和用于在 Python 中发送带有文件附件的电子邮件的有效负载
【发布时间】:2016-12-14 00:51:57
【问题描述】:

在没有太多 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. 我现在大致了解了这个脚本的工作原理,并制定了以下工作流程。请让我知道我的流程图(?)有多准确。

     as.string()  
     |
     +------------MIMEMultipart  
                  |                                                |---content-type  
                  |                                   +---header---+---content disposition  
                  +----.attach()-----+----MIMEBase----|  
                                     |                +---payload (to be encoded in Base64)
                                     +----MIMEText
    
  2. 我如何知道何时使用 MIMEMultipart、MIMEText 和 MIMEBase?这似乎是一个复杂的问题,所以也许只是向我提供一些一般的经验法则?

  3. 我读到 MIME 具有树状结构[2],这是否意味着 MIMEMultipart 始终位于顶部?
  4. 在第一个代码块中,MIMEMultipart 编码 ['From']、['To'] 和 ['Subject'],但在 Python 文档中,MIMEText 也可用于编码 ['From']、[ 'To'] 和 ['Subject']。我该如何决定使用一个?
  5. 究竟什么是“有效载荷”?是要传输的内容吗?如果是这样,这包括什么样的内容(我注意到正文和附件被视为有效负载)?我认为这将是一个简单的问题,但我找不到令人满意、可靠和简单的答案。
  6. 是真的,虽然 MIME 可以附加文件格式比只是一些文本简单得多,但最后所有的编码、标题信息和有效负载都变成了字符串,以便可以将它们传递给 .sendmail()?

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

【问题讨论】:

    标签: python email smtp mime smtplib


    【解决方案1】:

    电子邮件消息

    一封电子邮件由标题(例如“发件人”、“收件人”、“主题”等)和正文(参见RFC 822, section 3.1)组成。

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

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

    另一个有用的事情是您可以创建包含多个部分的消息(例如,如果您希望在 HTML 中同时包含 HTML 和图像)。这是通过指定 multipart Content-Type (RFC 2046, section 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 只是一个基类。正如specification 所说:“通常你不会专门创建MIMEBase 的实例”
    • MIMEText 用于文本(例如 text/plaintext/html),如果整个消息是文本格式,或者部分是文本格式。
    • MIMEMultipart 用于说“我有不止一个部分”,然后列出这些部分 - 如果你有附件,你这样做也是为了提供相同内容的替代版本(例如纯文本版本加上 HTML 版本)

    问题 5 “究竟什么是“有效负载”?” - 这只是消息内容(或消息部分)的一个花哨的词

    问题 6 在 SMTP 中只能使用 7 位是有限制的。详情请见this answer

    问题1我没完全看懂,不过好像图表差不多是对的。顺便说一句,我不会在这里使用MIMEBase,因为MIMEApplication 似乎更适合预期目的。

    【讨论】:

    • 嗨,首先感谢您在这篇文章中分享的详细信息和说明。我还不明白的是,当我有一个文本正文部分和一个 html 正文部分时,层次结构会是什么,它们不能相互替代。例如,我有一个带有 html 表格的文本段落,要写在电子邮件正文部分而不是作为附件。你能建议在这种情况下使用什么层次结构吗?
    猜你喜欢
    • 2023-03-27
    • 2014-11-09
    • 2017-02-04
    • 2018-07-24
    • 2019-11-21
    • 2020-09-16
    • 1970-01-01
    • 2015-09-09
    相关资源
    最近更新 更多