Как кодировать международные символы в именах получателей (НЕ адреса) с помощью smtplib.sendmail () в Python 3? - PullRequest
0 голосов
/ 06 октября 2019

Я использую стандартный вызов smtplib.sendmail () в моей программе на Python 3 для отправки электронных писем следующим образом:

smtp_session.sendmail('The Sender <sender@domain.com>', ['The ÅÄÖ Recipient <recipient@domain.com>'], 'Simple test body here')

Сеанс SMTP уже был успешно установлен до того, как эта строка кода былавыполняется, и он также всегда работает просто отлично, если в имени получателя нет «международных символов».

НО, как только я добавлю, например, «ÅÄÖ» в имя получателя (что даже просто8-битные символы ASCII, даже не «реальный юникод» или что-либо еще), как можно видеть выше, электронная почта просто исчезает и никогда не достигает отправителя, хотя ни методы, ни sendmail () не возвращают и не вызывают ошибки, ни что-либовнутри (я делал одношаговую отладку при этом).

Я точно знаю, что могу отправлять электронные письма с такими символами в именах получателей через тот же мой SMTP-сервер, используяобычная программа для работы с электронной почтой, такая как Thunderbird, поэтому я могу только предположить, что эта проблема связана с некоторой кодировкойr похоже?

Кроме того, решение также не должно относиться к этой mail_options=['SMTPUTF8'] штуке, потому что сервер просто отвечает, что не поддерживает это, если я пытаюсь его использовать (и опять же, электронные письма, использующиеэти точные имена получателей все еще могут быть отправлены через тот же SMTP-сервер с обычным почтовым клиентом, таким как Thunderbird).

Итак, есть ли какое-то простое решение, основанное на использовании некоторой кодировки, связанной с MIME, или аналогичнойстроки получателей, которые решат эту проблему, или как я могу отправить письмо из Python с таким именем получателя?

Ответы [ 2 ]

0 голосов
/ 07 октября 2019

Аргумент к smtplib.sendmail() не должен иметь удобочитаемых меток, только адрес конца.

smtp_session.sendmail('sender@domain.com', ['recipient@domain.com'],
    'Simple test body here')

Модуль email.headerregistry в Python 3.6 + имеет возможность дляизвлечение только конечной электронной почты путем разбивки структурированных заголовков на объекты с атрибутами.

from email.headerregistry import AddressHeader

hdr = dict()
AddressHeader.parse('To: The ÅÄÖ Recipient <recipient@domain.com>', hdr)
for grp in hdr['groups']:
    for addr in grp.addresses:
        print('{0}@{1}'.format(addr.username, addr.domain))

(я действительно надеюсь, что есть менее запутанный способ доступа к этой функции, но по крайней мере это дает ожидаемый результат.)

В текущем сообщении Python позаботится о правильной RFC2047-кодировке любых заголовков с содержимым Unicode (если вы используете правильные методы из библиотеки email для создания MIME-сообщения prop0er);но это чисто представление (RFC5322), а не транспорт (RFC5321). Таким образом, в самом сообщении вы можете увидеть

From: The Sender <sender@domain.com>
To: The =?utf-8?Q?=C3=85=C3=84=C3=96_Recipient?= <recipient@domain.com>

, хотя имейте в виду, что для содержимого сообщения не требуется фактического раскрытия заголовков отправителя или получателя транспорта. (Возможно, по касательной см. Заголовок «Кому:» для массового отправителя электронной почты )

0 голосов
/ 07 октября 2019

Символы в заголовках SMTP должны быть для печати ASCII, в числовом диапазоне 33-126 включительно . Если вам нужно представить символы за пределами этого диапазона в заголовке SMTP, вы должны использовать метод кодирования, определенный RFC 2231 (который является развитием более раннего метода, определенного RFC 2047 ). .

Исторически в Python вы использовали класс Header из модуля email.header для создания заголовков с соответствующей кодировкой. Это все еще доступно в Python 3, но в Python 3 более новая рекомендация - использовать класс EmailMessage из модуля email.message для создания всего сообщения и позволить ему позаботиться о кодировании любых заголовков, которыенуждается в особом лечении.

...