ENote
  • ✨Home
    • Відмова від відповідальності
  • Progr
    • Python
      • Модулі
        • pip
        • cgitb
        • datetime
          • Класс datetime() модуля datetime
            • Методы объекта datetime.datetime()
            • datetime.datetime examples
          • Класс timedelta() модуля datetime
            • datetime.timedelta examples
          • Класс date() модуля datetime
            • datetime.date examples
          • Класс time() модуля datetime
            • Формат для функций .strftime() и .strptime(). модуля datetime
        • os.path
        • pathlib
          • pathlib to str
        • subproces
        • os
        • Jinja
          • Синтаксис шаблонів Jinja
          • Клас Environment()
          • Простой пример cgi-скрипта c Jinja-шаблоном
          • Создание переменных
            • Як оновити глобальну змінну зсередини оператора IF / ELSE або циклу FOR
          • Фільтри і методи
          • Число у рядок, slices
          • Вбудовані фільтри Jinja2
        • re
          • re.search - example
          • re.findall - example
        • email / smtplib
          • Как отправлять электронные письма с помощью Python
        • requests
          • Як зберегти та завантажити файли cookie в запитах Python?
          • Извлечение и установка cookies с модулем requests в Python
          • Links
        • http.cookies
          • Всё о работе с cookie в Python — класс http.cookies
        • xlrd
        • xlwt
        • borb
          • ChunkOfText
          • send_usage_statistics
          • borb clear
          • 2.1.3 vs 2.1.15
          • QR-code
          • Залежності borb
        • JSON
          • Кирилиця в JSON
        • matplotlib
        • argparse
        • click
        • configparser
        • traceback
        • sys
          • exit()
        • mysql-connector-python
        • logging
        • icrawler
        • Auto Plates
        • rembg
        • random
      • Strings
        • Built-in methods
        • Форматування виводу
        • Початкові нулі
        • Рядок в число
      • list
        • Об’єднання списків
        • list.sort(), sorted()
        • list.reverse(), reversed()
        • all(), any()
        • sum(), min(), max()
        • map(), filter(), reduce()
        • join(), split()
      • tuple
      • dict
        • Об'єднання / злиття словників
        • Сортування словника Python: значення, ключі тощо
      • set
      • class Enum
      • Середнє арифметичне
      • Virtual environment
        • web-app
      • type(), isinstance()
      • __main__
      • Files & Dirs
        • Try except for exception handling
        • Cписок файлов директории
        • User Home Dir
        • Copy file
      • *args, **qwargs
      • Links
      • Область видимости
      • Handling a File Error
      • assert
      • if
      • Числа
        • Округлення чисел
        • Отримати число з рядка
      • Обработка исключений в Python
      • Файлы и сериализация данных
      • OOP
      • Net and Web
      • Структура проекта на Python
      • Распаковка итерируемых объектов
      • Links
      • Algorithms
      • Python exit commands: quit(), exit(), sys.exit() and os._exit()
      • Цикли for / while
      • uuid
    • JavaScript
      • String
        • replaceAll() polyfill
        • Шаблонные строки
      • Array
        • Все способы перебора массива в JavaScript
      • Object
      • document.location
      • RegExp
      • Examples
        • Вычисление остатка от деления
        • Остаток от деления и деление без остатка
        • Округление числа
      • XMLHttpRequest
      • alert, prompt, confirm
      • onclick
      • hidden, display:none
      • LocalStorage, sessionStorage
      • null, undefined
      • cookies (js)
      • var, let и const
        • var vs let
        • const
      • Модифікація DOM
        • DOM select
      • JSON
        • Try
      • fetch
      • typeof
      • FormData не включає disabled набори полів
      • FormData, fdata
      • Більше одного відео YouTube на одній сторінці
    • HTML, CSS
      • favicon
      • Деякі спецсимволи
      • meta
      • ASCII table
      • lang
      • Псевдоелементи ::after і ::before
      • Cursor
      • Об использовании нестандартных пробелов
      • Картинка фоном
      • Безпечні веб-шрифти
      • Завжди внизу, незалежно від пропорцій екрану
      • напівпрозорий елемент
      • Символи з тінью
      • SVG (bootstrap)
      • rel = canonical
      • link stylesheet: integrity & crossorigin
      • rel = noopener
    • Bootstrap
      • Form Validate
      • Password show/hide
    • Errors
  • Dev
    • Git
      • clone
      • git-scm (book)
      • git config
        • files .git*
        • core.filemode
        • core.sharedRepository
      • .gitignore
      • .gitkeep
      • Видалити з репозиторію
        • Видалений файл з однієї гілки...
      • Пам’ятка
        • Перегляд історії комітів
        • Скасувати git add
        • revert
        • Скасувати внесені зміни у файл
        • Додати до коміту файл
        • Видалити історію попередніх коммітів, та почати "з нуля"
        • Додати файли в останній коміт
      • Робота з гілками
        • Порівняти гілки
      • Git за полчаса
      • Три розділи проєкту Git
      • Merge conflict
      • Pull error
        • Git Error: You have divergent branches...
      • diff
      • Video
      • Merge скасувати
      • .gitignore: Permission denied
    • GitHub
      • SSH-підключення до GitHub
      • Перенести на сервер локальный репозиторий
      • Перенести на сервер репозиторій разом з історією
      • Створення змісту
    • Security
      • robots.txt
      • Cookies
    • Аутентифікація і cookies
      • ChatGPT
  • data
    • MySQL
      • MyISAM vs InnoDB
      • Типи даних
        • NULL (todo)
        • TIMESTAMP
        • YEAR
        • JSON
        • Требования к памяти для символьных типов
        • Поиск записей в таблице, которым нет соответствия в другой
      • Приклад створення БД, та користувача
        • Права для пользователей
      • Переглянути всі індекси таблиці
      • Копіювання, клонування таблиць
      • TEMPORARY TABLE
      • JOIN
      • ALTER TABLE
      • AUTO_INCREMENT
        • AUTO_INCREMENT у складовому індексі
      • LIMIT
        • Использование MySQL LIMIT
      • 10 Примеров входной загрузки данных из текстового файла в таблицы MySQL
      • Рішення
        • Выявление и удаление несвязанных записей
        • Выборка произвольных записей
        • Коректне сортування українських літер
        • Найти записи, которые присутствуют в одной таблице и отсутствуют во второй
        • Как удобно посмотреть данные...
        • Нахождение "дыр" в нумерации
        • Знайти дубликати полів в одній таблиці
        • Дані колонки 1 табл. перенести в 2 табл.
      • Функції
        • LAST_INSERT_ID()
        • GROUP_CONCAT
        • COUNT + DISTINCT
        • Функции для работы с датами и временем
      • Автоматизируйте создание бэкапов
      • mysqldump
        • Time Zone UTC
      • Результат запиту у файл
      • Результат запиту у змінну
      • Пособие по MySQL на Python
      • Змінні
      • Эмуляция функции row_number() в MySQL
      • Изучаем хранимые процедуры MySQL
      • SELECT DISTINCT
      • Dump всієї бази даних
      • Індекси
      • FOREIGN KEY
      • MAX(), MIN()
      • LENGTH, CHAR_LENGTH
      • Встановлення
    • MariaDB
    • PostgreSQL
      • Работа с базой данных PostgreSQL
      • Работаем с PostgreSQL через командную строку в Linux
    • Domains
      • Життєвий цикл доменів
      • Статус домена
    • SQLite, MySQL и PostgreSQL: сравниваем популярные реляционные СУБД
  • Linux
    • DNS
      • Как в DNS прописать 301 редирект
      • mail
        • SPF
          • Mirohost
        • _dmarc _domainkey
        • DKIM
        • Прописати ключі DKIM в exim
        • Листи з неіснуючим адресатом
    • Server
      • Zomro
        • pip
        • SSH-доступ по ключу (zomro)
        • venv
        • UnicodeEncodeError: 'latin-1' codec can't encode character
        • Mail Ports
        • Редірект з SSL-сертификатом на транзитному сайті
        • Редірект з SSL за допомогою .htaccess
      • Створення нового користувача з привілеями sudo в Ubuntu
      • SSH-доступ по ключу
      • Часовий пояс в Ubuntu 20.04
      • SSH-підключення командний рядок
      • Як встановити Python 3.9 (нижчу) на Ubuntu 22.04
      • Автозагрузка сервисов в Ubuntu
      • Підвищення безпеки SSH
      • Ubuntu Server
        • Art 01
    • Commands
      • adduser
      • apt
      • cat
      • ls
      • tar
      • ln
      • find
      • chmod
      • chown
      • mv
      • dig
      • ping
      • passwd
      • htpasswd
      • umask
      • usermode
      • history
      • cmp
      • chattr +i
    • Config
      • Keyboard
      • windows
      • My kbdswtch
      • Затримка при завантаженні системи
      • Files
        • /etc/resolv.conf
        • /boot/grub/grub.cfg
        • .config/user-dir.dirs
        • /etc/fstab
      • Як встановити шрифти
    • Apache
      • Встановлення
      • Подключить виртуальный хост
      • Файл .htaccess
        • Установка индексного файла
        • Фільтр IP-адрес
        • ModRewrite
          • Заборонити доступ за User-Agent
          • Перенаправити на іншу сторінку
          • Додавати слеш до адреси
        • Включити SSI
        • Виконувати скрипти CGI
        • Тимчасовий перехід з одного домену на інший
      • SSI
      • SSL
      • Відключити старт Apache з системою
      • Помилки
        • Скрипт не працює
        • CGI-скрипт не виводить кирилицю
        • Could not reliably determine
        • Permissions are missing on a component of the path
        • Symbolic link not allowed or link target not accessible
      • AddType, AddLanguage, AddCharset
    • Nginx
      • 301 редирект з www. та http: на https://(без www.)domain
    • Soft
      • SublimeText
        • Plugins
      • Firefox
      • Gwenview
      • inkscape
      • Double Commander
      • nano
      • mc
        • Знайти потрібний файл
      • meld / diffuse
      • hexedit
      • Kazam - відео з екрану
      • VeraCrypt
      • XnView MP
      • LibreOffice
      • xdotool
      • System Load Monitor
      • Battery Monitor
      • qBittorrent
    • Перетворення .RPM в .DEB
    • Bash
      • Конкатенация строк в Bash
      • Page
    • Файлові часові позначки в Linux: atime, mtime, ctime
    • Права доступу для файлів і каталогів
    • Зміна паролю root
    • Быстро удалить огромное количество файлов в каталоге
    • Як узнати версію Linux?
    • USB Flash ext4
    • Clear Cache
    • Доступ до спільної папки на Windows
    • Віртуальні консолі TTY1–TTY6
    • APT. Заборона оновлення
  • Різне
    • GitBook
    • Банковское округление
    • Ім’я користувача Youtube
  • Hard
    • Hardware
      • Acer Extensa
      • Таймер Feron TM22
      • WD My Book World Edition 2Tb
        • FTP
        • SSH
          • Проблеми
        • SSHFS
      • Canon PIXMA E3340
      • Термометри
    • Auto
      • Акумулятор
    • Electro
    • USB Flash recovery
