smtplib
— Клиент протокола SMTP¶
Источник: Lib/smtplib.py
Модуль smtplib
определяет объект клиентской сессии SMTP, который можно использовать для отправки почты на любой интернет-машине с демоном-приемником SMTP или ESMTP. Для получения подробной информации о работе SMTP и ESMTP обратитесь к RFC 821 (Simple Mail Transfer Protocol) и RFC 1869 (SMTP Service Extensions).
Availability: не WASI.
Этот модуль не работает или недоступен на WebAssembly. Дополнительную информацию см. в разделе Платформы WebAssembly.
- class smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)¶
Экземпляр
SMTP
инкапсулирует SMTP-соединение. Он имеет методы, поддерживающие полный набор операций SMTP и ESMTP. Если указаны необязательные параметры host и port, при инициализации вызывается метод SMTPconnect()
с этими параметрами. Если указано local_hostname, то в качестве FQDN локального хоста в команде HELO/EHLO используется local_hostname. В противном случае имя локального хоста находится с помощью методаsocket.getfqdn()
. Если вызовconnect()
возвращает что-либо, отличное от кода успеха, выдается сообщениеSMTPConnectError
. Необязательный параметр timeout задает таймаут в секундах для блокировки операций, таких как попытка соединения (если он не указан, будет использовано глобальное значение таймаута по умолчанию). Если таймаут истекает, вызывается сигналTimeoutError
. Необязательный параметр source_address позволяет привязываться к определенному адресу источника на машине с несколькими сетевыми интерфейсами и/или к определенному TCP-порту источника. Он принимает 2-кортеж(host, port)
, к которому сокет должен привязаться в качестве адреса источника перед подключением. Если значение опущено (или если 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.
Added in version 3.5: Теперь поддерживается расширение SMTPUTF8 (RFC 6531).
Изменено в версии 3.9: Если параметр timeout установлен в нулевое значение, он вызовет ошибку
ValueError
, чтобы предотвратить создание неблокирующего сокета.
- class smtplib.SMTP_SSL(host='', port=0, local_hostname=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
и позволяет настраивать различные аспекты безопасного соединения. Пожалуйста, прочитайте Соображения безопасности о лучших практиках.Изменено в версии 3.3: Был добавлен контекст.
Изменено в версии 3.3: Добавлен аргумент source_address.
Изменено в версии 3.4: Класс теперь поддерживает проверку имени хоста с помощью
ssl.SSLContext.check_hostname
и Указание имени сервера (см.ssl.HAS_SNI
).Изменено в версии 3.9: Если параметр timeout установлен в нулевое значение, то будет поднята ошибка
ValueError
, чтобы предотвратить создание неблокирующего сокета.Изменено в версии 3.12: Устаревшие параметры keyfile и certfile были удалены.
- class smtplib.LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None[, timeout])¶
Протокол LMTP, который очень похож на ESMTP, в значительной степени основан на стандартном клиенте SMTP. Обычно для LMTP используются сокеты Unix, поэтому наш метод
connect()
должен поддерживать их, а также обычный сервер хост:порт. Необязательные аргументы 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¶
Команда или опция не поддерживается сервером.
Added in version 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
, если имя входит в набор расширений служб 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)¶
Выдать
SMTP
AUTH
команду для указанного механизма аутентификации и обработайте ответ на вызов через автообъект.mechanism указывает, какой механизм аутентификации будет использоваться в качестве аргумента команды
AUTH
; допустимыми значениями являются те, которые перечислены в элементеauth
вesmtp_features
.authobject должен быть вызываемым объектом, принимающим необязательный единственный аргумент:
data = authobject(challenge=None)
Если необязательный ключевой аргумент initial_response_ok равен true, то
authobject()
будет вызван первым без аргумента. Он может вернуть RFC 4954 «начальный ответ» в формате ASCIIstr
, который будет закодирован и отправлен с командойAUTH
, как показано ниже. Еслиauthobject()
не поддерживает начальный ответ (например, потому что требует вызова), то при вызове с помощьюchallenge=None
он должен вернуть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
.Added in version 3.5.
- SMTP.starttls(*, 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.12: Устаревшие параметры keyfile и certfile были удалены.
SMTPHeloError
Сервер не ответил должным образом на приветствие
HELO
.SMTPNotSupportedError
Сервер не поддерживает расширение STARTTLS.
RuntimeError
Поддержка SSL/TLS недоступна вашему интерпретатору Python.
Изменено в версии 3.3: Был добавлен контекст.
Изменено в версии 3.4: Метод теперь поддерживает проверку имени хоста с помощью
SSLContext.check_hostname
и индикатора имени сервера (см.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
Сервер ответил с неожиданным кодом ошибки (кроме отказа получателя).
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.Added in version 3.2.
Added in version 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: Примеры.