Jak wysyłać e-maile przez Gmaila w Pythonie?

Photo of author

By maciekx

Wysyłanie wielu wiadomości e-mail pojedynczo może być nużące i czasochłonne. Na rynku dostępne są różne rozwiązania firm zewnętrznych, umożliwiające zbiorcze rozsyłanie korespondencji.

A gdyby tak stworzyć własny, dedykowany skrypt do automatyzacji tego procesu?

Brzmi interesująco, prawda?

Oczywiście! W dalszej części artykułu pokażemy, jak napisać skrypt w języku Python, który pozwoli na wysyłkę e-maili.

Python oferuje bibliotekę o nazwie `smtplib`, która jest wykorzystywana do obsługi wysyłania wiadomości. Działa ona w oparciu o protokół SMTP (Simple Mail Transport Protocol), który jest standardem wykorzystywanym do przesyłania e-maili.

Konfiguracja konta Gmail

W tym przykładzie użyjemy Gmaila jako dostawcy usług poczty elektronicznej. Google domyślnie blokuje możliwość logowania się do konta za pomocą skryptów. Aby umożliwić skryptom dostęp do naszego konta Gmail, musimy zmienić pewne ustawienia bezpieczeństwa.

Zmiana ustawień bezpieczeństwa konta Gmail może stwarzać potencjalne zagrożenie, ponieważ ułatwia dostęp do konta osobom trzecim. Dlatego zalecamy utworzenie nowego konta Gmail. Następnie, należy przejść do ustawień i aktywować opcję „Zezwalaj na mniej bezpieczne aplikacje”.

Jeżeli nie chcesz korzystać z powyższej opcji, możesz użyć API Google do uwierzytelniania konta Gmail. Szczegóły dotyczące korzystania z Google API znajdziesz tutaj.

Kroki niezbędne do wysłania wiadomości e-mail

Aby wysłać wiadomość za pomocą biblioteki `smtplib`, należy wykonać kilka określonych kroków. Najpierw omówimy je teoretycznie, a następnie napiszemy kod.

#1. Nawiązywanie połączenia z serwerem SMTP

Każdy dostawca usług poczty elektronicznej dysponuje unikalną nazwą domeny oraz portem serwera SMTP. W skrypcie musimy wykorzystać te dane odpowiadające naszemu dostawcy. Dla Gmaila są to: `smtp.gmail.com` (nazwa domeny) oraz `465` (port).

Dla połączenia z serwerem SMTP użyjemy szyfrowania SSL, ponieważ jest ono bezpieczniejsze od TSL. W przypadku użycia TSL należy wykorzystać port `587`, zamiast `465`. Nazwa domeny serwera SMTP będzie się różnić w zależności od usługodawcy.

Kod niezbędny do połączenia z serwerem SMTP wygląda następująco:

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

#2. Logowanie do serwera

Po pomyślnym połączeniu z serwerem SMTP możemy się zalogować, wykorzystując adres e-mail oraz hasło. Użyjemy metody `login` obiektu SMTP. Kod wygląda następująco:

server.login(sender_email, password)

#3. Wysyłka wiadomości

Po pomyślnym zalogowaniu możemy przejść do wysłania wiadomości, korzystając z metody `sendmail`. Pamiętaj, by sformatować wiadomość w następujący sposób:

Temat: Twój_temat_wiadomości\nTreść_wiadomości

Puste przestrzenie nie są wymagane; służą jedynie dla klarowności powyższego formatu. Przykładowy kod:

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

#4. Wylogowanie

Nie można zapomnieć o zamknięciu połączenia z serwerem SMTP.

Omówiliśmy kroki niezbędne do wysyłania wiadomości e-mail za pomocą Pythona. Niemniej jednak, nie zaprezentowaliśmy jeszcze pełnego kodu. Przejdźmy zatem do niego.

import smtplib, ssl

class Mail:

    def __init__(self):
        self.port = 465
        self.smtp_server_domain_name = "smtp.gmail.com"
        self.sender_mail = "ADRES_GMAIL"
        self.password = "TWOJE_HASŁO"

    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("Wprowadź adresy e-mail: ").split()
    subject = input("Wprowadź temat: ")
    content = input("Wprowadź treść: ")

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

Stworzyliśmy klasę o nazwie `Mail`, która zawiera metodę `send` do wysyłania wiadomości e-mail. Implementacja klasy zależy od potrzeb – w tym przypadku zwiększa ona czytelność kodu. W metodzie `send` umieściliśmy wszystkie kroki omówione wcześniej.

Gratulacje! Właśnie udało Ci się wysłać e-mail przy pomocy skryptu Pythona.

Wiadomości w formacie HTML

Co, jeśli zależy Ci na wysyłaniu wiadomości w formacie HTML? Czy jest to możliwe?

