关于python:发送邮件时Ascii编码错误

Ascii encoding error during sending a mail

我不熟悉python,尝试使用poplib和smtplib接收和重新发送电子邮件:

1
2
3
4
5
6
7
8
9
    messages = [pop_conn.retr(i)[1] for i in range(1, mail_count + 1)]
    #decode messages
    messages = [[line.decode("utf-8") for line in message] for message in messages]
    # Concat messages
    messages = ["
"
.join(msg) for msg in messages]
    #...        
    for message in messages:
        smtp_conn.sendmail(args.address, args.target, message)

在调试器中,所有消息字符串看起来都不错,但在sendmail调用中出现以下错误:

1
msg = _fix_eols(msg).encode('ascii')

UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 17938: ordinal not in range(128)

我做错什么了?


似乎任何字符\xa0表示都没有ASCII表示。根据这个链接,\xa0是非中断空格的Unicode字符。

因为这实际上只是一个空格,所以您可以尝试替换字符串中的所有\xa0字符:

1
2
 messages = ["
"
.join(msg.replace(u'\xa0', u' ')) for msg in messages]

公平地说,空格和不间断空格的功能是不同的,因此,根据此字符在消息中出现的位置,在将不间断空格替换为常规空格后,输出可能略有不同。

另一种选择是忽略任何产生错误的字符。此解决方案不理想,因为您可能会丢失最终更改文本格式(或有时更改文本含义)的字符。将非中断空间替换为普通空间是明智的做法,不管怎样,但对于所有其他讨厌的字符:

1
msg.encode("ascii", errors="ignore")

或者,您可以执行msg.encode("ascii", errors="replace"),但这将用'?'替换这些字符。看起来不太好。


您试图将不在ASCII标准中的UTF-8字符编码为ASCII。A0是一个不间断的空间。如果这是唯一一个不可使用ASCII编码的字符,您可以用普通空格替换它:

1
spaced_message = message.replace("\x0a","")

否则,请查看https://en.wikipedia.org/wiki/unicode_and_email unicode_-support_in_-message_bodies

将字符串编码为utf-7(是的,7)通常有效,但在许多系统中,它被正式否决。UTF-8需要base64编码,这有点棘手。