Як надсилати електронні листи через Gmail на Python?

Автоматизація розсилки електронних листів за допомогою Python

Відправка великої кількості електронних листів вручну – це досить трудомістка процедура. Існують спеціалізовані сервіси, які дозволяють здійснювати масову розсилку, але що, якби можна було створити власний, налаштований скрипт для цих цілей? Чи не було б це чудовою ідеєю? Саме цим ми і займемося – розробимо сценарій на Python для надсилання електронних повідомлень.

Python має вбудовану бібліотеку під назвою smtplib, призначену для роботи з електронною поштою. Ця бібліотека базується на протоколі SMTP (Simple Mail Transfer Protocol), який є стандартом для передачі електронних повідомлень між серверами.

Налаштування Gmail для роботи зі скриптами

У цьому прикладі ми використаємо Gmail як постачальника послуг електронної пошти. Google має обмеження на вхід у систему за допомогою скриптів, тому нам потрібно буде змінити деякі налаштування безпеки облікового запису, щоб надати скрипту доступ. Зміни параметрів безпеки облікового запису Gmail можуть створити ризики, надаючи можливість несанкціонованого доступу. Рекомендується створити для цих цілей окремий обліковий запис Gmail. Щоб дозволити менш безпечним програмам доступ до облікового запису, перейдіть за посиланням та увімкніть відповідний параметр.

Якщо ви не бажаєте змінювати налаштування безпеки, то можна скористатися API Google для авторизації в обліковому записі Gmail. Інформація про використання Google API для аутентифікації доступна тут.

Покрокова інструкція для надсилання електронного листа

Для відправки повідомлення за допомогою smtplib необхідно виконати ряд дій. Розглянемо їх детально перед тим, як перейдемо до написання коду.

#1. Встановлення з’єднання з SMTP-сервером

Кожен постачальник поштових послуг має власне доменне ім’я та номер порту SMTP-сервера. Нам потрібно буде вказати ці дані у скрипті. Для Gmail SMTP-сервер має доменне ім’я smtp.gmail.com та порт 465.

Для забезпечення безпеки з’єднання ми будемо використовувати SSL-шифрування, яке є надійнішим за TSL. Якщо потрібно використовувати TSL, використовуйте порт 587 замість 465. Зверніть увагу, що доменне ім’я SMTP-сервера залежить від постачальника послуг електронної пошти.

Код для встановлення з’єднання виглядає так:

server = smtplib.SMTP_SSL(smtp_server_domain_name, port, context=ssl_context)

#2. Авторизація

Після успішного з’єднання з SMTP-сервером ми можемо авторизуватися, використовуючи адресу електронної пошти та пароль за допомогою методу login об’єкта SMTP. Код виглядає наступним чином:

server.login(sender_email, password)

#3. Відправка електронного листа

Після входу можна відправляти повідомлення, використовуючи метод sendmail. Повідомлення має бути відформатоване наступним чином:

Тема: your_subject_for newline mail_content

Пробіли у цьому випадку не потрібні, вони наведені для кращого розуміння формату. Ось приклад коду:

server.sendmail(sender_mail, email, f"Subject: {subject}n{content}")

#4. Завершення сеансу

Не забудьте закрити з’єднання з SMTP-сервером, використавши метод quit().

Ми розглянули окремі кроки відправлення електронного листа. Розглянемо повний приклад коду на Python:

import smtplib, ssl

class Mail:

    def __init__(self):
        self.port = 465
        self.smtp_server_domain_name = "smtp.gmail.com"
        self.sender_mail = "GMAIL_ADDRESS"
        self.password = "SECURE_PASSWORD"

    def send(self, emails, subject, content):
        ssl_context = ssl.create_default_context()
        service = smtplib.SMTP_SSL(self.smtp_server_domain_name, self.port, context=ssl_context)
        service.login(self.sender_mail, self.password)
        
        for email in emails:
            result = service.sendmail(self.sender_mail, email, f"Subject: {subject}n{content}")

        service.quit()


if __name__ == '__main__':
    mails = input("Enter emails: ").split()
    subject = input("Enter subject: ")
    content = input("Enter content: ")

    mail = Mail()
    mail.send(mails, subject, content)

У цьому коді ми створили клас Mail з методом send для надсилання повідомлень. Використання класу робить код більш структурованим і зрозумілим. Метод send реалізує всі необхідні кроки відправки електронної пошти.

Отже, за допомогою цього скрипту на Python ми успішно відправили електронний лист.

Відправка HTML-повідомлень

А що робити, якщо потрібно надіслати лист у форматі HTML? Чи це можливо? Звичайно. Для цього ми використаємо бібліотеку email.mime, яка є частиною стандартної бібліотеки Python.

MIME (Multipurpose Internet Mail Extensions) – це стандарт, що дозволяє розширити можливості електронних листів, підтримуючи додатки, відео, зображення та інші типи контенту.