Powered by GitBook
On this page
  • Отправка электронного письма (email) с вложением.
  • Как отправить электронное письмо с помощью smtplib.
  • Отправка письма нескольким адресатам одновременно.
  • Использование строк TO, CC и BCC при отправке email.
  • Добавление вложения/файла с помощью модуля email.
  • Заключение.
  1. Progr
  2. Python
  3. Модулі
  4. email / smtplib

Как отправлять электронные письма с помощью Python

https://docs-python.ru/tutorial/otpravka-email-vlozheniem/

Previousemail / smtplibNextrequests

Last updated 2 years ago

Отправка электронного письма (email) с вложением.

В Стандартной библиотеке Python есть несколько отличных модулей, которые можно использовать для . Это модули email и smtplib. В этом материале не будут рассматриваться API этих двух модулей (объекты и их методы), здесь будут представлены реальные приемы использования этих модулей.

В частности, материал охватывает следующее:

  • .

  • .

  • .

  • .

  • .


Как отправить электронное письмо с помощью smtplib.

Если посмотреть на API модуля smtplib, то сразу становится понятно, как его использовать. Напишем быстрый пример, который показывает, как отправить электронное письмо.

import smtplib

# данные почтового сервиса
user = "your-address@yandex.ru"
passwd = "**********"
server = "smtp.yandex.ru"
port = 587