Oczywiście, że tak! Do tego celu użyjemy biblioteki `email.mime`, która jest wbudowana w Pythonie.

MIME to standard rozszerzający format wiadomości e-mail, umożliwiający przesyłanie nie tylko tekstu, ale także plików, obrazów, wideo itp.

Z modułu `email.mime` wykorzystamy dwie klasy: `MIMEText` i `MIMEMultipart`. Poniżej znajduje się ich krótkie omówienie.

#1. MIMEText

Klasa `MIMEText` jest przeznaczona do przechowywania treści wiadomości w formacie HTML. Tworzymy instancję klasy `MIMEText`, przekazując treść HTML oraz typ zawartości. Przykładowy kod:

html_content = MIMEText(html_template, 'html')

Niektóre serwery pocztowe mogą mieć problemy z poprawnym renderowaniem HTML. Dlatego zalecane jest utworzenie dwóch instancji klasy `MIMEText` – jednej dla zwykłego tekstu, a drugiej dla HTML.

#2. MIMEMultipart

Klasa `MIMEMultipart` upraszcza formatowanie wiadomości, w tym wprowadzenie tematu, adresów nadawcy i odbiorcy. Treść wygenerowaną za pomocą `MIMEText` dołączymy do obiektu `MIMEMultipart` przy użyciu metody `attach`.

Musimy pamiętać, aby utworzyć instancję `MIMEMultipart` z argumentem „alternative”, umożliwiającym renderowanie tekstu lub HTML. Poniżej przykład wysyłania wiadomości z treścią 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'] = 'newsblog.pl Świętuje'
            mail['From'] = self.sender_mail
            mail['To'] = email

            text_template = """
            newsblog.pl

            Witaj {0},
            Z radością informujemy, że nasz serwis osiągnął 10 milionów wyświetleń w tym miesiącu.
            """
            html_template = """
            <h1>newsblog.pl</h1>

            <p>Witaj {0},</p>
            <p>Z radością informujemy, że nasz serwis osiągnął <b>10 milionów</b> wyświetleń w poprzednim miesiącu.</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("Wprowadź adresy e-mail: ").split()

    mail = Mail()
    mail.send(mails)

Możemy dodać ukrytą kopię wiadomości (Bcc), wykorzystując odpowiedni atrybut w instancji `MIMEMultipart`.

Dodawanie załączników

Załącznikami mogą być obrazy, dokumenty PDF, arkusze kalkulacyjne itp. Do dodawania załączników wykorzystamy klasę `MIMEBase`, która jest częścią modułu `email.mime`.

Dodajmy załącznik do naszej wiadomości:

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:
            ## instancja MIMEMultipart

            ## szablony tekstu i HTML

            ## instancje MIMEText

            ## dołączenie wiadomości do MIMEMultipart

            ## dołączanie załącznika
            file_path = "newsblog.pl-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)

            ## wysyłanie maila

        service.quit()


if __name__ == '__main__':
    mails = input("Wprowadź adresy e-mail: ").split()

    mail = Mail()
    mail.send(mails)

Wysyłanie wiadomości do wielu odbiorców jednocześnie

Do tej pory korzystaliśmy z pętli, aby wysłać tę samą wiadomość do wielu odbiorców (w sytuacji, gdy nie chcemy, aby adresaci wiedzieli o sobie nawzajem).

Załóżmy, że chcemy wysłać tę samą wiadomość do 1000 osób należących do tej samej grupy jednocześnie. W takiej sytuacji pętla nie będzie optymalnym rozwiązaniem. Rozwiązaniem może być dodanie wielu adresów e-mail w polu „Do”. Jak to zrobić w skrypcie Pythona?

Musimy połączyć listę adresów e-mail w jeden ciąg znaków, oddzielając je przecinkami oraz spacjami. W tym celu możemy wykorzystać metodę `join`. Kod:

", ".join(emails)

Teraz wystarczy zastąpić pole „Do” w naszym skrypcie powyższym ciągiem znaków. I gotowe! Wysłaliśmy wiadomość do wielu odbiorców jednocześnie.

Podsumowanie

W Pythonie dostępnych jest szereg zewnętrznych bibliotek ułatwiających wysyłanie wiadomości e-mail, takich jak: Envelopes, Yagmail, Flanker. Ułatwiają one pisanie skryptów przy użyciu zaledwie kilku linijek kodu. Zachęcamy do ich przetestowania.

Dzięki zdobytym informacjom możesz samodzielnie zautomatyzować wysyłkę wiadomości e-mail przy pomocy Pythona. Struktura wysyłania maili będzie zależeć od Twoich indywidualnych potrzeb. W niniejszym poradniku omówiliśmy różne scenariusze. Możesz dowolnie modyfikować zaprezentowane skrypty, dostosowując je do własnych wymagań. Inspiracją dla tego artykułu był ten artykuł.

Miłego kodowania! 🙂


newsblog.pl