Pythonでメール送信: SMTPとAPIの使い方を徹底解説

On 4月 02, 2025
8min read
Aleksandr Varnin Full Stack Developer @ Railsware
Veljko Ristić Content Manager @ Mailtrap
How to Send an Email in Python

Pythonでメールを送りたいとお考えですか?本記事ではPythonのメール送信に関するあらゆる項目を網羅し、コード例、セキュリティ、メールテストもご紹介していきます。

さあ、メールを配信する準備はできていますか?
Mailtrapを無料で試す

smtplibのセットアップ

Pythonの`smtplib`モジュールを使うと、SMTPサーバーとやり取りするためのシンプルなインターフェースを利用できるようになり、お使いのアプリケーションから直接メールを送るプロセスが簡単になります。

このセクションでは`smtplib`のインポート方法、サーバー用のSMTPオブジェクトの作成、メール送信のための主要な関数の使用方法について説明いたします。それでは、Pythonスクリプトにメール機能を統合する方法を学んでいきましょう。

組み込みのsmtplibモジュールは、次のステートメントでインポートできます。

import smtplib

後でメールを送るためには、1つのSMTP(Simple Mail Transfer Protocol)オブジェクトを作成します。

smtpObj = smtplib.SMTP(host, port)

パラメータの詳細

  • host 任意の引数でSMTPサーバーが実行されているホストです。ホストのIPアドレスまたはドメイン名を指定できます。
  • port host 引数が指定されている場合は、SMTPサーバーがリッスンしているポートを指定します。
  • local_hostname 使われているSMTPサーバーがローカルマシンで実行されている場合、localhost を指定します。

SMTPオブジェクトにはメッセージ送信用のインスタンスメソッド_`sendmail`_があり、3つのパラメータを受け取れます。

  • sender 送信者のアドレスを含む文字列。
  • receivers 各受信者の文字列を含むリスト。
  • message RFCに準拠した文字列形式のメッセージ。
smtpObj.sendmail(sender, receivers, message)

メールモジュールが正しくインポートされていることを確認し、クラスや引数の完全な詳細を得るには、インタラクティブなPythonセッションで次のコマンドを入力します。

help(smtplib)

その他のSMTPオブジェクト(例:smtp.ehlo; smtp.send_message(msg)など)や応用については、Pythonドキュメントをご参照ください。

次のセクションではMailtrapのメール配信システムにおけるメール配信API/SMTP機能を使って、Pythonでメールを送る方法を説明いたします。最初にSMTPメソッドを紹介し、その後にPython SDKでの方法を解説しますので、ぜひご活用下さい。

SMTPを使ってメールを送る

このやり方は上記のsmtplibセクションで説明した内容と非常に似ていますが、カスタムのSMTP資格情報を設定する必要があります。この記事ではすでにMailtrapにサインアップしていて、ドメインも確認済みであることを前提としています。

Mailtrapのサインアップとドメイン確認がまだの場合は、詳細ガイドをご覧ください。

またMailtrapでsmtplibを使ってPythonでメールを送る方法についての解説動画も、ぜひご確認ください。

ご留意事項 以下のコードにはMailtrapのダミー資格情報(サーバーエンドポイントを除く)が含まれています。実際の資格情報に置き換えてください。

ここではMailtrapのSMTPサービスを使ってPythonでプレーンテキストのメールを送るための簡単なスクリプトをご紹介します。

import smtplib
from email.mime.text import MIMEText

# 設定
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
receiver_email = "new@サンプル.com"

# プレーンテキストの内容
text = """\
こんにちは。
Mailtrapブログの新しい投稿をぜひチェックしてください。
SMTPサーバーのテスト: クラウドベースそれともローカル?
https://mailtrap.io/ja/blog/cloud-or-local-smtp-server/
お役立ちコンテンツについてのご意見もお聞かせください!
"""

# MIMETextオブジェクトの作成
message = MIMEText(text, "plain")
message["Subject"] = "プレーンテキストメール"
message["From"] = sender_email
message["To"] = receiver_email

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # 接続を安全に保つ
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('送信完了')

概要

  • インポートと設定 Pythonの標準ライブラリからメール送信用のモジュール(smtplibおよびMIMEText)をインポートします。
  • メールサーバーの設定 SMTPサーバーの詳細(サーバーアドレス、ポート番号、認証情報)を設定します。
  • メールの内容 プレーンテキストのみを保持するMIMETextメッセージを作成します。後で、HTMLとプレーンテキストのバージョンを同時に含める方法も説明いたします。
  • メールの送信 withステートメントを使ってSMTPサーバーへの接続を適切に閉じ、メールを送信します。

おまけのアドバイス ログイン情報やサーバー情報などの機密データをスクリプトにハードコーディングするのはセキュリティリスクなので、環境変数を使って機密情報を保存することをお勧めします。そうすれば異なる環境間(開発、テスト、本番)でのコードの柔軟性が向上します。

HTMLメールを送る

(HTMLメールを送る方法についてさらに学びたい場合は、専用のチュートリアルをご覧ください。)

HTMLメールを送るためにスクリプトを調整する方法(複数の受信者を含む)を以下で説明いたします。修正版のスクリプトは下記の通りです。

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

# 設定
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
receiver_email = "new1@サンプル.com"

# メール内容
subject = "添付ファイルなしのHTMLメール"
html = """\
<html>
  <body>
    <p>こんにちは。<br>
   これは <b>テスト</b> メールです。<a href="https://www.python.org">Python</a>を使って送信しました。</p>
  </body>
</html>
"""

# マルチパートメッセージを作成し、ヘッダーを設定
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# HTML部分を添付
message.attach(MIMEText(html, "html"))

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('送信完了')