# тема письма
subject = "Тестовое письмо от Python."
# кому
to = "person@mail.ru"
# кодировка письма
charset = 'Content-Type: text/plain; charset=utf-8'
mime = 'MIME-Version: 1.0'
# текст письма
text = "Отправкой почты управляет Python!"

# формируем тело письма
body = "\r\n".join((f"From: {user}", f"To: {to}", 
       f"Subject: {subject}", mime, charset, "", text))

try:
    # подключаемся к почтовому сервису
    smtp = smtplib.SMTP(server, port)
    smtp.starttls()
    smtp.ehlo()
    # логинимся на почтовом сервере
    smtp.login(user, passwd)
    # пробуем послать письмо
    smtp.sendmail(user, to, body.encode('utf-8'))
except smtplib.SMTPException as err:
    print('Что - то пошло не так...')
    raise err
finally:
    smtp.quit()

Здесь импортируется только модуль smtplib. Две трети этого кода используются для настройки электронной почты. Большинство переменных не требуют пояснений, поэтому рассмотрим только одну переменную body.

'From: your-address@yandex.ru\r\nTo: person@mail.ru\r\n
Subject: Тестовое письмо от Python.\r\nMIME-Version: 1.0\r\n
Content-Type: text/plain; charset=utf-8\r\n\r\n
Отправкой почты управляет Python!'

