Документация Python неофициальный перевод
Содержание страницы

smtplib – клиент протокола SMTPsmtplib – SMTP protocol client

Исходный код: Lib/smtplib.py


Модуль smtplib определяет объект сессии SMTP-клиента, который можно использовать для отправки почты на любую машину в Интернете с демоном, прослушивающим SMTP или ESMTP. Подробнее о работе SMTP и ESMTP см. в RFC 821 (Простой протокол передачи почты) и RFC 1869 (Расширения службы SMTP).

class smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)

Экземпляр SMTP инкапсулирует SMTP-соединение. Он содержит методы, поддерживающие полный набор операций SMTP и ESMTP. Если указаны необязательные параметры host и port, метод SMTP connect() вызывается с этими параметрами во время инициализации. Если задан, local_hostname используется как полное доменное имя локального хоста в команде HELO/EHLO. В противном случае локальное имя хоста находится с помощью socket.getfqdn(). Если вызов connect() возвращает что-то, отличное от кода успеха, генерируется исключение SMTPConnectError. Необязательный параметр timeout задаёт тайм-аут в секундах для блокирующих операций, таких как попытка соединения (если не указан, используется глобальный тайм-аут по умолчанию). Если тайм-аут истекает, возбуждается socket.timeout. Необязательный параметр source_address позволяет выполнить привязку к определённому исходному адресу на машине с несколькими сетевыми интерфейсами и/или к определённому исходному TCP-порту. Он принимает кортеж из двух элементов (host, port), к которому сокет привязывается как к своему исходному адресу перед установкой соединения. Если параметр опущен (или host и port равны '' и/или 0 соответственно), будет использовано поведение ОС по умолчанию.

Для обычного использования достаточно методов инициализации/подключения, sendmail() и SMTP.quit(). Пример приведен ниже.

Класс SMTP поддерживает оператор with. При таком использовании команда SMTP QUIT отправляется автоматически при выходе из оператора with. Например:

>>> from smtplib import SMTP
>>> with SMTP("domain.org") as smtp:
...     smtp.noop()
...
(250, b'Ok')
>>>

Все команды вызывают событие аудита smtplib.SMTP.send с аргументами self и data, где data – это байты, которые будут отправлены удалённому хосту.

Изменено в версии 3.3: Добавлена поддержка оператора with.

Изменено в версии 3.3: добавлен аргумент source_address.

Новое в версии 3.5: Теперь поддерживается расширение SMTPUTF8 (RFC 6531).

Изменено в версии 3.9: Если параметр timeout установлен в ноль, будет возбуждено ValueError, чтобы предотвратить создание неблокирующего сокета.

class smtplib.SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None, [timeout, ]context=None, source_address=None)

Экземпляр SMTP_SSL ведёт себя точно так же, как экземпляры SMTP. SMTP_SSL следует использовать в ситуациях, когда SSL требуется с самого начала соединения и использование starttls() неуместно. Если host не указан, используется локальный хост. Если port равен нулю, используется стандартный порт SMTP-over-SSL (465). Необязательные аргументы local_hostname, timeout и source_address имеют те же значения, что и в классе SMTP. context, также необязательный, может содержать SSLContext и позволяет настраивать различные аспекты защищённого соединения. Пожалуйста, прочитайте Рекомендации по безопасности для получения лучших практик.

файл ключа и файл сертификата – устаревшая альтернатива контексту, и могут указывать на файл закрытого ключа и цепочки сертификатов в формате PEM для SSL-соединения.

Изменено в версии 3.3: был добавлен параметр context.

Изменено в версии 3.3: добавлен аргумент source_address.

Изменено в версии 3.4: Теперь класс поддерживает проверку имени хоста с помощью ssl.SSLContext.check_hostname и Server Name Indication (см. ssl.HAS_SNI).

Устарело с версии 3.6: keyfile и certfile устарели в пользу context. Вместо них используйте ssl.SSLContext.load_cert_chain(), или позвольте ssl.create_default_context() выбрать доверенные сертификаты ЦС системы.

Изменено в версии 3.9: Если параметр timeout установлен в ноль, будет возбуждено ValueError, чтобы предотвратить создание неблокирующего сокета.

class smtplib.LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None[, timeout])