概要

  • HTMLコンテンツの添付 HTMLコンテンツはMIMEText(html, "html")を使ってメールメッセージに添付されます。第2引数にhtmlを指定し、この部分のメールがHTMLとして解釈されることをメールクライアントに伝えます。

複数の受信者にメールを送る

ここでは上記のスクリプトを再利用し、受信者アドレスの取り扱い方法を調整します。

import smtplib
from email.mime.text import MIMEText

# 設定
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
# 受信者のメールアドレスのリスト
receiver_emails = ["new1@サンプル.com", "new2@サンプル.com", "new3@サンプル.com"]

# プレーンテキストの内容
text = """\
こんにちは。
Mailtrapブログの新しい投稿をぜひチェックしてみてください。
SMTPサーバーのテスト: クラウドベースそれともローカル?
https://mailtrap.io/ja/blog/cloud-or-local-smtp-server/
お役立ちコンテンツについてのご意見もお聞かせください!
"""

# MIMETextオブジェクトの作成
message = MIMEText(text, "plain")
message["Subject"] = "プレーンテキストメール"
message["From"] = sender_email
# 受信者のメールアドレスリストをカンマ区切りの文字列に結合
message["To"] = ", ".join(receiver_emails)

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # 接続を安全に保つ
    server.login(login, password)
    server.sendmail(sender_email, receiver_emails, message.as_string())

print('送信完了')

概要 元のplaintextのスクリプトと比べた変更点は以下の通りです。

  • 複数受信者の設定 receiver_email変数をreceiver_emailsに変更し、受信者のメールアドレスをリストで指定します。
  • Toヘッダーの設定 MIMETextメッセージオブジェクトのToヘッダーには、受信者のメールアドレスリストをカンマで区切った文字列として設定します。こうすればメールヘッダーにすべての受信者が正しく表示されます。
    • ご留意事項 一部のメールクライアント(Outlook、Yahoo、Gmailなど)は各受信者に他の受信者も表示する場合があります。プライバシー上の理由から、CCBCCを使えば、この点は修正できます。
  • ループによるメールの送信 メールは一度に送るのではなく、receiver_emailsリスト内の各受信者に対して個別に送信します。

添付ファイル付きのメールを送る

添付ファイルの場合はMIMEMultipartを使う必要があるため、マルチパート形式のメールが必要になります。またファイルを添付するためにはMIMEBaseクラスを使います。以下がスクリプトです。

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# 設定
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
receiver_email = "new@サンプル.com"  # 単一受信者

# メール内容
subject = "添付ファイル付きのメール"
body = "こんにちは。\nこれは添付ファイル付きのテストメールです。"

# マルチパートメッセージを作成し、ヘッダーを設定
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# 本文をメールに追加
message.attach(MIMEText(body, "plain"))

# 添付ファイルのパスを指定
filename = "ファイル/パス/を/ここに入力.pdf"  # 正しいパスに変更してください

# ファイルをバイナリモードで開く
with open(filename, "rb") as attachment:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())

# ファイルをASCII文字でエンコードしてメールで送信
encoders.encode_base64(part)

# ヘッダーをキー/値のペアとして添付ファイルパートに追加
part.add_header("Content-Disposition", f"attachment; filename= {filename}")

# メッセージに添付ファイルを追加
message.attach(part)

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('送信完了')

概要

  • MIMEMultipartの使用 本文だけでなく、添付ファイルを含むマルチパート形式のメールにするため、MIMETextの代わりにMIMEMultipartを使います。
  • 添付ファイルの追加
    • ファイルの準備 添付ファイルはバイナリモードrbで開き、内容が読み込まれます。
    • MIMEBaseオブジェクト 添付ファイル用にMIMEBaseオブジェクトが作成され、タイプの設定はapplication/octet-streamです。このタイプは汎用的なバイナリストリームで、あらゆるファイルタイプに適しています。メールクライアントは通常これを添付ファイルとして扱います。
    • エンコード ファイルの内容はbase64でエンコードされ、メール送信が安全に行われます。encoders.encode_base64(part)関数を使います。
    • ヘッダーの追加 添付ファイルにはファイル名などを示すヘッダーが追加されます(Content-Dispositionヘッダー)。
    • メッセージへのファイルの添付 添付ファイルのパートはmessage.attach(part)を使ってメッセージに添付されます。

埋め込み画像付きのメールを送る

HTMLコンテンツ内に画像を直接埋め込む場合、MIMEImageクラスを使います。画像を直接メール内に埋め込むと、添付ファイルとしてではなく、コンテンツの一部として表示できます。やり方は以下の通りです。

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email import encoders
import os

# 設定
port = 587
smtp_server = "live.smtp.mailtrap.io"
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
receiver_email = "new1@サンプル.com"

# 埋め込み画像を含むHTMLコンテンツ
html = """\
<html>
  <body>
    <p>こんにちは。<br>
    埋め込み画像付きの<b>テスト</b>メールです。<br>
    ここに画像があります。<img src="cid:画像1">.</p>
  </body>
</html>
"""

# マルチパートメッセージを作成し、ヘッダーを設定
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = "埋め込み画像付きのHTMLメール"

# HTML部分をメッセージに添付
message.attach(MIMEText(html, "html"))

# 画像ファイルのパスを指定
image_path = "画像の/ファイル/パスを/入力.jpg"  # 正しいパスに変更してください

# 画像ファイルをバイナリモードで開く
with open(image_path, 'rb') as img:
    # 画像ファイルを添付
    msg_img = MIMEImage(img.read(), name=os.path.basename(image_path))
    # Content-IDヘッダーを設定し、HTML内で参照
    msg_img.add_header('Content-ID', '<画像1>')
    # メッセージに画像を添付
    message.attach(msg_img)

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())

print('送信完了')