После этого, устанавливается соединение с сервером электронной почты, а затем вызываете метод smtp.sendmail модуля smtplib для отправки электронной почты. Если сервер электронной почты требует аутентификации, то перед отправкой письма необходимо авторизироваться на этом сервере:

smtp.login(user, passwd)

Обычно, представленный код выше оборачивают в функцию и вызывают ее с некоторыми из этих параметров.

import smtplib

def send_email(from_addr, to_addr, subject, text, encode='utf-8'):
    """
    Отправка электронного письма (email)
    """

    # оставшиеся настройки
    passwd = "**********"
    server = "smtp.yandex.ru"
    port = 587
    charset = f'Content-Type: text/plain; charset={encode}'
    mime = 'MIME-Version: 1.0'
    # формируем тело письма
    body = "\r\n".join((f"From: {from_addr}", f"To: {to_addr}", 
           f"Subject: {subject}", mime, charset, "", text))

    try:
        # подключаемся к почтовому сервису
        smtp = smtplib.SMTP(server, port)
        smtp.starttls()
        smtp.ehlo()
        # логинимся на почтовом сервере
        smtp.login(from_addr, passwd)
        # пробуем послать письмо
        smtp.sendmail(from_addr, to_addr, body.encode(encode))
    except smtplib.SMTPException as err:
        print('Что - то пошло не так...')
        raise err
    finally:
        smtp.quit()

if __name__ == "__main__":
    from_addr = "your-address@yandex.ru"
    to_addr = "person@mail.ru"
    subject = "Тестовое письмо от Python."
    text = "Отправкой почты управляет Python!"
    send_email(from_addr, to_addr, subject, text)

