email-examples.md
1> **Источник:** https://python-all.ru/3.1/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.1/library/email.html#module-email): Примеры89Вот несколько примеров использования пакета [`email`](https://python-all.ru/3.1/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-сервер, но не включать34# заголовок конверта.35s = smtplib.SMTP('localhost')36s.sendmail(me, [you], msg.as_string())37s.quit()38```3940Вот пример отправки MIME-сообщения, содержащего много семейных фотографий, которые могут находиться в каталоге:4142```python43# Импорт smtplib для функции отправки44import smtplib4546# Вот модули пакета email, которые нам понадобятся47from email.mime.image import MIMEImage48from email.mime.multipart import MIMEMultipart4950COMMASPACE = ', '5152# Создать контейнер (внешнее) email-сообщение.53msg = MIMEMultipart()54msg['Subject'] = 'Our family reunion'55# me == адрес электронной почты отправителя56# family = список адресов электронной почты всех получателей57msg['From'] = me58msg['To'] = COMMASPACE.join(family)59msg.preamble = 'Our family reunion'6061# Предположим, что все файлы изображений в формате PNG.62for file in pngfiles:63 # Открыть файлы в двоичном режиме. Пусть класс MIMEImage автоматически64 # определяет конкретный тип изображения.65 fp = open(file, 'rb')66 img = MIMEImage(fp.read())67 fp.close()68 msg.attach(img)6970# Отправляем email через собственный SMTP-сервер.71s = smtplib.SMTP('localhost')72s.sendmail(me, family, msg.as_string())73s.quit()74```7576Вот пример отправки всего содержимого каталога в виде email- сообщения: [\[1\]](https://python-all.ru/3.1/library/email-examples.html#id4)7778```python79#!/usr/bin/env python8081"""Отправляем содержимое каталога как MIME-сообщение."""8283import os84import sys85import smtplib86# Для определения типа MIME по расширению имени файла87import mimetypes8889from optparse import OptionParser9091from email import encoders92from email.message import Message93from email.mime.audio import MIMEAudio94from email.mime.base import MIMEBase95from email.mime.image import MIMEImage96from email.mime.multipart import MIMEMultipart97from email.mime.text import MIMEText9899COMMASPACE = ', '100101def main():102 parser = OptionParser(usage="""\103Send the contents of a directory as a MIME message.104105Usage: %prog [options]106107Unless the -o option is given, the email is sent by forwarding to your local108SMTP server, which then does the normal delivery process. Your local machine109must be running an SMTP server.110""")111 parser.add_option('-d', '--directory',112 type='string', action='store',113 help="""Mail the contents of the specified directory,114 otherwise use the current directory. Only the regular115 files in the directory are sent, and we don't recurse to116 subdirectories.""")117 parser.add_option('-o', '--output',118 type='string', action='store', metavar='FILE',119 help="""Print the composed message to FILE instead of120 sending the message to the SMTP server.""")121 parser.add_option('-s', '--sender',122 type='string', action='store', metavar='SENDER',123 help='The value of the From: header (required)')124 parser.add_option('-r', '--recipient',125 type='string', action='append', metavar='RECIPIENT',126 default=[], dest='recipients',127 help='A To: header value (at least one required)')128 opts, args = parser.parse_args()129 if not opts.sender or not opts.recipients:130 parser.print_help()131 sys.exit(1)132 directory = opts.directory133 if not directory:134 directory = '.'135 # Создать внешнее (оборачивающее) сообщение.136 outer = MIMEMultipart()137 outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory)138 outer['To'] = COMMASPACE.join(opts.recipients)139 outer['From'] = opts.sender140 outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'141142 for filename in os.listdir(directory):143 path = os.path.join(directory, filename)144 if not os.path.isfile(path):145 continue146 # Определяем тип содержимого по расширению файла. Кодировка147 # будет проигнорирована, хотя стоит проверять простые вещи, такие как148 # gzip-файлы или сжатые файлы.149 ctype, encoding = mimetypes.guess_type(path)150 if ctype is None or encoding is not None:151 # Не удалось определить тип, или файл закодирован (сжат), поэтому152 # используем общий тип 'набор битов'.153 ctype = 'application/octet-stream'154 maintype, subtype = ctype.split('/', 1)155 if maintype == 'text':156 fp = open(path)157 # Примечание: нужно обработать вычисление кодировки.158 msg = MIMEText(fp.read(), _subtype=subtype)159 fp.close()160 elif maintype == 'image':161 fp = open(path, 'rb')162 msg = MIMEImage(fp.read(), _subtype=subtype)163 fp.close()164 elif maintype == 'audio':165 fp = open(path, 'rb')166 msg = MIMEAudio(fp.read(), _subtype=subtype)167 fp.close()168 else:169 fp = open(path, 'rb')170 msg = MIMEBase(maintype, subtype)171 msg.set_payload(fp.read())172 fp.close()173 # Закодировать полезную нагрузку с помощью Base64.174 encoders.encode_base64(msg)175 # Установить параметр filename.176 msg.add_header('Content-Disposition', 'attachment', filename=filename)177 outer.attach(msg)178 # Теперь отправляем или сохраняем сообщение179 composed = outer.as_string()180 if opts.output:181 fp = open(opts.output, 'w')182 fp.write(composed)183 fp.close()184 else:185 s = smtplib.SMTP('localhost')186 s.sendmail(opts.sender, opts.recipients, composed)187 s.quit()188189if __name__ == '__main__':190 main()191```192193Вот пример распаковки MIME-сообщения вроде показанного выше в каталог с файлами:194195```python196#!/usr/bin/env python197198"""Распаковываем MIME-сообщение в каталог файлов."""199200import os201import sys202import email203import errno204import mimetypes205206from optparse import OptionParser207208def main():209 parser = OptionParser(usage="""\210Unpack a MIME message into a directory of files.211212Usage: %prog [options] msgfile213""")214 parser.add_option('-d', '--directory',215 type='string', action='store',216 help="""Unpack the MIME message into the named217 directory, which will be created if it doesn't already218 exist.""")219 opts, args = parser.parse_args()220 if not opts.directory:221 parser.print_help()222 sys.exit(1)223224 try:225 msgfile = args[0]226 except IndexError:227 parser.print_help()228 sys.exit(1)229230 try:231 os.mkdir(opts.directory)232 except OSError as e:233 # Игнорировать ошибку существования каталога234 if e.errno != errno.EEXIST:235 raise236237 fp = open(msgfile)238 msg = email.message_from_file(fp)239 fp.close()240241 counter = 1242 for part in msg.walk():243 # multipart/* – это просто контейнеры244 if part.get_content_maintype() == 'multipart':245 continue246 # Приложениям следует тщательно проверять имя файла, чтобы247 # email-сообщение не могло перезаписать важные файлы248 filename = part.get_filename()249 if not filename:250 ext = mimetypes.guess_extension(part.get_content_type())251 if not ext:252 # Использовать универсальное расширение для набора битов.253 ext = '.bin'254 filename = 'part-%03d%s' % (counter, ext)255 counter += 1256 fp = open(os.path.join(opts.directory, filename), 'wb')257 fp.write(part.get_payload(decode=True))258 fp.close()259260if __name__ == '__main__':261 main()262```263264Here’s an example of how to create an HTML message with an alternative plain text version: [\[2\]](https://python-all.ru/3.1/library/email-examples.html#id5)265266```python267#! /usr/bin/python268269import smtplib270271from email.mime.multipart import MIMEMultipart272from email.mime.text import MIMEText273274# me == мой адрес электронной почты.275# you == адрес электронной почты получателя.276me = "my@email.com"277you = "your@email.com"278279# Создать контейнер сообщения – правильный тип MIME – multipart/alternative.280msg = MIMEMultipart('alternative')281msg['Subject'] = "Link"282msg['From'] = me283msg['To'] = you284285# Создать тело сообщения (версии в виде простого текста и HTML).286text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"287html = """\288<html>289 <head></head>290 <body>291 <p>Hi!<br>292 How are you?<br>293 Here is the <a href="http://www.python.org">link</a> you wanted.294 </p>295 </body>296</html>297"""298299# Записать MIME-типы обеих частей – text/plain и text/html.300part1 = MIMEText(text, 'plain')301part2 = MIMEText(html, 'html')302303# Прикрепить части к контейнеру сообщения.304# Согласно RFC 2046, последняя часть многокомпонентного сообщения, в данном случае305# HTML-сообщение, является наилучшим и предпочтительным.306msg.attach(part1)307msg.attach(part2)308309# Отправка сообщения через локальный SMTP-сервер.310s = smtplib.SMTP('localhost')311# Функция sendmail принимает 3 аргумента: адрес отправителя, адрес получателя312# и сообщение для отправки – здесь оно отправляется в виде одной строки.313s.sendmail(me, you, msg.as_string())314s.quit()315```316317Сноски318319| [\[1\]](https://python-all.ru/3.1/library/email-examples.html#id2) | Спасибо Matthew Dixon Cowles за оригинальную идею и примеры. |320| --- | --- |321322| [\[2\]](https://python-all.ru/3.1/library/email-examples.html#id3) | Автор: Martin Matejek. |323| --- | --- |324