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. Если указаны необязательные параметры хоста и порта, то при инициализации вызывается метод SMTPconnect()с этими параметрами. Если указано, local_hostname используется в качестве FQDN локального хоста в команде HELO/EHLO. В противном случае, имя локального хоста находится с помощьюsocket.getfqdn(). Если вызовconnect()возвращает что-либо, кроме кода успеха, выдается предупреждениеSMTPConnectError. Необязательный параметр timeout задает таймаут в секундах для блокировки операций, таких как попытка соединения (если он не указан, будет использован глобальный таймаут по умолчанию). Если тайм-аут истекает, выдается сообщениеTimeoutError. Необязательный параметр source_address позволяет привязываться к определенному адресу источника на машине с несколькими сетевыми интерфейсами и/или к определенному порту TCP источника. Он принимает кортеж (хост, порт), к которому сокет должен привязаться в качестве адреса источника перед подключением. Если значение опущено (или если host или port равны''и/или 0 соответственно), будет использоваться поведение ОС по умолчанию.Для обычного использования вам понадобятся только методы инициализации/подключения,
sendmail()иSMTP.quit(). Пример приведен ниже.Класс
SMTPподдерживает операторwith. При его использовании команда SMTPQUITвыдается автоматически при выходе из оператора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. Сначала выполняется попытка ESMTPEHLO.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, этот метод сначала попробует ESMTPEHLO. Этот метод вернется нормально, если аутентификация прошла успешно, или может вызвать следующие исключения: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)¶ Выдать команду
SMTPAUTHдля указанного механизма аутентификации, и обработать ответ вызова через автообъект.mechanism указывает, какой механизм аутентификации должен использоваться в качестве аргумента команды
AUTH; допустимыми значениями являются те, которые перечислены в элементеauthкомандыesmtp_features.authobject должен быть вызываемым объектом, принимающим необязательный единственный аргумент:
data = authobject(challenge=None)
Если необязательный ключевой аргумент initial_response_ok равен true,
authobject()будет вызван первым без аргумента. Он может вернуть RFC 4954 «начальный ответ» ASCIIstr, который будет закодирован и отправлен с командойAUTH, как показано ниже. Еслиauthobject()не поддерживает начальный ответ (например, потому что он требует вызова), он должен вернутьNoneпри вызове с помощьюchallenge=None. Если initial_response_ok равно false, тоauthobject()не будет вызван первым с помощьюNone.Если проверка начального ответа возвращает
None, или если initial_response_ok ложно, будет вызванauthobject()для обработки ответа вызова сервера; передаваемый ему аргумент challenge будетbytes. Он должен вернуть ASCIIstrданные, которые будут закодированы в 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, этот метод сначала пробует ESMTPEHLO.Не рекомендуется, начиная с версии 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, этот метод сначала пробует ESMTPEHLO. Если сервер выполняет ESMTP, ему будет передан размер сообщения и каждая из указанных опций (если опция входит в набор функций, рекламируемых сервером). ЕслиEHLOне удается, будет выполнена попыткаHELOи опции ESMTP будут подавлены.Этот метод вернется нормально, если почта принята хотя бы для одного получателя. В противном случае он вызовет исключение. То есть, если этот метод не вызывает исключения, то кто-то должен получить вашу почту. Если этот метод не вызывает исключения, он возвращает словарь с одной записью для каждого получателя, которому было отказано. Каждая запись содержит кортеж из кода ошибки SMTP и сопроводительного сообщения об ошибке, отправленного сервером.
Если
SMTPUTF8включен в mail_options, и сервер поддерживает его, from_addr и to_addrs могут содержать символы, отличные от ASCII.Этот метод может вызвать следующие исключения:
SMTPRecipientsRefusedВсем получателям было отказано. Никто не получил почту. Атрибут
recipientsобъекта исключения представляет собой словарь с информацией об отказавшихся получателях (подобный тому, который возвращается, когда хотя бы один получатель был принят).SMTPHeloErrorСервер не ответил должным образом на приветствие
HELO.SMTPSenderRefusedСервер не принял from_addr.
SMTPDataErrorСервер ответил с неожиданным кодом ошибки (кроме отказа получателя).
SMTPNotSupportedErrorSMTPUTF8было задано в 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: Примеры.