Python | Web / API:Python でメール送信

Python Python
スポンサーリンク

概要(Pythonでメール送信は「smtplib+EmailMessage」が基本の型)

Python標準のsmtplibとemailパッケージを使えば、テキストメール、HTMLメール、添付ファイル、複数宛先、CC/BCCまで短いコードで送れます。重要なのは、SMTPサーバ設定(ホスト・ポート・認証・暗号化)、メッセージの正しい組み立て(ヘッダー・本文・MIME)、文字コード(UTF-8)と日本語対応、そしてエラー時の例外処理です。まずは「最短の送信」を動かし、次にHTML・添付・複数宛先へ広げ、最後に安全運用(認証情報の隠し方・失敗時の再試行)を押さえましょう。


仕組みと準備(SMTPの要点と使うモジュール)

SMTPの基本とポートの考え方

メールはSMTPサーバ経由で送信します。通常はSTARTTLSの587番ポート(平文で接続→TLS開始)、もしくはSMTPSの465番ポート(TLSで最初から暗号化)を使います。社内サーバやGmailなど、利用するSMTPのホスト名・ポート・認証方式を事前に確認します。

使うモジュール(smtplib+email)

送信はsmtplib、メッセージの組み立てはemail.message.EmailMessageやemail.mime.*を使います。EmailMessageはヘッダー、本文、添付を扱いやすく、初心者でも間違いが起きにくい選択です。


基本のテキストメール(最短で「届く」形)

EmailMessage+STARTTLSの基本形

import smtplib
from email.message import EmailMessage

SMTP_HOST = "smtp.example.com"
SMTP_PORT = 587  # STARTTLS
USERNAME = "user@example.com"
PASSWORD = "your_app_password"  # 本番は環境変数で渡すのが安全

msg = EmailMessage()
msg["Subject"] = "テストメール"
msg["From"] = USERNAME
msg["To"] = "to@example.com"
msg.set_content("これはPythonから送信したテキストメールです。", charset="utf-8")

with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=15) as server:
    server.starttls()              # 暗号化開始(STARTTLS)
    server.login(USERNAME, PASSWORD)
    server.send_message(msg)
Python

最短でも「From/To/Subject」「本文」「認証」「暗号化」の4点が揃っていれば十分に届きます。文字化けを避けるため、本文はUTF-8を明示します。

SSLポート(465)を使う場合

import smtplib
from email.message import EmailMessage

SMTP_HOST = "smtp.example.com"
SMTP_PORT = 465  # SMTPS

msg = EmailMessage()
msg["Subject"] = "SSLで送信"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.set_content("465番ポートでSSL接続から送信します。", charset="utf-8")

with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout=15) as server:
    server.login("user@example.com", "your_app_password")
    server.send_message(msg)
Python

465ではSMTP_SSLを使い、starttlsは不要です。


HTMLメールと日本語(見やすく、崩れない作り)

HTMLだけの送信(シンプル版)

from email.message import EmailMessage
import smtplib

msg = EmailMessage()
msg["Subject"] = "HTMLメールのテスト"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.add_alternative("""\
<!doctype html>
<html lang="ja">
  <body>
    <h1>こんにちは</h1>
    <p>これは <strong>HTML</strong> メールです。</p>
  </body>
</html>
""", subtype="html")

with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls()
    s.login("user@example.com", "your_app_password")
    s.send_message(msg)
Python

テキスト+HTMLのマルチパート(受信側の互換性を最大化)

from email.message import EmailMessage
import smtplib

msg = EmailMessage()
msg["Subject"] = "マルチパート(text+html)"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"

msg.set_content("これはテキスト版です。HTMLが読めない環境でも安心。", charset="utf-8")
msg.add_alternative("""\
<html><body>
<p>これはHTML版です。<br>見た目が整ったメールを届けます。</p>
</body></html>
""", subtype="html")

with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls()
    s.login("user@example.com", "your_app_password")
    s.send_message(msg)
Python

HTMLメールは「テキスト版も同梱」すると、表示互換性が上がります。日本語はUTF-8で統一し、本文や件名に機種依存文字を避けると崩れにくいです。


添付ファイル・複数宛先・CC/BCC(実務でよく使う形)

添付ファイルを付ける

from email.message import EmailMessage
import mimetypes, smtplib

msg = EmailMessage()
msg["Subject"] = "レポート添付"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.set_content("レポートを添付します。")

path = "report.pdf"
ctype, encoding = mimetypes.guess_type(path)
maintype, subtype = (ctype.split("/", 1) if ctype else ("application", "octet-stream"))
with open(path, "rb") as f:
    msg.add_attachment(f.read(), maintype=maintype, subtype=subtype, filename="report.pdf")

with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls(); s.login("user@example.com", "your_app_password")
    s.send_message(msg)
Python

MIMEタイプはmimetypesで推定し、filenameを付けると受信側で分かりやすくなります。

複数宛先・CC/BCC

from email.message import EmailMessage
import smtplib

to_list = ["a@example.com", "b@example.com"]
cc_list = ["c@example.com"]
bcc_list = ["d@example.com"]  # ヘッダーには載せない

msg = EmailMessage()
msg["Subject"] = "複数宛先のテスト"
msg["From"] = "user@example.com"
msg["To"] = ", ".join(to_list)
msg["Cc"] = ", ".join(cc_list)
msg.set_content("ToとCcへ同時送信。Bccはヘッダーに載らない宛先です。", charset="utf-8")

