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

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

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


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

class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])

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

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

Изменено в версии 2.6: добавлен параметр timeout.

class smtplib.SMTP_SSL([host[, port[, local_hostname[, keyfile[, certfile[, timeout]]]]]])

Экземпляр SMTP_SSL ведёт себя точно так же, как экземпляры SMTP. SMTP_SSL следует использовать, если SSL необходим с самого начала соединения, а использование starttls() не подходит. Если host не указан, используется локальный хост. Если port опущен, используется стандартный порт SMTP через SSL (465). local_hostname имеет тот же смысл, что и для класса SMTP. keyfile и certfile также необязательны; они могут содержать закрытый ключ в формате PEM и файл цепочки сертификатов для SSL-соединения. Необязательный параметр timeout задаёт тайм-аут в секундах для блокирующих операций, таких как попытка соединения (если не указан, используется глобальная настройка тайм-аута по умолчанию). Если время тайм-аута истекает, возбуждается socket.timeout.

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

class smtplib.LMTP([host[, port[, local_hostname]]])

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

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

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

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

exception smtplib.SMTPException

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

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.SMTPAuthenticationError

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

См. также

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

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

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

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

20.12.1. Объекты SMTPSMTP Objects

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

SMTP.set_debuglevel(level)

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

SMTP.docmd(cmd[, argstring])

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

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

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

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

SMTP.connect([host[, port]])

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

SMTP.helo([hostname])

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

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

SMTP.ehlo([hostname])

Идентификация перед 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.

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

SMTP.has_extn(name)

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

SMTP.verify(address)

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

Примечание

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

SMTP.login(user, password)

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

SMTPHeloError

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

SMTPAuthenticationError

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

SMTPException

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

SMTP.starttls([keyfile[, certfile]])

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

Если указаны keyfile и certfile, они передаются функции ssl() модуля socket.

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

Изменено в версии 2.6.

SMTPHeloError

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

SMTPException

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

Изменено в версии 2.6.

RuntimeError

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

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 используются для построения конверта сообщения, используемого транспортными агентами. SMTP никак не изменяет заголовки сообщения.

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

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

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

SMTPRecipientsRefused

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

SMTPHeloError

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

SMTPSenderRefused

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

SMTPDataError

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

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

SMTP.quit()

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

Изменено в версии 2.6: Возвращает значение.

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

20.12.2. Пример SMTPSMTP Example

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

import smtplib

def prompt(prompt):
    return raw_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 1:
    try:
        line = raw_input()
    except EOFError:
        break
    if not line:
        break
    msg = msg + line

print "Message length is " + repr(len(msg))

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

Примечание

В целом рекомендуется использовать возможности пакета email для создания email-сообщения, которое затем можно преобразовать в строку и отправить через sendmail(); см. примеры email.