概要

  • HTMLコンテンツの更新 HTMLコンテンツは<img>タグのsrc属性にContent-ID (cid)を使い、画像を参照します。このcidは、添付画像のContent-IDヘッダー値と一致する必要があります。
  • 画像の埋め込み
    • MIMEImageの使用 画像ファイルの処理にはMIMEImageクラスを使います。このクラスは画像の添付に特化しています。
    • 画像ファイルを開ける 埋め込む画像をバイナリモードで開きます。
    • MIMEImageオブジェクトの作成 バイナリの画像データからMIMEImageオブジェクトを作成します。このオブジェクトが画像添付部分になります。
    • Content-IDヘッダー MIMEImageオブジェクトにContent-IDヘッダーを設定し、src属性によりHTMLコンテンツの<img>タグで参照されます。このリンクにより、画像はダウンロード可能な添付としてではなく、メール本文内への直接埋め込みが可能になります。
    • 画像の添付 他のパーツと同様に、MIMEImageオブジェクトが複数のファイルに添付されます。

非同期のメール送信

非同期のメール送信をするには、Pythonのasyncioライブラリとaiosmtplib(非同期のSMTPクライエント)を使います。

このやり方だとプログラムの実行をブロックせずにメールを送信でき、特に複数のメールを送信したり、並行タスクを処理したりする場合に効率的です。

簡単な例として、添付ファイルおよび埋め込み画像なしのプレーンテキストのメールを1人の受信者に送信してみます。やり方は以下の通りです。

まずaiosmtplibをインストールします:

pip install aiosmtplib

スクリプトは以下の通りです。

import asyncio
from email.mime.text import MIMEText
from aiosmtplib import SMTP

async def send_email_async(sender_email, receiver_email, smtp_server, port, login, password, subject, body):
    message = MIMEText(body)
    message["From"] = sender_email
    message["To"] = receiver_email
    message["Subject"] = subject
    
    async with SMTP(hostname=smtp_server, port=port) as smtp:
        await smtp.login(login, password)
        await smtp.send_message(message)

async def main():
    # メール設定
    smtp_server = "live.smtp.mailtrap.io"
    port = 587
    sender_email = "mailtrap@サンプル.com"
    receiver_email = "new@サンプル.com"  # 送信先
    login = "api"  # Mailtrapで生成されたログイン
    password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード
    subject = "非同期メールテスト"
    body = "これは非同期で送信されたプレーンテキストメールです。"
    
    await send_email_async(sender_email=sender_email, receiver_email=receiver_email, smtp_server=smtp_server, port=port, login=login, password=password, subject=subject, body=body)
    print("非同期でメールを送信しました。")

if __name__ == "__main__":
    asyncio.run(main())

概要

  • 非同期関数の定義 async defを使って非同期関数を定義します。
  • 非同期操作 asyncioaiosmtplibを活用し、非同期でSMTP接続、ログイン、メール送信を行います。この方法だとメール送信がブロックされないため、ネットワーク処理を実行する際に応答性の維持が必要なアプリケーションの場合、特に便利です。
  • スクリプトの実行 mainの非同期関数がメールの詳細を設定し、send_email_asyncを呼び出してメールを送信します。asyncio.run(main())は非同期の実行をブート処理する形で、Pythonで効率よく非同期タスクを実行する方法を示しています。

メールの一斉送信

上記のコードはトランザクションメールのエンドポイントであるlive.smtp.mailtrap.ioを使っています。でもMailtrapのEmail Delivery Platformを使えば、同一プラン内で別のストリーム(bulk.smtp.mailtrap.io)を使ってメールを一斉送信できます。

Mailtrap Bulk Stream settings

唯一異なる点はホスト(エンドポイント)なので、スクリプトの調整が必要です。トランザクションとバルクメールの資格情報はほとんど同じでも、インフラは異なる旨ご留意ください。異なるインフラを使うことで、到達可能性とメール管理の改善につながります。

なお変更点をご説明するために、所定のSMTPエンドポイントを使ったシンプルなスクリプトを以下の通り作成しました。

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

# MailtrapのBulk SMTPサーバー設定
smtp_server = "bulk.smtp.mailtrap.io"
port = 587
login = "api"  # Mailtrapで生成されたログイン
password = "1a2b3c4d5e6f7g"  # Mailtrapで生成されたパスワード

sender_email = "mailtrap@サンプル.com"
receiver_email = "new@サンプル.com"  # 単一受信者

# Plain Text用のMIMETextメッセージを作成
subject = "Bulk SMTP経由のプレーンテキストメール"
body = "このメールはMailtrapのBulk SMTPサーバーを使って送信されました。"

# MIMEMultipartメッセージを作成し、ヘッダーを設定
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject

# テキストパートを添付
message.attach(MIMEText(body, "plain"))

# メールの送信
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()  # 接続をセキュリティで保護
    server.login(login, password)  # SMTPサーバーにログイン
    server.sendmail(sender_email, receiver_email, message.as_string())  # メールを送信

print('メールの送信が成功しました。')

概要

  • MIMEMultipartの使用 プレーンテキストのメールを単一受信者に送る場合でも、将来的に添付ファイルやHTMLコンテンツを追加する可能性があるため、MIMEMultipartを使っています。必要に応じてシンプルなMIMETextを利用することも可能です。
  • メール送信 server.sendmailの呼び出しは簡単です。送受信者を特定し、メッセージのオブジェクトを文字列形式に変換して送ります。

プロからのヒント 環境変数や外部設定ファイルでSMTPの資格情報を管理している場合、トランザクション用と一括送信用の設定を個別に管理することが推奨されます。

APIを使ってメールを送る

簡単に統合を行うために、Mailtrapは公式のPython SDKをご用意しました。◀️GitHubリンクをご参照ください 。プレーンテキストのメール送信、複数の受信者への送信、メールの一斉送信などの方法をご紹介しております。

