在Python中使用非ASCII字符编码电子邮件主题(SMTP)

20

我正在使用Python模块MimeWriter构造一封邮件,并使用smtplib发送。构造的邮件内容如下:

file msg.txt:
-----------------------
Content-Type: multipart/mixed;
from: me<me@abc.com>
to: me@abc.com
subject: 主題

Content-Type: text/plain;charset=utf-8

主題

我使用以下代码发送邮件:

import smtplib
s=smtplib.SMTP('smtp.abc.com')
toList = ['me@abc.com']
f=open('msg.txt') #above msg in msg.txt file
msg=f.read()
f.close()
s.sendmail('me@abc.com',toList,msg)

我可以正确获取电子邮件正文,但主题不正确。

subject: some junk characters

主題           <- body is correct.
请建议?是否有办法指定用于主题的解码方式,就像为正文指定的那样。我如何正确地解码主题?

1
在发布问题后,中文字符出现了乱码。 - Rakesh
3个回答

36

来自http://docs.python.org/library/email.header.html

from email.message import Message
from email.header import Header
msg = Message()
msg['Subject'] = Header('主題', 'utf-8')
print msg.as_string()

主题: =?utf-8?b?5Li76aGM?=

更简单:

from email.header import Header
print Header('主題', 'utf-8').encode()

你可以使用补码解码进行如下操作:

as complement decode may made with:

from email.header import decode_header
a = decode_header("""=?utf-8?b?5Li76aGM?=""")[0]
print(a[0].decode(a[1]))

参考: Python - email header decoding UTF-8


1
请注意,此处使用的是 email.message.Message API,该API已在Python 3.6中被 email.message.EmailMessage 取代。使用新的API时,您必须分配一个字符串:msg['Subject'] = 'unicode string',因为不支持分配Header对象。根据我的经验,在3.7.3版本中,“传统”的API效果更好 - 在3.8中修复了一些编码错误。 - Nickolay
感谢您的提醒。 - Sérgio

8
主题作为SMTP头传输,必须是仅限ASCII。为了支持主题中的编码,您需要在主题前缀中加入所需的编码方式。在您的情况下,我建议使用?UTF-8?B?前缀,这意味着 UTF-8Base64编码。
换句话说,我认为您的主题头应该大致如下:
Subject: =?UTF-8?B?JiMyMDAyNzsmIzM4OTg4Ow=?=

在PHP中,您可以这样做:

// Convert subject to base64
$subject_base64 = base64_encode($subject);
fwrite($smtp, "Subject: =?UTF-8?B?{$subject_base64}?=\r\n");

在Python中:
import base64
subject_base64 = base64.encodestring(subject).strip()
subject_line = "Subject: =?UTF-8?B?%s?=" % subject_base64

1
我会尝试这个,与此同时是否有任何Python API可以将其转换为上述格式。即根据所需的编码自动追加字符。 - Rakesh
1
我不确定 - 我只记得之前折腾这个问题时的那一部分。这个答案似乎表明,如果你使用MIMEMultipart类而不是MimeWriter,就可以正确地完成它。 - AHM
2
你应该在这里查找如何生成国际化标题的相关信息:http://docs.python.org/library/email.header.html - mata

1
简而言之,如果您使用EmailMessage API,您应该像这样编写代码:
from email.message import EmailMessage
from email.header import Header
msg = EmailMessage()
msg['Subject'] = Header('主題', 'utf-8').encode()

@Sérgio的回答不能在EmailMessage API中使用,因为只有字符串对象可以分配给EmailMessage()["Subject"],而不是email.header.Header对象。


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