Протокол LMTP, очень похожий на ESMTP, во многом основан на\nстандартном SMTP-клиенте. Для LMTP обычно используются Unix-сокеты, поэтому наш\nметод connect() должен поддерживать как обычный сервер host:port, так и Unix-сокеты.\nНеобязательные аргументы local_hostname и source_address имеют тот же\nсмысл, что и в классе SMTP. Чтобы указать Unix-сокет, необходимо использовать абсолютный путь для host, начинающийся с '/'.

Поддерживается аутентификация с использованием обычного механизма SMTP. При использовании Unix-сокета LMTP обычно не поддерживает и не требует аутентификации, но возможны исключения.

Изменено в версии 3.9: Добавлен необязательный параметр timeout.

Также определен неплохой набор исключений:

exception smtplib.SMTPException

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

Изменено в версии 3.4: SMTPException стал подклассом OSError

exception smtplib.SMTPServerDisconnected

Это исключение возбуждается, когда сервер неожиданно отключается или когда предпринимается попытка использовать экземпляр SMTP до подключения к серверу.

exception smtplib.SMTPResponseException

Базовый класс для всех исключений, содержащих код ошибки SMTP. Эти исключения генерируются в некоторых случаях, когда SMTP-сервер возвращает код ошибки. Код ошибки хранится в атрибуте smtp_code исключения, а атрибут smtp_error содержит сообщение об ошибке.

exception smtplib.SMTPSenderRefused

Адрес отправителя отклонен. В дополнение к атрибутам, задаваемым для всех исключений SMTPResponseException, здесь атрибут 'sender' устанавливается в строку, которую отклонил SMTP-сервер.

exception smtplib.SMTPRecipientsRefused

Все адреса получателей отклонены. Ошибки для каждого получателя доступны через атрибут recipients, который представляет собой словарь точно такого же типа, какой возвращает SMTP.sendmail().

exception smtplib.SMTPDataError

Сервер SMTP отказался принимать данные сообщения.

exception smtplib.SMTPConnectError

Произошла ошибка при установке соединения с сервером.

exception smtplib.SMTPHeloError

Сервер отклонил наше сообщение HELO.

exception smtplib.SMTPNotSupportedError

Запрошенная команда или опция не поддерживается сервером.

Новое в версии 3.5.

exception smtplib.SMTPAuthenticationError

Произошла ошибка аутентификации SMTP. Скорее всего, сервер не принял предоставленную комбинацию имени пользователя и пароля.

См. также

RFC 821 – Простой протокол передачи почты

Определение протокола SMTP. Этот документ описывает модель, порядок работы и детали протокола SMTP.

RFC 1869 – Расширения службы SMTP

Определение расширений ESMTP для SMTP. Описывается инфраструктура для расширения SMTP новыми командами, динамическое обнаружение команд, предоставляемых сервером, и определяются несколько дополнительных команд.

Объекты SMTPSMTP Objects

Экземпляр SMTP имеет следующие методы:

SMTP.set_debuglevel(level)

Устанавливает уровень отладочного вывода. Значение 1 или True для параметра level приводит к выводу отладочных сообщений о соединении и обо всех сообщениях, отправленных на сервер и полученных от него. Значение 2 для level добавляет к этим сообщениям временные метки.

Изменено в версии 3.5: Добавлен отладочный уровень 2.

SMTP.docmd(cmd, args='')

Отправляет команду cmd серверу. Необязательный аргумент args просто дописывается к команде через пробел.

Возвращает кортеж из двух элементов: числового кода ответа и собственно строки ответа (многострочные ответы объединяются в одну длинную строку).

При обычной работе нет необходимости явно вызывать этот метод. Он используется для реализации других методов и может быть полезен при тестировании частных расширений.

Если соединение с сервером потеряно во время ожидания ответа, будет возбуждено SMTPServerDisconnected.

SMTP.connect(host='localhost', port=0)

Подключается к хосту на указанном порту. По умолчанию подключается к локальному хосту на стандартном порту SMTP (25). Если имя хоста заканчивается на двоеточие (':'), за которым следует число, этот суффикс отбрасывается, а число интерпретируется как номер порта для использования. Этот метод автоматически вызывается конструктором, если хост указан при создании экземпляра. Возвращает кортеж из двух элементов: код ответа и сообщение, отправленное сервером в своём ответе на подключение.

Вызывает событие аудита smtplib.connect с аргументами self, host, port.

