发送电子邮件时,MIMEText UTF-8编码问题的解决方法

19

这是我发送电子邮件的代码片段:

servidor = smtplib.SMTP()
servidor.connect(HOST, PORT)
servidor.login(user, usenha)
assunto = str(self.lineEdit.text())
para = str(globe_email)             
texto = self.textEdit.toPlainText()
textos = str(texto)
corpo = MIMEText(textos.encode('utf-8'), _charset='utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = assunto
servidor.sendmail(user, [para], corpo.as_string())

除了主题部分外,一切都正常。当我尝试发送包含特殊字符的字符串(例如“ação”)时,它会引发此错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)

我该如何使用MIMEText发送包含特殊字符的邮件主题?
2个回答

47

在 Python 3 中,似乎需要使用 Header 对象来将 Subject 编码为 utf-8:

# -*- coding: utf-8 -*-
from email.mime.text import MIMEText
from email.header import Header
s = 'ação'
m = MIMEText(s, 'plain', 'utf-8')
m['Subject'] = Header(s, 'utf-8')
print(repr(m.as_string()))

输出:

'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: base64\nSubject: =?utf-8?b?YcOnw6Nv?=\n\nYcOnw6Nv\n

因此,原始脚本将变为:

servidor = smtplib.SMTP()
servidor.connect(HOST, PORT)
servidor.login(user, usenha)
assunto = str(self.lineEdit.text())
para = str(globe_email)             
texto = str(self.textEdit.toPlainText())
corpo = MIMEText(texto, 'plain', 'utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = Header(assunto, 'utf-8')
servidor.sendmail(user, [para], corpo.as_string())

似乎是这样?文档中有说明:https://docs.python.org/2/library/email.header.html - Al Martins
1
@AlMartins 是的,“似乎”是这样。我刚用Python-3.2.6、Python-3.3.0和Python-3.8.6进行了测试,无论是否使用Header对象,我都得到了完全相同的输出。这可能是由于compat32造成的。据推测,OP使用的是早期版本的Python3,其行为不同。因此,当前的文档似乎有些误导,因为并不一定需要使用Header对象。然而,为了向后兼容,最好继续使用它。 - ekhumoro

1

我已经改进了连接服务器和登录的其他方式,因为之前的方式在应用程序进行身份验证时出现了问题,而且人们可以看到应该使用的所有库。

from email.mime.text import MIMEText
from email.header import Header
import smtplib

user='email1@teste.com'
pwd='password'
server = smtplib.SMTP('smtp.office365.com', 587) #it works with outlook
server.ehlo()
server.starttls()
server.login(user, pwd)
assunto = 'Teste'
para = 'email2@teste.com'
texto = 'Niterói é uma cidade incrível '
corpo = MIMEText(texto, 'plain', 'utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = Header(assunto, 'utf-8')
try:
    server.sendmail(user, [para], corpo.as_string())
    print('email was sent')
except:
    print('error')
server.quit()

谢谢你的回答,但你能否详细解释一下吗?请查看如何撰写好的答案? - abestrad
在使用Flask时,Python 3不成功。html.encode('utf-8')有效。 - Al Martins

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