なおMailtrapでは非同期のメール送信はあいにくサポートしておらず、APIを使う場合ではあまり意味がありません。そのため、ここでは非同期メール送信には触れていません。

またMailtrapでのドメイン接続と確認が必要であることを覚えておいてください。詳しくはこちらの詳細ガイドと解説動画をご覧ください。

設定が完了したらPythonアプリに戻り、以下のコマンドでMailtrapの公式Python SDKをインストールします。

pip install mailtrap

(※ パッケージのバージョンが3.6以上である旨、ご確認ください。)

次にMailオブジェクトを作成し、Mailtrapの資格情報(例:メールアドレスと名前)を変数に入力します。アドレスには確認済みの送信ドメインを指定します。

import mailtrap as mt

# mailオブジェクトを作成
mail = mt.Mail(
    sender=mt.Address(email="mailtrap@サンプル.com", name="Mailtrapのテスト"),
    to=[mt.Address(email="あなたのメアド@メール.com")],
    subject="素晴らしい!",
    text="Mailtrapでテストメールを送信しました。おめでとうございます!",
)

# クライアントを作成して送信
client = mt.MailtrapClient(token="api-キーを-入力")
client.send(mail)

さらにAPIトークンでクライアントを作成する必要があります。Mailtrapアカウントの「Settings」ドロップダウンを展開し、「API Tokens」タブを選択して、トークンの横の「Copy」をクリックしてトークンをコピーします。

次に以下のコマンドでメールを送信します。

# クライアントを作成して送信
client = mt.MailtrapClient(token="api-キーを-入力")
client.send(mail)

次に、異なるユースケースにおけるSDKの活用方法をご紹介いたします。

以下はプレーンテキストのメールを送るシンプルなスクリプトです。

from mailtrap import Mail, Address, MailtrapClient

# プレーンテキストのメール用に基本的な情報を持つMailオブジェクトを作成
mail = Mail(
    # 送信者のメールアドレスとオプションの名前を指定
    sender=Address(email="mailtrap@サンプル.com", name="Mailtrapのテスト"),
    # 1つ以上の受信者を指定。ここでは単一の受信者
    to=[Address(email="あなたのメアド@メール.com", name="あなたのお名前")],
    # メールの件名
    subject="シンプルなプレーンテキストメール",
    # メールのプレーンテキスト内容
    text="これはMailtrap SDKを使って送信されたプレーンテキストのメールです。シンプルで分かりやすいです。",
    # オプション:Mailtrapサービス内での管理や仕分けがしやすくなるようカテゴリを指定
    category="テスト",
    # オプション:プレーンテキストメールでは不要ですが、追加のヘッダーは指定可能
    headers={"X-Example-Header": "HeaderValue"}
)

# MailtrapClientをAPIトークンで初期化
client = MailtrapClient(token="api-キーを-入力")

# クライアントのsendメソッドを使ってメールを送信
client.send(mail)

print("プレーンテキストメールが正常に送信されました。")

概要

  • クラスのインポート MailAddressMailtrapClientクラスのみをMailtrapライブラリからインポートし、プレーンテキストメール送信に集中しています。
  • Mailオブジェクトの作成
    • Mail コンストラクタを使ってメールオブジェクトを作成します。
    • sender Addressクラスを使って、送信者のメールアドレスと名前を指定します。
    • to 各受信者に対してAddressオブジェクトのリストを指定します。プレーンテキストメールの場合、通常1人以上の受信者がリストされます。
    • subject メールの件名。
    • text メールのプレーンテキスト形式の内容。
    • categoryheaders これらはオプションフィールドで、さらなるカテゴリ化やカスタムヘッダーの作成が可能になります。プレーンテキストメールの送信の場合、厳密には必要ではありませんが、Mailtrapサービス内の管理や技術的な用途、またはメールクライエントの処理において役立つこともあります。
  • メールの送信
    • MailtrapClientのインスタンスを作成し、APIトークンで認証します。
    • MailtrapClientsendメソッドを呼び出し、mailオブジェクトを引数として渡してメールを送信します。
    • 最後に、メールが送信されたことを示す確認メッセージが表示されます。

HTMLメールを送る

MailオブジェクトのhtmlパラメータにHTMLコンテンツを指定して、HTMLメールを送るスクリプトに変更します。

from mailtrap import Mail, Address, MailtrapClient

# HTMLメール送信用のMailオブジェクトを作成
mail = Mail(
    sender=Address(email="mailtrap@サンプル.com", name="Mailtrapのテスト"),
    to=[Address(email="recipient@email.com", name="受信者の名前")],
    subject="HTMLメールの件名をここに入力",
    text="HTMLをレンダリングしないメールクライアント向けのフォールバックテキストです",
    html="""
    <!DOCTYPE html>
    <html>
        <head>
            <title>メールの件名</title>
        </head>
        <body>
            <h1>こんにちは、皆さん!</h1>
            <p>これはMailtrapのPython SDKから送信された<strong>HTMLメール</strong>です。</p>
            <p>こちらのリンクをご覧ください。<a href="https://サンプル.com">サンプル.comを訪問</a></p>
        </body>
    </html>
    """,
    # 必要に応じてカテゴリやカスタムヘッダーを追加できます
    category="HTMLメール",
    headers={"X-Custom-Header": "Value"}
)

# MailtrapClientをAPIトークンで初期化
client = MailtrapClient(token="api-キーを-入力")

# メールを送信
client.send(mail)

print("HTMLメールが正常に送信されました。")