SMTP.helo(name='')

Идентифицирует себя перед SMTP-сервером с помощью HELO. Аргумент hostname по умолчанию равен полному доменному имени локального хоста. Сообщение, возвращённое сервером, сохраняется в атрибуте helo_resp объекта.

При обычной работе нет необходимости явно вызывать этот метод. Он будет неявно вызван sendmail() при необходимости.

SMTP.ehlo(name='')

Идентификация на ESMTP-сервере выполняется с помощью EHLO. Аргумент hostname по умолчанию равен полному доменному имени локального хоста. Ответ проверяется на наличие опции ESMTP, и они сохраняются для использования has_extn(). Также устанавливаются несколько информационных атрибутов: сообщение, возвращённое сервером, сохраняется как атрибут ehlo_resp; does_esmtp устанавливается в true или false в зависимости от того, поддерживает ли сервер ESMTP; а esmtp_features будет словарём, содержащим имена расширений службы SMTP, которые поддерживает этот сервер, и их параметры (если они есть).

Если не требуется использовать has_extn() перед отправкой почты, явно вызывать этот метод необязательно. Он будет неявно вызван методом sendmail() при необходимости.

SMTP.ehlo_or_helo_if_needed()

Этот метод вызывает ehlo() и/или helo(), если в течение этого сеанса ещё не было выполнено команды EHLO или HELO. Сначала он пробует ESMTP EHLO.

SMTPHeloError

Сервер некорректно ответил на приветствие HELO.

SMTP.has_extn(name)

Возвращает True, если name присутствует в наборе расширений SMTP-сервиса, возвращённых сервером, и False в противном случае. Регистр игнорируется.

SMTP.verify(address)

Проверяет корректность адреса на этом сервере с помощью SMTP VRFY. Возвращает кортеж, состоящий из кода 250 и полного адреса RFC 822 (включая имя человека), если адрес пользователя действителен. В противном случае возвращает код ошибки SMTP 400 или больше и строку ошибки.

Примечание

Многие сайты отключают SMTP VRFY, чтобы помешать спамерам.

SMTP.login(user, password, *, initial_response_ok=True)

Выполняет вход на SMTP-сервер, требующий аутентификации. Аргументами являются имя пользователя и пароль для аутентификации. Если в течение этого сеанса ещё не было выполнено команды EHLO или HELO, этот метод сначала пробует ESMTP EHLO. Этот метод завершается нормально, если аутентификация прошла успешно, или может возбудить следующие исключения:

SMTPHeloError

Сервер некорректно ответил на приветствие HELO.

SMTPAuthenticationError

Сервер не принял комбинацию имя пользователя/пароль.

SMTPNotSupportedError

Команда AUTH не поддерживается сервером.

SMTPException

Не найден подходящий метод аутентификации.

Каждый из методов аутентификации, поддерживаемых smtplib, перебирается по очереди, если сервер объявляет о их поддержке. Список поддерживаемых методов аутентификации см. в auth(). Параметр initial_response_ok передаётся в auth().

Необязательный именованный аргумент initial_response_ok определяет, можно ли для методов аутентификации, которые это поддерживают, отправлять «начальный ответ» (initial response), как указано в RFC 4954, вместе с командой AUTH, а не требовать запроса/ответа (challenge/response).

Изменено в версии 3.5: SMTPNotSupportedError может быть возбуждено, и добавлен параметр initial_response_ok.

SMTP.auth(mechanism, authobject, *, initial_response_ok=True)

Отправляет команду SMTP AUTH для указанного механизма аутентификации mechanism и обрабатывает ответ на запрос (challenge response) через authobject.

mechanism указывает, какой механизм аутентификации будет использоваться в качестве аргумента команды AUTH; допустимые значения перечислены в элементе auth словаря esmtp_features.

authobject должен быть вызываемым объектом, принимающим один необязательный аргумент:

data = authobject(challenge=None)

Если необязательный именованный аргумент initial_response_ok равен true, сначала вызывается authobject() без аргументов. Он может вернуть «начальный ответ» RFC 4954 в виде ASCII str, который будет закодирован и отправлен с командой AUTH, как описано ниже. Если authobject() не поддерживает начальный ответ (например, потому что требует запроса), он должен вернуть None при вызове с challenge=None. Если initial_response_ok равен false, то authobject() не будет сначала вызываться с None.

