概要(SMTPは「メールをサーバ経由で届ける」ための標準プロトコル)
SMTPは、メールを送信側から受信側へ「サーバを介して転送する」ための仕組みです。Pythonでは標準ライブラリのsmtplibを使い、SMTPサーバへ接続・暗号化・認証・送信の順に進めます。初心者がまず押さえる要点は、送信経路(ホスト・ポート)、暗号化方式(STARTTLS/SMTPS)、認証(SMTP AUTH)、そして正しいメッセージ構成(ヘッダーと本文)です。特にポート587でのSTARTTLS、または465でのSSL接続が実務の定番です。
SMTPの仕組みと接続の基本
サーバとポート(587のSTARTTLS、465のSMTPS)
SMTPサーバへはホスト名とポートで接続します。一般的には、587番で平文接続→STARTTLSコマンドで暗号化開始(サブミッションポート)、または465番で最初からTLS(SMTPS)を使います。どちらもSMTP AUTHによりユーザー名・パスワードで認証してから送信します。
Pythonのsmtplib(最小の流れ)
PythonのsmtplibはSMTPまたはSMTP_SSLで接続し、必要に応じてstarttls()、login()、send_message()の順に実行します。EmailMessageなどで件名・差出人・宛先・本文を組み立てたうえで送るのが基本です。
最短の送信例(テキストメール)
STARTTLS(587)で送る
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()
server.login(USERNAME, PASSWORD)
server.send_message(msg)
Pythonこの型は、SMTP接続→STARTTLSで暗号化→認証→送信の順序です。587はSTARTTLS向けの定番ポートで、広く推奨されています。
SMTPS(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)
Python465では最初からTLSで保護された接続を使い、starttls()は不要です。
メッセージの組み立て(ヘッダー・本文・MIME)
EmailMessageで安全に組む
EmailMessageを使えば、Subject/From/Toなどのヘッダー、本文(text/plainやtext/html)、添付(MIMEタイプ推定)を簡潔に扱えます。smtplibは送信層、emailパッケージはメッセージ層と覚えると整理できます。
HTMLメールとテキスト併記(互換性向上)
HTMLのみよりも、text/plainの代替を同梱したmultipartで送ると、HTMLが見られない環境でも崩れません。EmailMessage.add_alternativeでHTML、set_contentでテキストを組み合わせるのが定番です。
よくある設定と運用のポイント
Gmailを使う場合の注意(アプリパスワード)
GmailのSMTPはホストsmtp.gmail.com、ポート587(STARTTLS)が一般的です。2段階認証と併用して「アプリパスワード」を使うのが推奨されます。通常のパスワードでは認証に失敗するケースがあるため、運用側の設定を必ず確認しましょう。
送信ドメインの健全性(迷惑判定対策)
大量配信や外部宛への送信では、SPF/DKIMなど送信ドメイン認証を整えると到達率が上がります。SMTPのコードだけでなく、ドメイン側の設定が品質に直結します。
エラー対策(接続・認証・タイムアウト)
代表的な失敗と対処
- 認証エラー: ユーザー名・パスワード不一致、アプリパスワード未設定(Gmailなど)。運用設定の再確認が必要です。
- 接続エラー: ホスト・ポートの誤り、ネットワーク遮断、ファイアウォール。SMTP_HOST/PORTと到達性を確認します。
- SSL/暗号化エラー: STARTTLS未実行で平文のまま、または465なのにSMTP_SSL未使用。暗号化手順を正しく選びます。
タイムアウト設定で「待ち続け」を防ぐ
SMTP/SMTP_SSL生成時のtimeoutで、サーバ遅延やネットワーク不調に備えます。例外(SMTPException、timeout)を捕捉して再試行やログ化につなげる運用が安全です。
例題で身につける(定番から実務まで)
例題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)
PythonSTARTTLSは587で実施し、login→send_messageの順に進めます。
例題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)
PythonHTMLのみより、テキスト併記の方が互換性が高く、受信側の表示崩れを避けられます。
例題3:SMTP_SSL(465)で送る
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["Subject"] = "SMTPSで送信"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.set_content("465番ポートでのSSL接続です。", charset="utf-8")
with smtplib.SMTP_SSL("smtp.example.com", 465, timeout=10) as s:
s.login("user@example.com", "your_app_password")
s.send_message(msg)
Python465ではSMTP_SSLを使い、starttls()は不要です。
例題4:エラー処理のひな形
import smtplib, socket
from email.message import EmailMessage
msg = EmailMessage()
msg["Subject"] = "送信テスト"
msg["From"] = "user@example.com"
msg["To"] = "to@example.com"
msg.set_content("本文", charset="utf-8")
try:
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:
print("認証エラー:アプリパスワードや資格情報を確認")
except smtplib.SMTPConnectError:
print("接続エラー:ホスト・ポート・到達性を確認")
except (smtplib.SMTPException, socket.timeout) as e:
print("送信失敗:", e)
Python典型的な例外を捕捉して原因切り分けします。timeoutの指定も重要です。
まとめ
SMTPは「送信サーバへ接続→暗号化→認証→送信」という直線的な流れです。ポート587でのSTARTTLS、または465でのSMTP_SSLを正しく選び、EmailMessageでメッセージを安全に組み立てる。Gmailではアプリパスワードの採用が現実的で、到達率を高めるにはドメイン側のSPF/DKIM整備も効いてきます。接続・認証・暗号化・タイムアウト・例外処理の型を最初から入れておけば、初心者でも短いコードで「届く」「崩れない」メール送信を安定運用できます。