概要

  • HTMLコンテンツ MailオブジェクトのhtmlパラメータにHTMLコンテンツを指定します。これはHTMLを表示できるメールクライアントによりレンダリングされます。
  • フォールバックのテキストコンテンツ HTMLをレンダリングできないメールクライアントや、受信者がプレーンテキストを好む場合のために、プレーンテキストバージョンを指定します。
  • メール送信 HTMLコンテンツが定義されているので、メール送信に関するその他のプロセスは同様です。

複数の受信者にメールを送る

これから受信者の部分を複数の受信者に対応するように変更していきます。

以下のスクリプトではToフィールド、Cc(カーボンコピー)、Bcc(ブラインドカーボンコピー)を使った複数受信者の追加方法についても触れています。メソッドはシンプルで、ロジックも明確なので、ここでは概要セクションを割愛いたします。

from mailtrap import Mail, Address, MailtrapClient

# 複数の受信者を含むMailオブジェクトを作成。CcおよびBccアドレスも含む
mail = Mail(
    # 送信者のメールアドレスとオプションの名前を指定
    sender=Address(email="mailtrap@サンプル.com", name="Mailtrapのテスト"),
    # "To"フィールドに複数の受信者を指定
    to=[
        Address(email="受信者1@メール.com", name="受信者1人目"),
        Address(email="受信者2@メール.com", name="受信者2人目"),
    ],
    # "Cc"フィールドに受信者を追加
    cc=[
        Address(email="cc1@メール.com", name="CC 受信者1人目"),
        Address(email="cc2@メール.com", name="CC 受信者2人目"),
    ],
    # "Bcc"フィールドに受信者を追加
    bcc=[
        Address(email="bcc1@メール.com", name="BCC 受信者1人目"),
        Address(email="bcc2@メール.com", name="BCC 受信者2人目"),
    ],
    # メールの件名
    subject="複数の受信者へのメール",
    # プレーンテキストの内容
    text="このメールは、CcおよびBccアドレスを含む複数の受信者に送信されます。",
    # 必要に応じてカテゴリやカスタムヘッダーを追加可能
    category="大量メール",
    headers={"X-Custom-Header": "Value"}
)

# MailtrapClientをAPIトークンで初期化
client = MailtrapClient(token="api-キーを-入力")

# クライアントのsendメソッドでメールを送信
client.send(mail)

print("複数の受信者にメールが正常に送信されました。")

添付ファイル付きのメールを送る

ここではAttachmentクラスを使ってファイルをメールに添付する方法を中心に説明いたします。この例では一般的なファイルを添付しますが、ファイルタイプに関わらずアプローチは同様です。

from mailtrap import Mail, Address, MailtrapClient, Attachment, Disposition
import base64
from pathlib import Path

# 添付したいファイルを準備
file_path = Path("ファイル/パスを/ここに/入力.pdf")  # ファイルのパスを更新してください
file_content = file_path.read_bytes()  # ファイル内容をバイトとして読み込む

# ファイル内容をbase64でエンコード
encoded_content = base64.b64encode(file_content)

# 添付ファイル付きのMailオブジェクトを作成
mail = Mail(
    sender=Address(email="mailtrap@サンプル.com", name="Mailtrapのテスト"),
    to=[Address(email="受信者@メール.com", name="受信者の名前")],
    subject="添付ファイル付きのメール",
    text="このメールには添付ファイルが含まれています。確認してください。",
    # 添付ファイルを定義
    attachments=[
        Attachment(
            content=encoded_content,  # ファイルのbase64エンコードされた内容
            filename=file_path.name,  # メール内で表示されるファイル名
            disposition=Disposition.ATTACHMENT,  # ファイルが添付ファイルであることを示す
            mimetype="application/pdf",  # ファイルのMIMEタイプ
        )
    ],
)

# MailtrapClientをAPIトークンで初期化
client = MailtrapClient(token="api-キーを-入力")

# メールを送信
client.send(mail)

print("添付ファイル付きのメールが正常に送信されました。")

概要

  • ファイルの準備 添付したいファイルのパスを指定し、バイナリ形式で内容を読み込みます。エンコードと転送には、バイナリモード (‘read_bytes()’メソッド)が必須です。
  • base64エンコード メールプロトコルはバイナリに対応していないので、ファイル内容をbase64でエンコードする必要があります。このエンコードは、メールで安全に送信できるテキスト形式にバイナリデータを変換してくれます。‘base64.b64encode’メソッドはこのために使用されます。
  • 添付ファイルの作成 複数のパラメータでAttachmentクラスのインスタンスを作成します。
    • content ファイルのbase64エンコードされた内容。
    • filename メールに表示されるファイル名。
    • disposition Disposition.ATTACHMENTを指定し、ファイルが埋め込み画像のようにインラインではなく、添付ファイルであることを示します。
    • mimetype ファイルのMIMEタイプを指定して、クライアントがファイルをどのように扱うかを判断できるようにします。PDFの場合はapplication/pdfです。

埋め込み画像付きのメールを送る

ここではHTMLコンテンツ内に直接表示される画像を添付します。通常、画像を添付してContent-ID (cid)で参照すると、HTML内で埋め込み画像として表示できます。以下はその方法です。

from mailtrap import Mail, Address, MailtrapClient, Attachment, Disposition
import base64
from pathlib import Path

# 画像のパスを指定
image_path = Path("画像の/ファイル/パスを/入力.jpg")
image_content = image_path.read_bytes()  # 画像コンテンツをバイト型で読み込む

# 画像コンテンツをbase64でエンコード
encoded_image = base64.b64encode(image_content)