З модуля email.mime нам знадобляться два класи: MIMEText та MIMEMultipart. Розглянемо їх призначення:

#1. MIMEText

Клас MIMEText використовується для формування HTML-контенту нашого повідомлення. Ми створюємо екземпляр класу, передаючи HTML-код і тип контенту. Ось приклад:

html_content = MIMEText(html_template, 'html')

Оскільки не всі поштові клієнти підтримують відтворення HTML, рекомендується створити два екземпляри MIMEText: для звичайного тексту і для HTML.

#2. MIMEMultipart

Клас MIMEMultipart спрощує форматування електронного листа, дозволяючи додавати тему, адреси відправника та одержувача, тощо. Ми передаємо вміст, сформований за допомогою MIMEText, до MIMEMultipart за допомогою методу attach.

Важливо створити екземпляр MIMEMultipart з аргументом ‘alternative’, що дозволить відображати як простий текст, так і HTML. Розглянемо приклад відправки HTML-повідомлення:

import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


class Mail:

    def __init__(self):
        ...

    def send(self, emails):
        ssl_context = ssl.create_default_context()
        service = smtplib.SMTP_SSL(self.smtp_server_domain_name, self.port, context=ssl_context)
        service.login(self.sender_mail, self.password)
        
        for email in emails:
            mail = MIMEMultipart('alternative')
            mail['Subject'] = 'techukraine.net Celebrations'
            mail['From'] = self.sender_mail
            mail['To'] = email

            text_template = """
            techukraine.net

            Hi {0},
            We are delighted announce that our website hits 10 Million views this month.
            """
            html_template = """
            <h1>techukraine.net</h1>

            <p>Hi {0},</p>
            <p>We are delighted announce that our website hits <b>10 Million</b> views last month.</p>
            """

            html_content = MIMEText(html_template.format(email.split("@")[0]), 'html')
            text_content = MIMEText(text_template.format(email.split("@")[0]), 'plain')

            mail.attach(text_content)
            mail.attach(html_content)

            service.sendmail(self.sender_mail, email, mail.as_string())

        service.quit()


if __name__ == '__main__':
    mails = input("Enter emails: ").split()

    mail = Mail()
    mail.send(mails)

Крім того, можна додати приховану копію листа, використовуючи атрибут ‘Bcc’ екземпляра MIMEMultipart.

Додавання вкладень

Вкладеннями можуть бути зображення, PDF-файли, документи, таблиці тощо. Для додавання вкладень ми скористаємося класом MIMEBase з модуля email.mime. Розглянемо, як додати вкладення до нашого листа:

import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from pathlib import Path


class Mail:

    def __init__(self):
        ...

    def send(self, emails):
        ## login...
        
        for email in emails:
            ## MIMEMultipart instance

            ## text and html templates

            ## MIMEText instances

            ## attaching messages to MIMEMultipart

            ## attaching an attachment
            file_path = "techukraine.net-logo.png"
            mimeBase = MIMEBase("application", "octet-stream")
            with open(file_path, "rb") as file:
                mimeBase.set_payload(file.read())
            encoders.encode_base64(mimeBase)
            mimeBase.add_header("Content-Disposition", f"attachment; filename={Path(file_path).name}")
            mail.attach(mimeBase)

            ## sending mail

        service.quit()


if __name__ == '__main__':
    mails = input("Enter emails: ").split()

    mail = Mail()
    mail.send(mails)

Масова розсилка

У попередніх прикладах ми використовували цикл для відправки одного і того ж повідомлення кільком одержувачам. Це підходить у випадках, коли ви не хочете, щоб одержувачі знали про інших одержувачів. Якщо вам потрібно надіслати той же лист одночасно 1000 членам групи, то використання циклу буде неефективним. У такому випадку можна додати декілька електронних адрес у поле “Кому”. Розглянемо, як це зробити за допомогою Python:

Необхідно об’єднати список електронних адрес у рядок, розділений комою та пробілом. Для цього можна скористатися методом join. Ось приклад:

", ".join(emails)

Замініть поле “Кому” у попередніх скриптах на цей рядок, і ви отримаєте можливість відправляти масові повідомлення.

Підсумок

Існують також сторонні бібліотеки для надсилання електронних листів, такі як Envelopes, Yagmail, Flanker, які спрощують процес написання коду. Ви можете ознайомитися з ними для подальших експериментів.

Тепер ви маєте можливість автоматизувати свою електронну пошту за допомогою скриптів на Python. Структура скриптів може відрізнятися залежно від вашого конкретного завдання. У цьому посібнику були розглянуті різні сценарії надсилання електронних листів, які ви можете використовувати для своїх потреб. За основу було взято інформацію з цієї статті.

Успішного кодування! 🙂