email-examples.md
1> **Источник:** https://python-all.ru/3.2/library/email-examples.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.1.11. [`email`](https://python-all.ru/3.2/library/email.html#module-email): Примеры89Вот несколько примеров использования пакета [`email`](https://python-all.ru/3.2/library/email.html#module-email) для чтения, записи и отправки простых email-сообщений, а также более сложных MIME-сообщений.1011Сначала посмотрим, как создать и отправить простое текстовое сообщение:1213```python14# Импорт smtplib для функции отправки15import smtplib1617# Импортируются необходимые модули email.18from email.mime.text import MIMEText1920# Открыть обычный текстовый файл для чтения. В этом примере предполагается, что21# текстовый файл содержит только символы ASCII.22fp = open(textfile, 'rb')23# Создать сообщение text/plain24msg = MIMEText(fp.read())25fp.close()2627# me == адрес электронной почты отправителя28# you == адрес электронной почты получателя29msg['Subject'] = 'The contents of %s' % textfile30msg['From'] = me31msg['To'] = you3233# Отправить сообщение через собственный SMTP-сервер.34s = smtplib.SMTP('localhost')35s.send_message(msg)36s.quit()37```3839Разбор заголовков RFC822 легко выполняется с помощью методов parse(filename) или parsestr(message\_as\_string) класса Parser():4041```python42# Импортируются необходимые модули email.43from email.parser import Parser4445# Если заголовки электронного письма находятся в файле, раскомментируйте эту строку:46#headers = Parser().parse(open(messagefile, 'r'))4748# Или для разбора заголовков из строки используйте:49headers = Parser().parsestr('From: <user@example.com>\n'50 'To: <someone_else@example.com>\n'51 'Subject: Test message\n'52 '\n'53 'Body would go here\n')5455# Теперь к элементам заголовков можно обращаться как к словарю:56print('To: %s' % headers['to'])57print('From: %s' % headers['from'])58print('Subject: %s' % headers['subject'])59```6061Вот пример отправки MIME-сообщения, содержащего много семейных фотографий, которые могут находиться в каталоге:6263```python64# Импорт smtplib для функции отправки65import smtplib6667# Вот модули пакета email, которые нам понадобятся68from email.mime.image import MIMEImage69from email.mime.multipart import MIMEMultipart7071COMMASPACE = ', '7273# Создать контейнер (внешнее) email-сообщение.74msg = MIMEMultipart()75msg['Subject'] = 'Our family reunion'76# me == адрес электронной почты отправителя77# family = список адресов электронной почты всех получателей78msg['From'] = me79msg['To'] = COMMASPACE.join(family)80msg.preamble = 'Our family reunion'8182# Предположим, что все файлы изображений в формате PNG.83for file in pngfiles:84 # Открыть файлы в двоичном режиме. Пусть класс MIMEImage автоматически85 # определяет конкретный тип изображения.86 fp = open(file, 'rb')87 img = MIMEImage(fp.read())88 fp.close()89 msg.attach(img)9091# Отправляем email через собственный SMTP-сервер.92s = smtplib.SMTP('localhost')93s.send_message(msg)94s.quit()95```9697Вот пример отправки всего содержимого каталога в виде email- сообщения: [\[1\]](https://python-all.ru/3.2/library/email-examples.html#id4)9899```python100#!/usr/bin/env python3101102"""Отправляем содержимое каталога как MIME-сообщение."""103104import os105import sys106import smtplib107# Для определения типа MIME по расширению имени файла108import mimetypes109110from optparse import OptionParser111112from email import encoders113from email.message import Message114from email.mime.audio import MIMEAudio115from email.mime.base import MIMEBase116from email.mime.image import MIMEImage117from email.mime.multipart import MIMEMultipart118from email.mime.text import MIMEText119120COMMASPACE = ', '121122def main():123 parser = OptionParser(usage="""\124Send the contents of a directory as a MIME message.125126Usage: %prog [options]127128Unless the -o option is given, the email is sent by forwarding to your local129SMTP server, which then does the normal delivery process. Your local machine130must be running an SMTP server.131""")132 parser.add_option('-d', '--directory',133 type='string', action='store',134 help="""Mail the contents of the specified directory,135 otherwise use the current directory. Only the regular136 files in the directory are sent, and we don't recurse to137 subdirectories.""")138 parser.add_option('-o', '--output',139 type='string', action='store', metavar='FILE',140 help="""Print the composed message to FILE instead of141 sending the message to the SMTP server.""")142 parser.add_option('-s', '--sender',143 type='string', action='store', metavar='SENDER',144 help='The value of the From: header (required)')145 parser.add_option('-r', '--recipient',146 type='string', action='append', metavar='RECIPIENT',147 default=[], dest='recipients',148 help='A To: header value (at least one required)')149 opts, args = parser.parse_args()150 if not opts.sender or not opts.recipients:151 parser.print_help()152 sys.exit(1)153 directory = opts.directory154 if not directory:155 directory = '.'156 # Создать внешнее (оборачивающее) сообщение.157 outer = MIMEMultipart()158 outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory)159 outer['To'] = COMMASPACE.join(opts.recipients)160 outer['From'] = opts.sender161 outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'162163 for filename in os.listdir(directory):164 path = os.path.join(directory, filename)165 if not os.path.isfile(path):166 continue167 # Определяем тип содержимого по расширению файла. Кодировка168 # будет проигнорирована, хотя стоит проверять простые вещи, такие как169 # gzip-файлы или сжатые файлы.170 ctype, encoding = mimetypes.guess_type(path)171 if ctype is None or encoding is not None:172 # Не удалось определить тип, или файл закодирован (сжат), поэтому173 # используем общий тип 'набор битов'.174 ctype = 'application/octet-stream'175 maintype, subtype = ctype.split('/', 1)176 if maintype == 'text':177 fp = open(path)178 # Примечание: нужно обработать вычисление кодировки.179 msg = MIMEText(fp.read(), _subtype=subtype)180 fp.close()181 elif maintype == 'image':182 fp = open(path, 'rb')183 msg = MIMEImage(fp.read(), _subtype=subtype)184 fp.close()185 elif maintype == 'audio':186 fp = open(path, 'rb')187 msg = MIMEAudio(fp.read(), _subtype=subtype)188 fp.close()189 else:190 fp = open(path, 'rb')191 msg = MIMEBase(maintype, subtype)192 msg.set_payload(fp.read())193 fp.close()194 # Закодировать полезную нагрузку с помощью Base64.195 encoders.encode_base64(msg)196 # Установить параметр filename.197 msg.add_header('Content-Disposition', 'attachment', filename=filename)198 outer.attach(msg)199 # Теперь отправляем или сохраняем сообщение200 composed = outer.as_string()201 if opts.output:202 fp = open(opts.output, 'w')203 fp.write(composed)204 fp.close()205 else:206 s = smtplib.SMTP('localhost')207 s.sendmail(opts.sender, opts.recipients, composed)208 s.quit()209210if __name__ == '__main__':211 main()212```213214Вот пример распаковки MIME-сообщения вроде показанного выше в каталог с файлами:215216```python217#!/usr/bin/env python3218219"""Распаковываем MIME-сообщение в каталог файлов."""220221import os222import sys223import email224import errno225import mimetypes226227from optparse import OptionParser228229def main():230 parser = OptionParser(usage="""\231Unpack a MIME message into a directory of files.232233Usage: %prog [options] msgfile234""")235 parser.add_option('-d', '--directory',236 type='string', action='store',237 help="""Unpack the MIME message into the named238 directory, which will be created if it doesn't already239 exist.""")240 opts, args = parser.parse_args()241 if not opts.directory:242 parser.print_help()243 sys.exit(1)244245 try:246 msgfile = args[0]247 except IndexError:248 parser.print_help()249 sys.exit(1)250251 try:252 os.mkdir(opts.directory)253 except OSError as e:254 # Игнорировать ошибку существования каталога255 if e.errno != errno.EEXIST:256 raise257258 fp = open(msgfile)259 msg = email.message_from_file(fp)260 fp.close()261262 counter = 1263 for part in msg.walk():264 # multipart/* – это просто контейнеры265 if part.get_content_maintype() == 'multipart':266 continue267 # Приложениям следует тщательно проверять имя файла, чтобы268 # email-сообщение не могло перезаписать важные файлы269 filename = part.get_filename()270 if not filename:271 ext = mimetypes.guess_extension(part.get_content_type())272 if not ext:273 # Использовать универсальное расширение для набора битов.274 ext = '.bin'275 filename = 'part-%03d%s' % (counter, ext)276 counter += 1277 fp = open(os.path.join(opts.directory, filename), 'wb')278 fp.write(part.get_payload(decode=True))279 fp.close()280281if __name__ == '__main__':282 main()283```284285Here’s an example of how to create an HTML message with an alternative plain text version: [\[2\]](https://python-all.ru/3.2/library/email-examples.html#id5)286287```python288#!/usr/bin/env python3289290import smtplib291292from email.mime.multipart import MIMEMultipart293from email.mime.text import MIMEText294295# me == мой адрес электронной почты.296# you == адрес электронной почты получателя.297me = "my@email.com"298you = "your@email.com"299300# Создать контейнер сообщения – правильный тип MIME – multipart/alternative.301msg = MIMEMultipart('alternative')302msg['Subject'] = "Link"303msg['From'] = me304msg['To'] = you305306# Создать тело сообщения (версии в виде простого текста и HTML).307text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"308html = """\309<html>310 <head></head>311 <body>312 <p>Hi!<br>313 How are you?<br>314 Here is the <a href="http://www.python.org">link</a> you wanted.315 </p>316 </body>317</html>318"""319320# Записать MIME-типы обеих частей – text/plain и text/html.321part1 = MIMEText(text, 'plain')322part2 = MIMEText(html, 'html')323324# Прикрепить части к контейнеру сообщения.325# Согласно RFC 2046, последняя часть многокомпонентного сообщения, в данном случае326# HTML-сообщение, является наилучшим и предпочтительным.327msg.attach(part1)328msg.attach(part2)329330# Отправка сообщения через локальный SMTP-сервер.331s = smtplib.SMTP('localhost')332# Функция sendmail принимает 3 аргумента: адрес отправителя, адрес получателя333# и сообщение для отправки – здесь оно отправляется в виде одной строки.334s.sendmail(me, you, msg.as_string())335s.quit()336```337338Сноски339340| [\[1\]](https://python-all.ru/3.2/library/email-examples.html#id2) | Спасибо Matthew Dixon Cowles за оригинальную идею и примеры. |341| --- | --- |342343| [\[2\]](https://python-all.ru/3.2/library/email-examples.html#id3) | Автор: Martin Matejek. |344| --- | --- |345