# HTMLコンテンツと埋め込み画像を含むMailオブジェクトを作成
mail = Mail(
    sender=Address(email="mailtrap@サンプル.com", name="Mailtrapテスト"),
    to=[Address(email="受信者@サンプル.com", name="受信者の名前")],
    subject="埋め込み画像付きメール",
    text="HTMLをレンダリングしないメールクライアント用のフォールバックテキストです。",
    html="""
    <!DOCTYPE html>
    <html>
        <body>
            <h1>こんにちは、皆さん!</h1>
            <p>このメールには埋め込み画像が含まれています。</p>
            <!-- HTML内で画像を埋め込むために 'cid:image_cid' をsrc属性に使用 -->
            <img src="cid:image_cid">
        </body>
    </html>
    """,
    attachments=[
        Attachment(
            content=encoded_image,
            filename=image_path.name,
            disposition=Disposition.INLINE,  # 添付ファイルをインラインとしてマーク
            mimetype="image/jpeg",  # 画像のMIMEタイプ
            content_id="image_cid",  # HTMLのsrc属性で参照するContent-ID
        )
    ],
)

# MailtrapClientをAPIトークンで初期化
client = MailtrapClient(token="api-キーを-入力")

# メールを送信
client.send(mail)

print("埋め込み画像付きメールが正常に送信されました。")

概要

  • 画像の準備 画像を添付する前に、その内容をバイト型で読み込み、base64でエンコードします。このエンコードは、メールコンテンツ(および添付ファイル)をテキスト形式で安全に送るために必須です。
  • HTMLコンテンツ Mailオブジェクトのhtmlパラメータには<img>タグが含まれており、src属性には画像添付ファイルのContent-IDを参照するためのcid:スキームが使われています。これによりHTMLコンテンツ内に画像を直接埋め込めます。
  • 画像の添付 Attachmentクラスを使って、以下のパラメータで画像を添付します。
    • content base64でエンコードされた画像コンテンツ。
    • filename 画像ファイルの名前。画像を表示できない場合、一部のメールクライアントではこれが代わりに使われます。
    • disposition Disposition.INLINEに設定し、HTMLコンテンツと一緒にインラインで表示されることを指定します。
    • mimetype 画像のMIMEタイプ(例: image/jpeg)を指定します。これによりメールクライアントはファイルの適切な処理方法を理解しやすくなります。
    • content_id htmlのsrc属性で参照するための固有のIDです。
    • メールの送信 メールを送るプロセスはこれまでと同様です。

メールの一斉送信

Mailtrapのメール配信システムでは、トランザクションメールだけでなく同一プラン内でメールの一斉送信もできます。この機能を使うにはストリームを選択し、APIボタンを押してPython統合を選択します。

MailtrapのAPIを使ったメール一斉送信の設定

以下の手順で設定を進めます。

  1. requestsライブラリがインストールされているか確認します。インストールされていない場合は、次のコマンドでインストールします。
pip install requests
  1. メールの詳細を指定したJSONペイロードを構築し、toフィールドで複数の受信者を指定します。
  1. requestsライブラリを使ってMailtrapのBulk APIエンドポイントにPOSTリクエストを送信し、認証ヘッダーとペイロードを指定します。以下はサンプルスクリプトです。
import requests
import json

def send_mailtrap_email(payload):
    url = "https://bulk.api.mailtrap.io/api/send"
    headers = {
      "Authorization": "Bearer お使いの_api_トークン",  # MailtrapのAPIトークンに置き換え
          "Content-Type": "application/json"
        }

        response = requests.post(url, headers=headers, data=json.dumps(payload))
        return response.text

    payload = {
        "from": {"email": "mailtrap@mailtrapデモ.com", "name": "Mailtrapのテスト"},
        "to": [{"email": "受信者@サンプル.com"}],  # 必要に応じて受信者を追加
        "subject": "さすがですね!",
        "text": "Mailtrapでテストメールを送信していただきありがとうございます!",
        "category": "インテグレーションテスト"
}

response_text = send_mailtrap_email(payload)
print(response_text)

概要

  • payload payloadはMailtrapのBulk APIで期待されるJSON構造に合わせた辞書で、送信者、受信者、件名、本文などのメールの詳細を指定できます。
  • send_mailtrap_email メール送信処理をカプセル化した関数です。入力としてペイロードを受け取り、JSON形式に変換し、MailtrapのBulk APIにPOSTリクエストを送信します。

メール送信のセキュリティに関する考慮事項

メール送信を自動化して、頻繁に多数の受信者に送信する際には、特にSMTPメソッドを使う場合、追加のセキュリティ対策を講じることが推奨されます。

ここではスクリプトに資格情報をハードコーディングしない方法やエラー処理についてのベストプラクティスをいくつか紹介いたします。以下の対策は、メールプロバイダー(SendGrid、SES、Gmailアカウントなど)に関わらず適用されます。

機密情報に環境変数を使う

環境変数はアプリケーションコードの外部で構成設定や機密情報を管理するための安全な方法です。

Pythonでは、`os`モジュールを使って環境変数にアクセスできます。

import os

smtp_server = os.getenv("SMTP_SERVER", "default.smtp.server")
login = os.getenv("SMTP_LOGIN")
password = os.getenv("SMTP_PASSWORD")

# SMTP接続の設定での使用例
# smtp.login(login, password)

実行前に、オペレーティングシステムで環境変数を設定します。LinuxやmacOSのターミナルでは、以下のように一時的に設定できます。

export SMTP_SERVER=live.smtp.mailtrap.io
export SMTP_LOGIN=あなたの_ログイン
export SMTP_PASSWORD=あなたの_パスワード

Windowsでは、コマンドラインで以下のように設定します。

set SMTP_SERVER=live.smtp.mailtrap.io
set SMTP_LOGIN=あなたの_ログイン
set SMTP_PASSWORD=yあなたの_パスワード

エラー処理

以下は、ネットワークエラーや認証エラーなど、メール送信プロセス中に発生する可能性のある予期しないエラーを管理する方法です。

