27.07.2024

Python3 — Отправка почты с помощью библиотеки smtplib на кириллические домены

Понадобилось недавно наладить отправку электронной почты с сайта на django. Но оказалось все не так очевидно, как казалось в самом начале.

Я решил проверить на этом коде

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


def run():
    noreply = 'no**ly@промик.рф'
    smtp_host = 'smtp.yandex.ru'
    login, password = noreply, '***'
    recipients_emails = [noreply]

    msg = MIMEText('Hello!', 'plain', 'utf-8')
    msg['Subject'] = Header('Subject', 'utf-8')
    msg['From'] = login
    msg['To'] = ", ".join(recipients_emails)

    s = smtplib.SMTP(smtp_host, 587, timeout=10)
  

    try:
        s.starttls()
        s.login(login, password)
        s.sendmail(msg['From'], recipients_emails, msg.as_string())
    finally:
        s.quit()

И получил ошибку:

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

Тут-то я сразу понял, что дело в моем кириллическом домене и отправку нужно совершать на адрес в punycode. Мои изыскания привели меня к методу encode с кодировкой ‘idna’.

В использовании есть небольшие нюансы. Этот метод не стоит применить ко всему адресу почты, если в нем только кириллический домен. Вот, смотрите, что получилось:

>>> noreply = 'no**ly@промик.рф'
>>> print(noreply.encode('idna').decode('utf-8'))
xn--no**ly@-b9guuxmo.xn--p1ai

В части адреса явно закралось что-то лишнее. Поэтому я решил написать небольшую функцию, которая кодирует адрес почты в punycode:

>>> noreply = 'no**ly@промик.рф'
>>> def mail2punycode(mail):
...     import re
... 
...     return "%s%s" % (re.sub(r'@.*$', '@', mail), mail.split('@')[1].encode('idna').decode('utf-8'))
... 
>>> print(mail2punycode(noreply))
no**ly@xn--h1aeeheg.xn--p1ai

В итоге, почта стала отправляться без каких-либо проблем.

Кстати, мы с девушкой запустили новый проект — путеводитель по скидкам промик.рф, заходите — будем рады. Сайт написан на django — для меня это новшество и, если честно, я просто кайфую от использования django 🙂

Добавить комментарий