Если проверка начального ответа возвращает None или если initial_response_ok равен false, вызывается authobject() для обработки ответа на запрос сервера; аргумент challenge, который ему передаётся, будет bytes. Он должен вернуть ASCII str data, который будет закодирован в base64 и отправлен на сервер.

Класс SMTP предоставляет authobjects для механизмов CRAM-MD5, PLAIN и LOGIN; они называются SMTP.auth_cram_md5, SMTP.auth_plain и SMTP.auth_login соответственно. Все они требуют, чтобы свойства user и password экземпляра SMTP были установлены в соответствующие значения.

Пользовательскому коду обычно не нужно вызывать auth напрямую; вместо этого можно вызвать метод login(), который переберёт каждый из вышеперечисленных механизмов по порядку. auth предоставляется для упрощения реализации методов аутентификации, не поддерживаемых (пока) напрямую smtplib.

Новое в версии 3.5.

SMTP.starttls(keyfile=None, certfile=None, context=None)

Переводит SMTP-соединение в режим TLS (безопасность транспортного уровня). Все последующие SMTP-команды будут зашифрованы. После этого следует снова вызвать ehlo().

Если указаны keyfile и certfile, они используются для создания ssl.SSLContext.

Необязательный параметр context – это объект ssl.SSLContext; это альтернатива использованию keyfile и certfile, и если он указан, то keyfile и certfile должны быть None.

Если в течение этого сеанса ещё не выполнялась команда EHLO или HELO, метод сначала пытается выполнить ESMTP EHLO.

Устарело с версии 3.6: keyfile и certfile устарели в пользу context. Вместо них используйте ssl.SSLContext.load_cert_chain(), или позвольте ssl.create_default_context() выбрать доверенные сертификаты ЦС системы.

SMTPHeloError

Сервер некорректно ответил на приветствие HELO.

SMTPNotSupportedError

Сервер не поддерживает расширение STARTTLS.

RuntimeError

Интерпретатор Python не поддерживает SSL/TLS.

Изменено в версии 3.3: был добавлен параметр context.

Изменено в версии 3.4: Теперь метод поддерживает проверку имени хоста с помощью SSLContext.check_hostname и Server Name Indicator (см. HAS_SNI).

Изменено в версии 3.5: Исключение, возбуждаемое при отсутствии поддержки STARTTLS, теперь является подклассом SMTPNotSupportedError вместо базового SMTPException.

SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())

Отправляет почту. Обязательными аргументами являются строка обратного адреса RFC 822, список строк адресов получателей RFC 822 (простая строка будет рассматриваться как список с одним адресом) и строка сообщения. Вызывающий может передать список параметров ESMTP (например, 8bitmime) для использования в командах MAIL FROM в качестве mail_options. Параметры ESMTP (например, команды DSN), которые должны использоваться со всеми командами RCPT, могут быть переданы как rcpt_options. (Если необходимо использовать разные параметры ESMTP для разных получателей, нужно использовать низкоуровневые методы, такие как mail(), rcpt() и data(), для отправки сообщения.)

Примечание

Параметры from_addr и to_addrs используются для построения конверта сообщения, используемого транспортными агентами. sendmail никак не изменяет заголовки сообщения.

msg может быть строкой, содержащей символы из диапазона ASCII, или байтовой строкой. Строка кодируется в байты с помощью кодека ascii, а одиночные символы \r и \n преобразуются в символы \r\n. Байтовая строка не изменяется.

Если в течение этого сеанса ещё не выполнялась команда EHLO или HELO, данный метод сначала пытается выполнить ESMTP EHLO. Если сервер поддерживает ESMTP, ему будут переданы размер сообщения и каждая из указанных опций (если опция присутствует в наборе возможностей, объявленных сервером). Если EHLO не удаётся, будет выполнена попытка HELO и ESMTP-опции будут подавлены.

Метод завершается нормально, если почта принята хотя бы одним получателем. В противном случае возбуждается исключение. То есть, если метод не возбуждает исключение, значит, кто-то должен получить ваше письмо. Если метод не возбуждает исключение, он возвращает словарь с одной записью для каждого получателя, которому было отказано. Каждая запись содержит кортеж из кода ошибки SMTP и соответствующего сообщения об ошибке, отправленного сервером.

