【问题标题】:Cannot send email containing Cyrillic无法发送包含西里尔字母的电子邮件
【发布时间】:2019-07-23 10:30:03
【问题描述】:

我对编码非常陌生,作为挑战,我尝试从网站上抓取天气数据,然后将这些数据发送到我的电子邮件。 我怀疑西里尔字母是电子邮件无法发送的原因。 我已经进行了一些测试,如果我的参数“主题”和“味精”通过了正常的拉丁语 邮件有效,但如果其中一个有任何非拉丁语,则邮件将无法通过。我对 unicode 的了解非常有限,我不知道为什么会导致错误

import smtplib
import config
import requests
from bs4 import BeautifulSoup


def weather():
    src = requests.get('https://www.sinoptik.bg/asenovgrad-bulgaria-100733618').text
    soup = BeautifulSoup(src, 'lxml')

    city_name = soup.find('h1').text
    current_temp = soup.find('span', class_='wfCurrentTemp').text
    feels_temp = soup.find('span', class_='wfCurrentFeelTemp').text
    weather_type = soup.find('strong').text
    a = f'{city_name}\nТемпературата вмомента е {current_temp}\n{feels_temp}C\nОчаква се предимно {weather_type} време.'
    return a


def send_email(subject, msg):
    try:
        server = smtplib.SMTP('smtp.gmail.com:587')
        server.ehlo()
        server.starttls()
        server.login(config.EMAIL_ADRESS, config.PASSWORD)
        message = 'Subject: {}\n\n{}'.format(subject, msg)
        server.sendmail(config.EMAIL_ADRESS, config.SEND_TO, message)
        server.quit()
        print('Success: Email sent!')
    except:
        print('Email failed to send.')


subject = 'Дневна прогноза за времето'
msg = weather()

send_email(subject, msg)

当我删除 try/except 我得到以下错误:

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

使用 .encode('utf-8) 我设法让电子邮件发送,但我收到了 ascii 字符。

b'\xd0\x90\xd1\x81\xd0\xb5\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xb3\xd1\x80\xd0\xb0\xd0\xb4\n\xd0\xa2\xd0\xb5\xd0\xbc\xd0\xbf\xd0\xb5\xd1\x80\xd0\xb0\xd1\x82\xd1\x83\xd1\x80\xd0\xb0\xd1\x82\xd0\xb0 \xd0\xb2\xd0\xbc\xd0\xbe\xd0\xbc\xd0\xb5\xd0\xbd\xd1\x82\xd0\xb0 \xd0\xb5 18\xc2\xb0C\n\xd0\xa3\xd1\x81\xd0\xb5\xd1\x89\xd0\xb0 \xd1\x81\xd0\xb5: 18\xc2\xb0C\n\xd0\x9e\xd1\x87\xd0\xb0\xd0\xba\xd0\xb2\xd0\xb0 \xd1\x81\xd0\xb5 \xd0\xbf\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb8\xd0\xbc\xd0\xbd\xd0\xbe \xd0\xa1\xd0\xbb\xd1\x8a\xd0\xbd\xd1\x87\xd0\xb5\xd0\xb2\xd0\xbe \xd0\xb2\xd1\x80\xd0\xb5\xd0\xbc\xd0\xb5.'

然后我尝试使用 .decode() 将其解码,但电子邮件无法再次使用?

【问题讨论】:

  • 如果您遇到任何错误,请在问题中提供这些作为代码块。您很可能需要在将字符串传递给电子邮件函数之前对其进行编码。您可以按照send_email(subject.encode(), msg) 的方式做一些事情。
  • 嗯,显而易见的解决方案是不要在您的电子邮件中使用醉酒的信件,但如果这不是一个选项,您可以尝试使用谷歌搜索 unicode-emails-in-python -.-
  • 您应该在服务器对象的 smtp_error 属性中从服务器获取错误消息
  • 我没有收到任何错误,因为我有(尝试:除外:)当我删除它时,我得到 UnicodeEncodeError: 'ascii' codec can't encode characters in position 9-14: ordinal not在范围内(128)

标签: python unicode ascii smtplib


【解决方案1】:

导入另一个模块似乎可以部分解决问题

from email.mime.text import MIMEText

然后更改以下内容:

message = 'Subject: {}\n\n{}'.format(subject, msg)
        server.sendmail(config.EMAIL_ADRESS, config.SEND_TO, message)

message = MIMEText('Subject: {}\n\n{}'.format(subject, msg))
server.sendmail(config.EMAIL_ADRESS, config.SEND_TO, message.as_string())

不幸的是,此更改影响了电子邮件的正文,“主题”不再作为一个,而是在电子邮件正文中,使我的“主题”为空。

【讨论】:

  • MIMEText 不是完整的 MIME 消息,只是 MIME 的一部分。您想从一条消息开始并填充它。
【解决方案2】:

电子邮件最初是严格的 7 位 ASCII,您必须使用 MIME 封装来正确包含任何其他类型的内容并正确添加元数据以识别其类型和编码。 email 库透明地为您执行此操作,并处理许多其他通过将字符串拼凑在一起很难或麻烦的细节(特别是如果您不太熟悉 RFC5322 和朋友的要求)。

from email.message import EmailMessage
import smtplib

msg = EmailMessage()
msg['Subject'] = 'Дневна прогноза за времето'
msg['From'] = me
msg['To'] = you
msg.set_content(weather())

server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
server.login(config.EMAIL_ADRESS, config.PASSWORD)

server.send_message(msg)
server.quit()

这几乎是https://docs.python.org/3/library/email.examples.html 中第一个适应您的情况的示例。

也许注意到email 库在 Python 3.6 中进行了大修;如果您需要支持较旧的版本,则上述某些内容可能需要稍作调整。一旦您知道要查找的内容,就应该不难找到示例。

【讨论】:

    猜你喜欢
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多