try:
    # メール送信を試行
    server.sendmail(sender_email, recipient_email, message.as_string())
except smtplib.SMTPException as e:
    print(f"SMTPエラーが発生しました: {e}")
except Exception as e:
    print(f"エラーが発生しました: {e}")

SSLを使う

smtplib.SMTP_SSLを使ってメールを送る基本的な概要は以下の通りです。

import smtplib
from email.mime.text import MIMEText


# 設定
port = 465
smtp_server = "live.smtp.mailtrap.io"
login = "username"
password = "password"

sender_email = "送信者@登録済みの_ドメイン.com"
receiver_email = "受信者@gmail.com"

text = """\
こんにちは。
ご興味があるコンテンツを、ぜひお知らせください!
"""

message = MIMEText(text, "plain")
message["Subject"] = "プレーンテキストメール"
message["From"] = sender_email
message["To"] = receiver_email

with smtplib.SMTP_SSL(smtp_server, port) as server:
    server.login(login, password)
    server.sendmail(sender_email, receiver_email, message.as_string())
    print("メールが正常に送信されました!")

外部設定ファイルを使う

SMTPサーバーの詳細やメールアドレスなどの構成データを外部ファイルや環境変数に保存すると、スクリプトのセキュリティと柔軟性を向上できます。より複雑な設定の場合は、JSONファイルなどを使うのも一つの方法です。

  • JSON構成ファイルの例 (config.json)
{
    "smtp_server": "live.smtp.mailtrap.io",
    "smtp_port": 587,
    "login": "あなたの_ログイン",
    "password": "あなたの_パスワード"
}
  • 構成ファイルの読み込み方法
import json

with open('config.json', 'r') as config_file:
    config = json.load(config_file)

smtp_server = config.get('smtp_server')
smtp_port = config.get('smtp_port')
login = config.get('login')
password = config.get('password')

ヒント:Googleアカウントからメールを送信し、GmailのSMTPサーバー(smtp.gmail.com)をご利用になりたい場合は、こちらの記事で詳細をご覧ください。

テスト環境でのメール送信とメール送信テスト

新しいアプリを作成したり、新機能を追加したりする際、特に初めて実施する場合はテストサーバーで試行することが重要です。以下、その理由を簡単に説明いたします。

  1. テスト中に友人や顧客の受信ボックスにメールが送信される心配がありません。これは一斉メール送信やメールデータベースを操作する際に特に重要です。
  2. テストメールで自分の受信ボックスがいっぱいになることを防げます。
  3. ドメインがスパムとしてブロックリストに登録されるリスクを軽減できます。

テスト用SMTPサーバー環境は、実際のサードパーティのWebサーバーの動作を模倣しています。以下の例ではMailtrapのメール送信テストを使い、SMTPトラフィックをキャプチャし、実際の受信者に届く前にメールを検査してデバッグします。

またメール送信テスト機能を使うと、HTML/CSSの検証、メール内容の分析、txt形式と内容のプレビュー、スパムスコアの評価も可能です。設定は簡単で、アプリで生成された認証情報をコピーしてコードに貼り付けるだけです。

ご留意事項 ここではSMTPとAPIの方法を個別に取り上げていきます。Pythonを使ったテストに関する詳細なチュートリアルが必要な場合は、こちらの記事をご参照ください。

SMTP

Mailtrapにアクセスし、「Email Testing」から「My Inbox」を選択します。SMTP設定タブで「Show credentials」をクリックすると、テスト用の認証情報が表示されます。

Mailtrapのメール送信テストSMTPの設定

以下のようにコードに組み込んで実際に使ってみましょう。

import smtplib
port = 2525 
smtp_server = "sandbox.smtp.mailtrap.io"
login = "1b2c3d4e5d66f" # Mailtrapで生成されたログイン
password = "1b2c3d4e5d66f" # Mailtrapで生成されたパスワード

Mailtrapを使うとさらに簡単に設定できます。「SMTP Settings」タブ のIntegrations (統合) セクションに移動し、Mailtrapの認証情報を含むシンプルなテキストメッセージ用テンプレートを取得します。

要注意 コード内のスニペットは安全のためダミーの認証情報を使っています。実際の認証情報をコピーして貼り付けてください。

Pythonコードに対して送信元と送信先の情報を指示するメール送信の最も基本的なやり方は、sendmail() インスタンスメソッドです。ここではこの方法をご紹介しますが、DjangoやFlaskとの統合も可能です。

Mailtrapのメール送信の統合 smtplib