all_rcpts = to_list + cc_list + bcc_list
with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls(); s.login("user@example.com", "your_app_password")
    s.send_message(msg, to_addrs=all_rcpts)
Python

BCCはヘッダーに書かず、SMTP送信時だけ宛先に含めます。


エラー処理・安全運用(失敗しない、漏らさない)

代表的な例外のハンドリング

import smtplib, socket
from email.message import EmailMessage

try:
    msg = EmailMessage()
    msg["Subject"] = "送信テスト"
    msg["From"] = "user@example.com"
    msg["To"] = "to@example.com"
    msg.set_content("本文", charset="utf-8")

    with smtplib.SMTP("smtp.example.com", 587, timeout=15) as s:
        s.starttls()
        s.login("user@example.com", "your_app_password")
        s.send_message(msg)
except smtplib.SMTPAuthenticationError as e:
    print("認証エラー:ユーザー名/パスワード、アプリパスワード設定を確認")
except smtplib.SMTPConnectError as e:
    print("接続エラー:ホスト名、ポート、ネットワーク到達性を確認")
except smtplib.SMTPException as e:
    print("SMTP一般エラー:", e)
except socket.timeout:
    print("タイムアウト:サーバ遅延やファイアウォールを確認")
Python

smtplibは認証・接続・一般的SMTP例外のクラスが用意されています。タイムアウトも設定して「待ち続け」を防ぎます。

認証情報の管理(環境変数で隠す)

import os

USERNAME = os.environ["SMTP_USER"]
PASSWORD = os.environ["SMTP_PASS"]
Python

コードに平文で書かず、環境変数や秘密管理ツールを使います。Gmailなら「アプリパスワード」を発行して使う運用が安全です。

送信の健全性(From/Reply-To、SPF/DKIMの考慮)

Fromは送信者として正しいドメインを使い、必要ならReply-Toで返信先を明示します。外部へ大量配信する場合、SPF/DKIMなど送信ドメイン認証を管理側で設定しておくと迷惑メール判定を避けやすくなります。


例題で身につける(定番から実務まで)

例題1:テキストメール(STARTTLS)

import smtplib
from email.message import EmailMessage

def send_text(to):
    msg = EmailMessage()
    msg["Subject"] = "最短テキストメール"
    msg["From"] = "user@example.com"
    msg["To"] = to
    msg.set_content("こんにちは。Pythonからのメールです。", charset="utf-8")

    with smtplib.SMTP("smtp.example.com", 587, timeout=10) as s:
        s.starttls()
        s.login("user@example.com", "your_app_password")
        s.send_message(msg)

send_text("to@example.com")
Python

例題2:テキスト+HTMLのマルチパート

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg["Subject"] = "見やすいHTML+テキスト"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.set_content("テキスト版です。", charset="utf-8")
msg.add_alternative("<h1>HTML版です</h1><p>整った見た目で届けます。</p>", subtype="html")

with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls(); s.login("user@example.com", "your_app_password")
    s.send_message(msg)
Python

例題3:添付ファイル+複数宛先(CC/BCC)

import smtplib, mimetypes
from email.message import EmailMessage

msg = EmailMessage()
msg["Subject"] = "週次レポート"
msg["From"] = "user@example.com"
msg["To"] = "a@example.com, b@example.com"
msg["Cc"] = "c@example.com"
msg.set_content("レポート添付します。", charset="utf-8")

ctype, _ = mimetypes.guess_type("report.xlsx")
maintype, subtype = (ctype.split("/", 1) if ctype else ("application", "octet-stream"))
with open("report.xlsx", "rb") as f:
    msg.add_attachment(f.read(), maintype=maintype, subtype=subtype, filename="report.xlsx")

recipients = ["a@example.com", "b@example.com", "c@example.com", "d@example.com"]  # dはBCC
with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls(); s.login("user@example.com", "your_app_password")
    s.send_message(msg, to_addrs=recipients)
Python

例題4:安全運用(環境変数+例外処理のひな形)

import os, smtplib, socket
from email.message import EmailMessage

SMTP_HOST = os.getenv("SMTP_HOST", "smtp.example.com")
SMTP_PORT = int(os.getenv("SMTP_PORT", "587"))
USERNAME = os.environ["SMTP_USER"]
PASSWORD = os.environ["SMTP_PASS"]

msg = EmailMessage()
msg["Subject"] = "安全運用のひな形"
msg["From"] = USERNAME
msg["To"] = "to@example.com"
msg.set_content("例外処理と環境変数を組み込んだ送信例。", charset="utf-8")

try:
    with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=15) as s:
        s.starttls()
        s.login(USERNAME, PASSWORD)
        s.send_message(msg)
except (smtplib.SMTPException, socket.timeout) as e:
    print("送信失敗:", e)
Python

まとめ

Pythonでのメール送信は、smtplib(接続・送信)とEmailMessage(組み立て)が基本です。まずテキストの最短送信を確実にし、次にHTMLとテキストのマルチパート、添付、複数宛先、CC/BCCを広げます。日本語はUTF-8で統一し、ポートと暗号化(587+STARTTLS、または465+SSL)を正しく選択。認証情報は環境変数で隠し、タイムアウトと例外を必ず入れて「落ちない・漏らさない」運用にする。これらの型を身につければ、初心者でも短いコードで実務品質のメール送信が書けます。

タイトルとURLをコピーしました