Иногда, часть оставшихся настроек задается файлом конфигурации в создаваемом приложения. Добавим файл конфигурации для хранения информации о сервере и адресе отправителя. Сохраним файл конфигурации как email.ini. Это удобно, если почтовый сервер обновляется и имя меняется, то не надо лезть в код, нужно только изменить файл конфигурации.

[smtp]
server = smtp.yandex.ru
port = 587
email = your-address@yandex.ru
passwd = **********
import os, sys
import smtplib
from configparser import ConfigParser

def send_email(to_addr, subject, text, encode='utf-8'):
    """
    Отправка электронного письма (email)
    """

    base_path = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(base_path, "email.ini")
    # проверка наличия файла `email.ini`
    if os.path.exists(config_path):
        cfg = ConfigParser()
        cfg.read(config_path)
        # извлечение переменных из конфигурации
        server = cfg.get("smtp", "server")
        port = cfg.get("smtp", "port")
        from_addr = cfg.get("smtp", "email")
        passwd = cfg.get("smtp", "passwd")
    else:
        print("Конфигурация не найдена!")
        sys.exit(1)

    charset = f'Content-Type: text/plain; charset={encode}'
    mime = 'MIME-Version: 1.0'
    # формируем тело письма
    body = "\r\n".join((f"From: {from_addr}", f"To: {to_addr}", 
           f"Subject: {subject}", mime, charset, "", text))

    try:
        # подключаемся к почтовому сервису
        smtp = smtplib.SMTP(server, port)
        smtp.starttls()
        smtp.ehlo()
        # логинимся на почтовом сервере
        smtp.login(from_addr, passwd)
        # пробуем послать письмо
        smtp.sendmail(from_addr, to_addr, body.encode(encode))
    except smtplib.SMTPException as err:
        print('Что - то пошло не так...')
        raise err
    finally:
        smtp.quit()

if __name__ == "__main__":
    to_addr = "person@mail.ru"
    subject = "Тестовое письмо от Python."
    text = "Отправкой почты управляет Python!"
    send_email(to_addr, subject, text)

В дальнейшем, следует еще добавить обработчик исключений вокруг вызова ConfigParser.read(), так как файл может существовать, но быть поврежденным, или может не быть разрешения на его открытие, что вызовет исключение.

Отправка письма нескольким адресатам одновременно.

import os, sys
import smtplib
from configparser import ConfigParser

def send_email(to_addr, subject, text, encode='utf-8'):
    """
    Отправка электронного письма (email)
    """

    base_path = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(base_path, "email.ini")
    # проверка наличия файла `email.ini`
    if os.path.exists(config_path):
        cfg = ConfigParser()
        cfg.read(config_path)
        # извлечение переменных из конфигурации
        server = cfg.get("smtp", "server")
        port = cfg.get("smtp", "port")
        from_addr = cfg.get("smtp", "email")
        passwd = cfg.get("smtp", "passwd")
    else:
        print("Конфигурация не найдена!")
        sys.exit(1)
    
    charset = f'Content-Type: text/plain; charset={encode}'
    mime = 'MIME-Version: 1.0'
    # формируем тело письма
    body = "\r\n".join((f"From: {from_addr}", f"To: {', '.join(to_addr)}", 
           f"Subject: {subject}", mime, charset, "", text))

    try:
        smtp = smtplib.SMTP(server, port)
        smtp.starttls()
        smtp.ehlo()
        smtp.login(from_addr, passwd)
        smtp.sendmail(from_addr, to_addr, body.encode(encode))
    except smtplib.SMTPException as err:
        print('Что - то пошло не так...')
        raise err
    finally:
        smtp.quit()

if __name__ == "__main__":
    # список адресов для отправки письма
    to_addr = ["person-one@mail.ru", "person-two@mail.ru"]
    subject = "Тестовое письмо от Python."
    text = "Отправкой почты управляет Python!"
    send_email(to_addr, subject, text)

Использование строк TO, CC и BCC при отправке email.