以下の例を見て、エラーハンドリングを追加してみましょう(#の後にある説明をご参照ください)。エラーを検出するには、tryexceptブロックを使います。例外の一覧についてはこちらのドキュメントをご参照ください。

# 必要なモジュールをインポートします
import smtplib
from socket import gaierror

# SMTPサーバーの設定を定義します
port = 2525 
smtp_server = "sandbox.smtp.mailtrap.io"
login = "1b2c3d4e5d66f" # Mailtrapで生成されたログイン情報を貼り付け
password = "1b2c3d4e5d66f"  # Mailtrapで生成されたパスワードを貼
# 送信者と受信者のメールアドレスを指定
sender = "from@サンプル.com"
receiver = "mailtrap@サンプル.com"
# メッセージの内容を記入(件名と本文の間には二重改行 \n を使用)
message = f"""\
Subject: Mailtrap、こんにちは
To: {receiver}
From: {sender}

これはPythonで送る最初のメッセージです。"""

try:
    #上記で指定した認証情報でメールを送信
    with smtplib.SMTP(smtp_server, port) as server:
        server.login(login, password)
        server.sendmail(sender, receiver, message)
    # メールが正常に送信されたか、または修正が必要なエラーを報告
    print('送信されました')
except (gaierror, ConnectionRefusedError):
    print('サーバーへの接続に失敗しました。接続設定が正しくない可能性があります')
except smtplib.SMTPServerDisconnected:
    print('サーバーへの接続に失敗しました。ユーザー名またはパスワードが間違っていますか?')
except smtplib.SMTPException as e:
    print('SMTPエラーが発生しました: ' + str(e))

Shellに「Sent (送信されました)」という結果が表示されたら、Mailtrapの受信トレイにメッセージが表示されるはずです。

MailtrapのPythonテストメッセージ

ローカル環境で作業を進める場合は、ローカルSMTPデバッグサーバーを利用するのも一つの方法です。Pythonにはsmtpdモジュールが用意されており、DebuggingServer機能を使うと、送るメッセージを破棄し、stdoutに出力してくれます。なお、すべてのオペレーションシステムに対応しています。

SMTPサーバーを localhost:1025 に設定します。

python -m aiosmtpd -n -l localhost:1025

ポート番号25でSMTPメールサーバーを実行するには、ルート権限が必要です。

sudo python -m aiosmtpd -n -l localhost:25

これでコードが正しく動作するかどうかを確認し、問題があれば指摘してくれます。ただしHTMLメールテンプレートのレンダリングは確認できません。

API

APIテストの完全な詳細については、APIドキュメントをご覧ください。以下では、Python 3を使った手順をステップごとに説明いたします。

  1. http.client.HTTPSConnection を使って、Mailtrapのメール送信テストのAPIエンドポイントへの接続を確立します。
  2. 受信者(toccbcc)、送信者(from)、件名、テキスト内容、添付ファイルやカスタム変数など、メールの内容をJSONペイロードとして定義します。
  3. POSTリクエストをMailtrapのメール送信テストAPIに対して実行し、ペイロードと必要なヘッダー(認証用のAPIトークンを含む)を送信します。例は以下の通りです。
import http.client
import json

def test_send_email():
    conn = http.client.HTTPSConnection("sandbox.api.mailtrap.io")
    
    payload = {
        "to": [{"email": "田中_ゆうき@サンプル.com", "name": "田中ゆうき"}],
        "cc": [{"email": "斉藤_あきら@サンプル.com", "name": "斉藤あきら"}],
        "bcc": [{"email": "鈴木_まさみ@サンプル.com", "name": "鈴木まさみ"}],
        "from": {"email": "営業@サンプル.com", "name": "サンプル営業チーム"},
        "attachments": [
            {
                "content": "base64_encoded_content_here",
                "filename": "index.html",
                "type": "text/html",
                "disposition": "attachment"
            }
        ],
        "custom_variables": {"user_id": "45982", "batch_id": "PSJ-12"},
        "headers": {"X-Message-Source": "dev.私のドメイン.com"},
        "subject": "ご注文確認のご案内",
        "text": "ご注文番号1234を承りました",
        "category": "APIテスト"
    }

    headers = {
        'Content-Type': "application/json",
        'Accept': "application/json",
        'Api-Token': "api_トークンを_ここに入力"  # 実際のAPIトークンに置き換えてください
    }

    # ペイロードをJSON文字列に変換
    json_payload = json.dumps(payload)

    # POSTリクエストを実行
    conn.request("POST", "/api/send/inbox_id", json_payload, headers)  # 'inbox_id' を実際の受信トレイIDに置き換えます

    # レスポンスを取得
    response = conn.getresponse()
    data = response.read()

    print(data.decode("utf-8"))

if __name__ == "__main__":
    test_send_email()

ご留意事項

  • ペイロード この辞書にはテストしたいメールの全詳細が含まれています。プレースホルダーの値は、テストケースに関連する実際のデータに置き換えてください。添付ファイルの場合は、ファイルの内容をBase64でエンコードし、contentフィールドに含めます。
  • ヘッダー Content-TypeAcceptApi-Token のヘッダーを含めます。Api-TokenにはMailtrapのAPIトークンを設定します。
  • リクエストとレスポンス スクリプトは/api/send/inbox_idエンドポイントに対してPOSTリクエストを実行し、inbox_id を実際の受信トレイIDに置き換えます。その後、レスポンスを読み取り、結果を表示してくれます。

Pythonを使ったメール送信の次のステップ

この記事では、Pythonを使ったメール送信の方法やその基本的なロジックについて解説いたしました。Pythonのドキュメントを参照し、ご自身のコードで実験を重ねることをお勧めします。そうすれば、さらに素晴らしい結果を得られるはずです!

より高機能で美しいアプリを作成する際に役立つPythonのフレームワークとライブラリは多数あります。特にメール送信機能の構築プロセスの改善に便利なものもあるので、ぜひご検討ください。

最も人気のあるフレームワークは以下の通りです。

  1. Flask:Flask Mailを使ってメール送信を簡単に実装できます。Flaskのメール送信方法のガイドもご覧ください。
  2. Django:HTMLテンプレートの作成に最適です。Djangoのメール送信チュートリアルもご参考ください。
  3. Zope:ウェブサイト開発に役立ちます。
  4. Marrow Mailer:さまざまな便利な設定を追加できるメール配信フレームワークです。
  5. PlotlyDash:グラフやレポートの送信に便利です。

それでは、うまくいくことを願っています。メール送信の際はリスクの削減に努めることをどうぞお忘れなく!

Article by Aleksandr Varnin Full Stack Developer @ Railsware
Article by Veljko Ristić Content Manager @ Mailtrap

Linguist by trade, digital marketer at heart, I’m a Content Manager who’s been in the online space for 10+ years. From ads to e-books, I’ve covered it all as a writer, editor, project manager, and everything in between. Now, my passion is with email infrastructure with a strong focus on technical content and the cutting-edge in programming logic and flows. But I still like spreading my gospels while blogging purely about marketing.