Если SMTPUTF8 включён в mail_options и сервер это поддерживает, from_addr и to_addrs могут содержать символы, не входящие в ASCII.

Этот метод может возбуждать следующие исключения:

SMTPRecipientsRefused

Все получатели были отклонены. Почта не была доставлена. Атрибут recipients объекта исключения представляет собой словарь с информацией об отклонённых получателях (такой же, как возвращается, когда хотя бы один получатель был принят).

SMTPHeloError

Сервер некорректно ответил на приветствие HELO.

SMTPSenderRefused

Сервер не принял адрес from_addr.

SMTPDataError

Сервер ответил неожиданным кодом ошибки (не связанным с отказом отдельному получателю).

SMTPNotSupportedError

Параметр SMTPUTF8 был указан в mail_options, но не поддерживается сервером.

Если не указано иное, соединение остаётся открытым даже после возбуждения исключения.

Изменено в версии 3.2: msg может быть байтовой строкой.

Изменено в версии 3.5: Добавлена поддержка SMTPUTF8, и может возбуждаться SMTPNotSupportedError, если указан SMTPUTF8, но сервер его не поддерживает.

SMTP.send_message(msg, from_addr=None, to_addrs=None, mail_options=(), rcpt_options=())

Это удобный метод для вызова sendmail() с сообщением, представленным объектом email.message.Message. Аргументы имеют тот же смысл, что и для sendmail(), за исключением того, что msg является объектом Message.

Если from_addr равно None или to_addrs равно None, send_message заполняет эти аргументы адресами, извлечёнными из заголовков msg в соответствии с RFC 5322: from_addr устанавливается в поле Sender, если оно присутствует, иначе – в поле From. to_addrs объединяет значения (если они есть) полей To, Cc и Bcc из msg. Если в сообщении присутствует ровно один набор заголовков Resent-*, обычные заголовки игнорируются, а используются заголовки Resent-*. Если сообщение содержит более одного набора заголовков Resent-*, возбуждается ValueError, поскольку нет способа однозначно определить самый последний набор заголовков Resent-.

send_message сериализует msg с помощью\nBytesGenerator, используя \r\n в качестве linesep, и\nвызывает sendmail() для передачи результирующего сообщения. Независимо от\nзначений from_addr и to_addrs, send_message не передаёт никакие\nзаголовки Bcc или Resent-Bcc, которые могут присутствовать\nв msg. Если какой-либо из адресов в from_addr и to_addrs содержит\nсимволы, отличные от ASCII, и сервер не объявляет поддержку SMTPUTF8,\nвозникает ошибка SMTPNotSupported. В противном случае Message\nсериализуется с клоном своего policy, у которого\nатрибут utf8 установлен в True, а\nSMTPUTF8 и BODY=8BITMIME добавляются к mail_options.

Новое в версии 3.2.

Новое в версии 3.5: Поддержка интернационализированных адресов (SMTPUTF8).

SMTP.quit()

Завершает сеанс SMTP и закрывает соединение. Возвращает результат команды SMTP QUIT.

Также поддерживаются низкоуровневые методы, соответствующие стандартным командам SMTP/ESMTP HELP, RSET, NOOP, MAIL, RCPT и DATA. Обычно их не нужно вызывать напрямую, поэтому они не документированы здесь. Подробнее см. в коде модуля.

Пример SMTPSMTP Example

Этот пример запрашивает у пользователя адреса, необходимые в конверте сообщения (адреса ‘To’\nи ‘From’), а также само сообщение для отправки. Обратите внимание, что заголовки,\nкоторые должны быть включены в сообщение, должны быть включены в сообщение при вводе; этот\nпример не выполняет никакой обработки заголовков RFC 822. В частности,\nадреса ‘To’ и ‘From’ должны быть явно включены в заголовки сообщения.

import smtplib

def prompt(prompt):
    return input(prompt).strip()

fromaddr = prompt("From: ")
toaddrs  = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")

# Добавьте заголовки From: и To: в начало!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
       % (fromaddr, ", ".join(toaddrs)))
while True:
    try:
        line = input()
    except EOFError:
        break
    if not line:
        break
    msg = msg + line

print("Message length is", len(msg))

server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Примечание

В общем случае рекомендуется использовать возможности пакета email для создания сообщения электронной почты, которое затем можно отправить через send_message(); см. email: Примеры.