0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonを使ってGmailでメールを送信する

Posted at

この記事について

Python を使って Gmail 経由でメールを送信する方法をまとめました。
Google アカウント側で必要な設定と、Python でのメール送信コードを順に解説します。

準備

アプリパスワードを取得する

PythonプログラムからGmailでメールを送信するにはGoogleアカウント側でアプリパスワードを発行しておく必要があります。手順は次の通りです。

  1. Googleアカウントの「セキュリティとログイン」に移動する
  2. 2段階認証プロセスを有効化する
  3. 画面上部の検索バーで「アプリパスワード」と入力して、設定画面に移動する
    image.png
  4. 任意のアプリ名を入力する
  5. 生成されたアプリパスワードを控えておく

環境変数を設定

パスワードや自分のメールアドレスを.envで管理するためにpython-dotenvをインストールします。

pip install python-dotenv

環境変数の設定ファイルとして.envファイルを作成します。

.env
MY_MAIL_ADDRESS=<自分のメールアドレス>
APP_PASS=<控えておいたアプリパスワード>
SMTP_SERVER='smtp.gmail.com'
SMTP_PORT=465

SMTP_PORTについて

GoogleのドキュメントによるとGmailのSMTPサーバーのポートは465と587が利用できます。465はImplicit TLS用、587はSTARTTLS用(最初は平文で通信、その後TLSに切替)として利用します。暗号化方式によって後述のソースコードも変わるので注意してください。(ここでそれぞれについて解説しています。)

プログラムの作成

プログラム全体

ここでは、メールの作成から送信までを行うPythonプログラムの全体像を示します。dotenv以外はPythonの標準ライブラリを利用しています。プログラムの簡易さを優先してエラーハンドリングなどは省略しました。

send_email.py
import os

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

from dotenv import load_dotenv

load_dotenv()

def create_message(to_email: str, subject: str, body: str) -> MIMEMultipart:
    """
    multipart形式のMIMEメッセージを作成
    Args:
        to_email (str): 送信先メールアドレス
        subject (str): メールの件名
        body (str): メールの本文
    Returns:
        MIMEMultipart: 作成したメールメッセージ
    """
    msg = MIMEMultipart()  # 初期化

    # メッセージを作成
    msg['Subject'] = subject
    msg['From'] = os.getenv('MY_MAIL_ADDRESS')
    msg['To'] = to_email
    msg.attach(MIMEText(body, 'plain'))
    return msg

def send_email(msg: MIMEMultipart):
	"""
    SMTPサーバーを使用してメールを送信
    Args:
        msg (MIMEMultipart): 送信するメールメッセージ
    """
    # SMTP_PORTが465の場合はsmtplib.SMTP_SSLを587の場合はsmtplib.SMTPを利用
    # このコードは465(Implicit TLS)の場合
    with smtplib.SMTP_SSL(os.getenv('SMTP_SERVER'), os.getenv('SMTP_PORT')) as server:
        server.login(os.getenv('MY_MAIL_ADDRESS'), os.getenv('APP_PASS'))
        server.send_message(msg)

if __name__ == '__main__':
    to_email = '<送り先のメールアドレス>'
    subject = 'Pythonによる自動送信テスト'
    body = 'このメールはPythonから自動送信しています。'

    # メッセージの作成
    message = create_message(
        to_email=to_email,
        subject=subject,
        body=body
    )
    # メールの送信
    send_email(message)

envファイルの読み込み

from dotenv import load_dotenv

load_dotenv()

この部分の記述によって環境変数を設定で作成した.envファイルの内容を環境変数として利用できるようになります。以降はos.getenv()で環境変数を呼び出します。

メッセージ作成関数

メールのメッセージを作成する関数create_message()では、メッセージをMIME形式で作成します。今回は本文のみですが添付ファイルなどに対応しているmultipart形式で作成しています。

def create_message(to_email: str, subject: str, body: str) -> MIMEMultipart:
    """
    multipart形式のMIMEメッセージを作成
    Args:
        to_email (str): 送信先メールアドレス
        subject (str): メールの件名
        body (str): メールの本文
    Returns:
        MIMEMultipart: 作成したメールメッセージ
    """
    msg = MIMEMultipart()  # 初期化

    # メッセージを作成
    msg['Subject'] = subject
    msg['From'] = os.getenv('MY_MAIL_ADDRESS')
    msg['To'] = to_email
    msg.attach(MIMEText(body, 'plain'))
    return msg

メール送信関数

メールを送信する関数send_email()では、SMTPサーバーに接続してcreate_message()で作成したメールを送信します。

def send_email(msg: MIMEMultipart):
	"""
    SMTPサーバーを使用してメールを送信
    Args:
        msg (MIMEMultipart): 送信するメールメッセージ
	"""
    # SMTP_PORTが465の場合はsmtplib.SMTP_SSLを587の場合はsmtplib.SMTPを利用
    # このコードは465(Implicit TLS)の場合
    with smtplib.SMTP_SSL(os.getenv('SMTP_SERVER'), os.getenv('SMTP_PORT')) as server:
        server.login(os.getenv('MY_MAIL_ADDRESS'), os.getenv('APP_PASS'))
        server.send_message(msg)

上記で述べたように、GMailのSMTPサーバーでは暗号方式としてImplicit TLS(ポート番号465)とSTARTTLS(ポート番号587)が利用可能で、暗号化方式によって呼び出すメソッドが異なることに注意してください。

STARTTLS利用版のコード

STARTTLSを使ってメールを送る場合は次のようにソースコードを書き替えます。その際に.envファイルのSMTP_PORTを587に変更してください。

STARTTLS利用版
def send_email(msg: MIMEMultipart):
    """
    SMTPサーバーを使用してメールを送信
    Args:
        msg (MIMEMultipart): 送信するメールメッセージ
    """
    # smtplib.SMTP_SSLではなくsmtplib.SMTPを利用
    with smtplib.SMTP(os.getenv('SMTP_SERVER'), os.getenv('SMTP_PORT')) as server:
        server.starttls()  # 追加
        server.login(os.getenv('MY_MAIL_ADDRESS'), os.getenv('APP_PASS'))
        server.send_message(msg)

withブロックの部分について

smtplib.SMTP_SSL(もしくはsmtplib.SMTP)でwithブロックを利用することでブロック終了時にサーバーとの接続を自動で閉じることができます。手動で接続を閉じる場合はserver.quit()を利用します。

明示的にサーバー接続を閉じる場合
def send_email(msg: MIMEMultipart):
    """
    SMTPサーバーを使用してメールを送信
    Args:
        msg (MIMEMultipart): 送信するメールメッセージ
    """
    server = smtplib.SMTP_SSL(os.getenv('SMTP_SERVER'), int(os.getenv('SMTP_PORT')))
    server.login(os.getenv('MY_MAIL_ADDRESS'), os.getenv('APP_PASS'))
    server.send_message(msg)
    server.quit()  # サーバーとの接続を明示的に閉じる

最後に

今回はPythonを利用したメール送信について解説してみました。参考になれば幸いです。

参考資料

GmailのIMAP:https://developers.google.com/workspace/gmail/imap/imap-smtp?hl=ja

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?