为什么这个Python程序在用utf-8编码时发送空电子邮件?

时间:2018-02-01 04:52:08

标签: python encoding utf-8

在编码msg变量之前,我收到了这个错误:

  

UnicodeEncodeError:'ascii'编解码器无法编码字符'\ xfc'   位置4:序数不在范围内(128)

所以我做了一些研究,最后对变量进行了编码:

msg = (os.path.splitext(base)[0] + ': ' + text).encode('utf-8')
server.sendmail('...@gmail.com', '...@gmail.com', msg)

以下是请求中的其余代码:

def remind_me(path, time, day_freq):

for filename in glob.glob(os.path.join(path, '*.docx')):
    # file_count = sum(len(files))
    # random_file = random.randint(0, file_number-1)
    doc = docx.Document(filename)
    p_number = len(doc.paragraphs)

    text = ''
    while text == '':
        rp = random.randint(0, p_number-1) # random paragraph number
        text = doc.paragraphs[rp].text # gives the entire text in the paragraph

    base = os.path.basename(filename)
    print(os.path.splitext(base)[0] + ': ' + text)
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login('...@gmail.com', 'password')
    msg = (os.path.splitext(base)[0] + ': ' + text).encode('utf-8')
    server.sendmail('...@gmail.com', '...@gmail.com', msg)
    server.quit()

现在,它发送空电子邮件而不是传递邮件。它没有返回吗?如果是这样,为什么?

注意:Word文档包含一些字符,如ş,ö,ğ,ç。

1 个答案:

答案 0 :(得分:1)

msg的{​​{1}}参数应该是包含有效RFC5322消息的smtplib.sendmail序列。取一个字符串并将其编码为UTF-8是不太可能产生一个字符串(如果它已经是ASCII,则编码它没有任何用处;如果不是,那么你最有可能做错了)。

为了解释为什么不太可行,请让我提供一些背景资料。在MIME消息中传输非ASCII字符串的方式取决于消息结构中字符串的上下文。这是一个简单的消息,其中“Hëlló”一词嵌入在三个不同的上下文中,需要不同的编码,其中没有一个能够轻松接受原始的UTF-8。

bytes

最近的扩展允许符合要求的系统之间的部分消息包含裸UTF-8(即使在标题中!)但我强烈怀疑这不是你所处的场景。也许切向看也{ {3}}

回到您的代码,我假设如果From: me <sender@example.org> To: you <recipient@example.net> Subject: =?utf-8?Q?H=C3=ABll=C3=B3?= (RFC2047 encoding) MIME-Version: 1.0 Content-type: multipart/mixed; boundary="fooo" --fooo Content-type: text/plain; charset="utf-8" Content-transfer-encoding: quoted-printable H=C3=ABll=C3=B3 is bare quoted-printable (RFC2045), like what you see in the Subject header but without the RFC2047 wrapping. --fooo Content-type: application/octet-stream; filename*=UTF-8''H%C3%ABll%C3%B3 This is a file whose name has been RFC2231-encoded. --fooo-- 巧合地也是您想要添加到邮件开头的标题的名称,那么它可以正常工作,{{1}包含一个包含其余消息的字符串。您没有显示足够的代码来明智地推断这一点,但似乎不太可能。如果base已经包含有效的MIME消息,则将其编码为UTF-8不应该是必要的或有用的(但是当你得到编码错误时它显然没有)。

我们假设text包含textbase因此被定义:

Subject

现在,连接text实际上产生了一个类似于上面的消息(虽然我重新排序了一些标题,以便text='''=?utf-8?B?H=C3=ABll=C3=B3?= (RFC2047 encoding) MIME-Version: 1.0 Content-type: multipart/mixed; boundary="fooo" ....''' 首先放置这个场景)但是再次,我想这不是事情的实际情况在你的代码中。

如果您的目标是将提取的文本作为电子邮件正文发送,那么这样做的方式大致是

base + ': ' + text

Subject:调用构建一个电子邮件对象,其中包含发件人,主题,收件人列表和正文的空间;它的from email.mime.text import MIMEText body_text = os.path.splitext(base)[0] + ': ' + text sender = 'you@example.net' recipient = 'me@example.org' message = MIMEText(body_text) message[subject] = 'Extracted text' message[from] = sender message[to] = recipient server = smtplib.SMTP('smtp.gmail.com', 587) # ... smtplib setup, login, authenticate? server.send_message(message) 方法返回一个表示,该表示看起来与上面的 ad hoc 示例消息大致相似(虽然更简单,没有多部分结构),适合通过SMTP进行传输。它透明地处理正确的字符集并为非ASCII标题元素和正文部分(有效负载)应用合适的内容传输编码。

Python的标准库包含相当低级的函数,因此您必须知道一点点才能正确连接所有部分。有第三方图书馆隐藏了一些这些细节;但是你会用电子邮件来评论任何一个主题和一个主体,当然还有发送者和接收者。