有没有一种在事先不知道文件类型的情况下使用 SMTP 在 python 中发送电子邮件附件的快速方法?

Is there a quick way to send email attachments in python using SMTP without knowing the file type in advance?

我正在开发一个 Python 程序,可以使用 SMTP 发送带附件的电子邮件。到目前为止,通过互联网搜索,我发现了两种将文件附加到 MIME 电子邮件的主要方法。一种方法是使用 MIMEBase class 并像这样附加文件(无论文件类型如何):

attach_file = open(attach_file_name, 'rb') # Open the file as binary mode
payload = MIMEBase('application', 'octate-stream')
payload.set_payload((attach_file).read())
encoders.encode_base64(payload) #encode the attachment
attach_file.close()
#add payload header with filename
payload.add_header('Content-Decomposition', "attachment; filename= %s" % attach_file_name)
msg.attach(payload)

这个方法的问题是我发现在许多电子邮件客户端(例如 Gmail)上,附件显示为“noname”并且不可预览(尽管您仍然可以通过下载和打开来查看它正确的程序)。

我遇到的第二种方法是将文件附加到与其类型相对应的子class,如下所示:

f=open(attach_file_name, 'rb')
img_data = f.read()
f.close()
image = MIMEImage(img_data, name=os.path.basename(attach_file_name))
msg.attach(image)

此示例适用于图片,并且可以在 Gmail 中正确显示,但不能用于发送其他类型的文件。如果我们想使用方法 2 发送文件,看起来我们需要先知道它的类型。有没有一种方法可以轻松确定与 MIME 相关的文件类型,以便代码可以即时执行此操作(无需枚举特定文件类型的所有不同扩展名)?或者有没有办法在不知道附件类型的情况下发送附件并正确显示?

SMTP 不关心附件包含什么。只需将其设为 application/octet-stream 并希望收件人知道如何处理它。但请确保您正确拼写了 MIME 类型。 (“八位字节”只是“8 位字节”的另一种说法。)

此外,Content-Decomposition 不是有效的 MIME header 名称;你想要 Content-Disposition.

这些可怕的拼写错误可能是您在某些客户中发现问题的原因。当您拼错关键技术关键字时,他们无法猜出您的意思。

更重要的是,您的两次尝试似乎都有 copy/pasted 几年前的电子邮件代码。当前的 Python 3.6+ email 库代码更具可读性和通用性。可能会扔掉你所有的东西,然后从 examples in the documentation.

重新开始

如果您可以正确 猜出您正在传输的文件的 MIME 类型,将该信息添加到 MIME header 中将会很有用;但是针对任意附件类型自动执行此操作不太可能有帮助。如果你的猜测逻辑猜错了,你只是通过声称你知道什么时候不知道而让事情变得更难。

所以,我不特别推荐尝试;但是如果您想自己验证这是徒劳的,请尝试 mimetypes.guess_type method from the standard library. 文档表明这仅包含对 collection 文件扩展名的固定猜测;更彻底的方法是使用文件的实际内容和 libmagic 或类似的方法来尝试识别它是什么。