smtplib — Клиент протокола SMTP

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


Модуль smtplib определяет объект клиентской сессии SMTP, который можно использовать для отправки почты на любую машину в Интернете с демоном SMTP или ESMTP listener. Подробности работы SMTP и ESMTP смотрите в RFC 821 (Simple Mail Transfer Protocol) и RFC 1869 (SMTP Service Extensions).

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

Экземпляр SMTP инкапсулирует SMTP-соединение. Он имеет методы, поддерживающие полный набор операций SMTP и ESMTP. Если указаны необязательные параметры хоста и порта, то при инициализации вызывается метод SMTP connect() с этими параметрами. Если указано, local_hostname используется в качестве FQDN локального хоста в команде HELO/EHLO. В противном случае, имя локального хоста находится с помощью socket.getfqdn(). Если вызов connect() возвращает что-либо, кроме кода успеха, выдается предупреждение SMTPConnectError. Необязательный параметр timeout задает таймаут в секундах для блокировки операций, таких как попытка соединения (если он не указан, будет использован глобальный таймаут по умолчанию). Если тайм-аут истекает, выдается сообщение TimeoutError. Необязательный параметр source_address позволяет привязываться к определенному адресу источника на машине с несколькими сетевыми интерфейсами и/или к определенному порту TCP источника. Он принимает кортеж (хост, порт), к которому сокет должен привязаться в качестве адреса источника перед подключением. Если значение опущено (или если 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')
>>>

Вызывает auditing event smtplib.send с аргументами self, 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 и позволяет настраивать различные аспекты безопасного соединения. Пожалуйста, прочитайте Соображения безопасности о лучших практиках.

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

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

Изменено в версии 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, в значительной степени основан на стандартном клиенте SMTP. Обычно для LMTP используются сокеты Unix, поэтому наш метод connect() должен поддерживать их, а также обычный сервер host:port. Необязательные аргументы local_hostname и source_address имеют то же значение, что и в классе 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 новыми командами, поддерживается динамическое обнаружение команд, предоставляемых сервером, и определяется несколько дополнительных команд.

Объекты SMTP

Экземпляр 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) для подключения к локальному хосту. Если имя хоста заканчивается двоеточием (':'), за которым следует число, этот суффикс будет удален, а число будет интерпретировано как номер порта, который нужно использовать. Этот метод автоматически вызывается конструктором, если при инстанцировании указан хост. Возвращает кортеж из кода ответа и сообщения, отправленного сервером в ответе на соединение.

Вызывает auditing event 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 определяет, может ли для методов аутентификации, которые его поддерживают, «начальный ответ», как указано в RFC 4954, быть отправлен вместе с командой AUTH, а не требовать вызова/ответа.

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

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

Выдать команду SMTP AUTH для указанного механизма аутентификации, и обработать ответ вызова через автообъект.

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 ложно, будет вызван authobject() для обработки ответа вызова сервера; передаваемый ему аргумент challenge будет bytes. Он должен вернуть ASCII str данные, которые будут закодированы в 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 (Transport Layer Security). Все последующие команды 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

Поддержка SSL/TLS недоступна вашему интерпретатору Python.

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

Изменено в версии 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 с адресами (пустая строка будет рассматриваться как список с 1 адресом) и строка сообщения. Вызывающая сторона может передать список опций 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, используя BytesGenerator с \r\n в качестве linesep, и вызывает sendmail() для передачи полученного сообщения. Независимо от значений from_addr и to_addrs, send_message не передает никаких Bcc или Resent-Bcc заголовков, которые могут появиться в msg. Если любой из адресов в from_addr и to_addrs содержит символы, не являющиеся символами ASCII, и сервер не рекламирует поддержку SMTPUTF8, возникает ошибка SMTPNotSupported. В противном случае Message сериализуется с клоном своего policy с атрибутом utf8 установленным в True, а SMTPUTF8 и BODY=8BITMIME добавляются в mail_options.

Добавлено в версии 3.2.

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

SMTP.quit()

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

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

Пример SMTP

Этот пример запрашивает у пользователя адреса, необходимые для конверта сообщения (адреса «Кому» и «От»), и сообщение, которое должно быть доставлено. Обратите внимание, что заголовки, которые должны быть включены в сообщение, должны быть включены в сообщение в том виде, в котором они введены; этот пример не выполняет никакой обработки заголовков RFC 822. В частности, адреса „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):")

# Add the From: and To: headers at the start!
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: Примеры.

Вернуться на верх