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

email-examples.md

348 строк · 13.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/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/2.7/library/email.html#module-email): Примеры89Вот несколько примеров использования пакета [`email`](https://python-all.ru/2.7/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Разбор заголовков RFC822 легко выполняется с помощью методов parse(filename) или parsestr(message\_as\_string) класса Parser():4142```python43# Импортируются необходимые модули email.44from email.parser import Parser4546#  Если заголовки электронного письма находятся в файле, раскомментируйте эту строку:47#headers = Parser().parse(open(messagefile, 'r'))4849#  Или для разбора заголовков из строки используйте:50headers = Parser().parsestr('From: <user@example.com>\n'51        'To: <someone_else@example.com>\n'52        'Subject: Test message\n'53        '\n'54        'Body would go here\n')5556#  Теперь к элементам заголовков можно обращаться как к словарю:57print 'To: %s' % headers['to']58print 'From: %s' % headers['from']59print 'Subject: %s' % headers['subject']60```6162Вот пример отправки MIME-сообщения, содержащего много семейных фотографий, которые могут находиться в каталоге:6364```python65# Импорт smtplib для функции отправки66import smtplib6768# Вот модули пакета email, которые нам понадобятся69from email.mime.image import MIMEImage70from email.mime.multipart import MIMEMultipart7172COMMASPACE = ', '7374# Создать контейнер (внешнее) email-сообщение.75msg = MIMEMultipart()76msg['Subject'] = 'Our family reunion'77# me == адрес электронной почты отправителя78# family = список адресов электронной почты всех получателей79msg['From'] = me80msg['To'] = COMMASPACE.join(family)81msg.preamble = 'Our family reunion'8283# Предположим, что все файлы изображений в формате PNG.84for file in pngfiles:85    # Открыть файлы в двоичном режиме. Пусть класс MIMEImage автоматически86    # определяет конкретный тип изображения.87    fp = open(file, 'rb')88    img = MIMEImage(fp.read())89    fp.close()90    msg.attach(img)9192# Отправляем email через собственный SMTP-сервер.93s = smtplib.SMTP('localhost')94s.sendmail(me, family, msg.as_string())95s.quit()96```9798Вот пример отправки всего содержимого каталога в виде email- сообщения: [1](https://python-all.ru/2.7/library/email-examples.html#id4)99100```python101#!/usr/bin/env python102103"""Отправляем содержимое каталога как MIME-сообщение."""104105import os106import sys107import smtplib108# Для определения типа MIME по расширению имени файла109import mimetypes110111from optparse import OptionParser112113from email import encoders114from email.message import Message115from email.mime.audio import MIMEAudio116from email.mime.base import MIMEBase117from email.mime.image import MIMEImage118from email.mime.multipart import MIMEMultipart119from email.mime.text import MIMEText120121COMMASPACE = ', '122123def main():124    parser = OptionParser(usage="""\125Send the contents of a directory as a MIME message.126127Usage: %prog [options]128129Unless the -o option is given, the email is sent by forwarding to your local130SMTP server, which then does the normal delivery process.  Your local machine131must be running an SMTP server.132""")133    parser.add_option('-d', '--directory',134                      type='string', action='store',135                      help="""Mail the contents of the specified directory,136                      otherwise use the current directory.  Only the regular137                      files in the directory are sent, and we don't recurse to138                      subdirectories.""")139    parser.add_option('-o', '--output',140                      type='string', action='store', metavar='FILE',141                      help="""Print the composed message to FILE instead of142                      sending the message to the SMTP server.""")143    parser.add_option('-s', '--sender',144                      type='string', action='store', metavar='SENDER',145                      help='The value of the From: header (required)')146    parser.add_option('-r', '--recipient',147                      type='string', action='append', metavar='RECIPIENT',148                      default=[], dest='recipients',149                      help='A To: header value (at least one required)')150    opts, args = parser.parse_args()151    if not opts.sender or not opts.recipients:152        parser.print_help()153        sys.exit(1)154    directory = opts.directory155    if not directory:156        directory = '.'157    # Создать внешнее (оборачивающее) сообщение.158    outer = MIMEMultipart()159    outer['Subject'] = 'Contents of directory %s' % os.path.abspath(directory)160    outer['To'] = COMMASPACE.join(opts.recipients)161    outer['From'] = opts.sender162    outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'163164    for filename in os.listdir(directory):165        path = os.path.join(directory, filename)166        if not os.path.isfile(path):167            continue168        # Определяем тип содержимого по расширению файла. Кодировка169        # будет проигнорирована, хотя стоит проверять простые вещи, такие как170        # gzip-файлы или сжатые файлы.171        ctype, encoding = mimetypes.guess_type(path)172        if ctype is None or encoding is not None:173            # Не удалось определить тип, или файл закодирован (сжат), поэтому174            # используем общий тип 'набор битов'.175            ctype = 'application/octet-stream'176        maintype, subtype = ctype.split('/', 1)177        if maintype == 'text':178            fp = open(path)179            # Примечание: нужно обработать вычисление кодировки.180            msg = MIMEText(fp.read(), _subtype=subtype)181            fp.close()182        elif maintype == 'image':183            fp = open(path, 'rb')184            msg = MIMEImage(fp.read(), _subtype=subtype)185            fp.close()186        elif maintype == 'audio':187            fp = open(path, 'rb')188            msg = MIMEAudio(fp.read(), _subtype=subtype)189            fp.close()190        else:191            fp = open(path, 'rb')192            msg = MIMEBase(maintype, subtype)193            msg.set_payload(fp.read())194            fp.close()195            # Закодировать полезную нагрузку с помощью Base64.196            encoders.encode_base64(msg)197        # Установить параметр filename.198        msg.add_header('Content-Disposition', 'attachment', filename=filename)199        outer.attach(msg)200    # Теперь отправляем или сохраняем сообщение201    composed = outer.as_string()202    if opts.output:203        fp = open(opts.output, 'w')204        fp.write(composed)205        fp.close()206    else:207        s = smtplib.SMTP('localhost')208        s.sendmail(opts.sender, opts.recipients, composed)209        s.quit()210211if __name__ == '__main__':212    main()213```214215Вот пример распаковки MIME-сообщения вроде показанного выше в каталог с файлами:216217```python218#!/usr/bin/env python219220"""Распаковываем MIME-сообщение в каталог файлов."""221222import os223import sys224import email225import errno226import mimetypes227228from optparse import OptionParser229230def main():231    parser = OptionParser(usage="""\232Unpack a MIME message into a directory of files.233234Usage: %prog [options] msgfile235""")236    parser.add_option('-d', '--directory',237                      type='string', action='store',238                      help="""Unpack the MIME message into the named239                      directory, which will be created if it doesn't already240                      exist.""")241    opts, args = parser.parse_args()242    if not opts.directory:243        parser.print_help()244        sys.exit(1)245246    try:247        msgfile = args[0]248    except IndexError:249        parser.print_help()250        sys.exit(1)251252    try:253        os.mkdir(opts.directory)254    except OSError as e:255        # Игнорировать ошибку существования каталога256        if e.errno != errno.EEXIST:257            raise258259    fp = open(msgfile)260    msg = email.message_from_file(fp)261    fp.close()262263    counter = 1264    for part in msg.walk():265        # multipart/* – это просто контейнеры266        if part.get_content_maintype() == 'multipart':267            continue268        # Приложениям следует тщательно проверять имя файла, чтобы269        # email-сообщение не могло перезаписать важные файлы270        filename = part.get_filename()271        if not filename:272            ext = mimetypes.guess_extension(part.get_content_type())273            if not ext:274                # Использовать универсальное расширение для набора битов.275                ext = '.bin'276            filename = 'part-%03d%s' % (counter, ext)277        counter += 1278        fp = open(os.path.join(opts.directory, filename), 'wb')279        fp.write(part.get_payload(decode=True))280        fp.close()281282if __name__ == '__main__':283    main()284```285286Here’s an example of how to create an HTML message with an alternative plain text version: [2](https://python-all.ru/2.7/library/email-examples.html#id5)287288```python289#!/usr/bin/env python290291import smtplib292293from email.mime.multipart import MIMEMultipart294from email.mime.text import MIMEText295296# me == мой адрес электронной почты.297# you == адрес электронной почты получателя.298me = "my@email.com"299you = "your@email.com"300301# Создать контейнер сообщения – правильный тип MIME – multipart/alternative.302msg = MIMEMultipart('alternative')303msg['Subject'] = "Link"304msg['From'] = me305msg['To'] = you306307# Создать тело сообщения (версии в виде простого текста и HTML).308text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttps://www.python.org"309html = """\310<html>311  <head></head>312  <body>313    <p>Hi!<br>314       How are you?<br>315       Here is the <a href="https://www.python.org">link</a> you wanted.316    </p>317  </body>318</html>319"""320321# Записать MIME-типы обеих частей – text/plain и text/html.322part1 = MIMEText(text, 'plain')323part2 = MIMEText(html, 'html')324325# Прикрепить части к контейнеру сообщения.326# Согласно RFC 2046, последняя часть многокомпонентного сообщения, в данном случае327# HTML-сообщение, является наилучшим и предпочтительным.328msg.attach(part1)329msg.attach(part2)330331# Отправка сообщения через локальный SMTP-сервер.332s = smtplib.SMTP('localhost')333# Функция sendmail принимает 3 аргумента: адрес отправителя, адрес получателя334# и сообщение для отправки – здесь оно отправляется в виде одной строки.335s.sendmail(me, you, msg.as_string())336s.quit()337```338339Сноски340341**[1](https://python-all.ru/2.7/library/email-examples.html#id2)**342343Спасибо Matthew Dixon Cowles за оригинальную идею и примеры.344345**[2](https://python-all.ru/2.7/library/email-examples.html#id3)**346347Автор: Martin Matejek.348