В этом коде передадим три списка, в каждом из которых по одному адресу электронной почты. Создадим поля CC и BCC точно так же, как и раньше, а также необходимо объединить три списка адресов в один, чтобы передать его методу smtp.sendmail().

import os, sys
import smtplib
from configparser import ConfigParser

def send_email(to_eml, subject, text, cc_eml, bcc_eml, encode='utf-8'):
    """
    Отправка электронного письма (email)
    """

    base_path = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(base_path, "email.ini")
    # проверка наличия файла `email.ini`
    if os.path.exists(config_path):
        cfg = ConfigParser()
        cfg.read(config_path)
        # извлечение переменных из конфигурации
        server = cfg.get("smtp", "server")
        port = cfg.get("smtp", "port")
        from_addr = cfg.get("smtp", "email")
        passwd = cfg.get("smtp", "passwd")
    else:
        print("Конфигурация не найдена!")
        sys.exit(1)

    # извлечение переменных из конфигурации
    server = cfg.get("smtp", "server")
    port = cfg.get("smtp", "port")
    from_addr = cfg.get("smtp", "email")
    passwd = cfg.get("smtp", "passwd")
    charset = f'Content-Type: text/plain; charset={encode}'
    mime = 'MIME-Version: 1.0'
    # формируем тело письма
    body = "\r\n".join((f"From: {from_addr}", f"To: {', '.join(to_eml)}", 
           f"CC: {', '.join(cc_eml)}", f"BCC: {', '.join(bcc_eml)}"
           f"Subject: {subject}", mime, charset, "", text))
    all_emails = to_eml + cc_eml + bcc_eml

    try:
        smtp = smtplib.SMTP(server, port)
        smtp.starttls()
        smtp.ehlo()
        smtp.login(from_addr, passwd)
        smtp.sendmail(from_addr, all_emails, body.encode(encode))
    except smtplib.SMTPException as err:
        print('Что - то пошло не так...')
        raise err
    finally:
        smtp.quit()

if __name__ == "__main__":
    to_addr = ["person@mail.ru"]
    cc_addr = ["person-one@mail.ru"] 
    bcc_addr = ["person-two@mail.ru"]
    subject = "Тестовое письмо от Python."
    text = "Отправкой почты управляет Python!"
    send_email(to_addr, subject, text, cc_addr, bcc_addr)

Добавление вложения/файла с помощью модуля email.

Модуль email делает добавление вложений чрезвычайно простым.

В этом примере, в функцию отправки электронной почты добавим новый аргумент file_to_attach, а также создадим и добавим заголовок Content-Disposition и объект MIMEMultipart. Заголовок можно создать и добавить в любое время, но, до добавления вложения.

Письмо формируется в объекте MIMEMultipart() путем добавления необходимых полей, как ключей словаря. Если необходимо указать дату формирования письма, нужно использовать функцию formatdate модуля email, чтобы вставить правильно отформатированную дату.

Чтобы добавить тело сообщения, как вложение, нужно создать экземпляр MIMEText(text). Далее добавляется вложение, как результат чтения файла вложения в режиме 'rb' (байтовый объект) MIMEBase(data). Обратите внимание, что для отправки сообщения, необходимо преобразовать словарный объект msg в строку методом msg.as_string().

import os, sys
import smtplib
from configparser import ConfigParser

from configparser import ConfigParser
from email import encoders
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate

def send_email(to_addr, subject, text, file_to_attach,  
                cc_addr, bcc_addr):
    """
    Отправка электронного письма с вложением
    """

    base_path = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(base_path, "email.ini")
    # проверка наличия файла `email.ini`
    if os.path.exists(config_path):
        cfg = ConfigParser()
        cfg.read(config_path)
        # извлечение переменных из конфигурации
        server = cfg.get("smtp", "server")
        port = cfg.get("smtp", "port")
        from_addr = cfg.get("smtp", "email")
        passwd = cfg.get("smtp", "passwd")
    else:
        print("Конфигурация не найдена!")
        sys.exit(1)

    # извлечение переменных из конфигурации
    server = cfg.get("smtp", "server")
    port = cfg.get("smtp", "port")
    from_addr = cfg.get("smtp", "email")
    passwd = cfg.get("smtp", "passwd")
    # формируем тело письма
    msg = MIMEMultipart()
    msg["From"] = from_addr
    msg["Subject"] = subject
    msg["Date"] = formatdate(localtime=True)
    if text:
        # текст письма отправляем как вложение
        msg.attach(MIMEText(text))
    msg["To"] = ', '.join(to_emails)
    msg["cc"] = ', '.join(cc_emails)
    emails = to_emails + cc_emails

    attachment = MIMEBase('application', "octet-stream")
    header = 'Content-Disposition', f'attachment; filename="{file_to_attach}"'
    try:
        with open(file_to_attach, "rb") as fh:
            data = fh.read()
        attachment.set_payload(data)
        encoders.encode_base64(attachment)
        attachment.add_header(*header)
        msg.attach(attachment)
    except IOError:
        print(f"Ошибка при открытии файла вложения {file_to_attach}")

    try:
        smtp = smtplib.SMTP(server, port)
        smtp.starttls()
        smtp.ehlo()
        smtp.login(from_addr, passwd)
        smtp.sendmail(from_addr, emails, msg.as_string())
    except smtplib.SMTPException as err:
        print('Что - то пошло не так...')
        raise err
    finally:
        smtp.quit()

if __name__ == "__main__":
    to_addr = ["person@mail.ru"]
    cc_addr = ["person-one@mail.ru"] 
    subject = "Тестовое письмо от Python."
    text = "Отправкой почты управляет Python!"
    file_attach = '/path/to/file_attach'
    send_email(to_addr, subject, text, file_attach, cc_addr)

Заключение.

Теперь вы знаете, как отправлять электронные письма с помощью Python. Для тех, кто любит мини-проекты, нужно вернуться и добавить более подробную обработку ошибок в часть кода smtp.sendmail() на случай, если во время процесса произойдет что-то странное. Одним из примеров может быть добавление исключений SMTPAuthenticationError или SMTPConnectError и т. д.

Можно усилить обработку ошибок во время прикрепления файла, чтобы отловить другие ошибки. Наконец, можно взять различные списки адресов электронной почты и создать один нормализованный список, в котором будут удалены дубликаты. Это особенно важно, если читать список адресов из файла.

Для создания этой переменной используется метод , который объединяет все предыдущие переменные в одну строку, где каждая строка заканчивается символом возврата каретки ('/r') плюс новая строка ('/n'). В итоге, переменная body, будет выглядеть как-то так:

Получился очень простой файл конфигурации, в котором есть только один раздел с пометкой [smtp]. Чтобы прочитать файл конфигурации и превратить его в словарь Python, будем использовать . Вот обновленная версия кода.

Добавили небольшую проверку в код. Сначала получаем путь, по которому находится сам скрипт отправки электронной почты base_path. Затем объединяем этот путь с именем email.ini, чтобы получить полный путь к файлу конфигурации. Потом проверяем наличие этого файла и в случае успешной проверки создаем объект , если нет, то выводим сообщение и выходим из сценария.

Для отправки письма нескольким адресатам одновременно необходимо вместо одного email-адреса, записанного в качестве строки, предоставить адресов электронной почты. Чтобы это работало, нужно создать строку, разделенную запятыми, в части f"To: {', '.join(to_addr)}", при создании переменной body, а также передать список адресов электронной почты методу smtp.sendmail().

создания и отправки электронных писем
Как отправить электронное письмо с помощью smtplib
Как отправить письмо сразу на несколько адресов
Как отправить электронную почту, используя строки CC и BCC
Как добавить вложение и тело письма с помощью модуля email
Заключение
str.join()
модуль ConfigParser
ConfigParser
список