メールの送信

revision-up-to:17812 (1.4)

Python の smtplib モジュール を使えば、比較的簡単にメールを送信できます が、 Django ではこのライブラリへの軽量ラッパを二つ用意しています。これらのラッパ ではメールの送信を極めて素早くおこなえ、開発時のテストメールの送信を簡単にでき、 SMTPを使えないプラットフォームにも対応しています。

コードは: django.core.mail にあります。

お手軽な例

二行だけです:

from django.core.mail import send_mail

send_mail('Subject here', 'Here is the message.', 'from@example.com',
    ['to@example.com'], fail_silently=False)

これで、 EMAIL_HOST および EMAIL_PORT 設定で指定した SMTP ホストを介してメールを送信します。 EMAIL_HOST_USER および EMAIL_HOST_PASSWORD を指定していれば、 SMTP サーバの認証に使います。 また、SMTP サーバとの接続に TLS を使うかどうかを EMAIL_USE_TLS で設定できます。

Note

django.core.mail で送信されるメールの文字セットは DEFAULT_CHARSET 設定の値に設定されます。

send_mail()

send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None)

メールを送信する最も簡単な方法は django.core.mail.send_mail() です。

subject, message, from_email および recipient_list は必須の パラメタです。

  • subject: 文字列です。
  • message: 文字列です。
  • from_email: 文字列です。
  • recipient_list: 文字列からなるリストで、各々がメールアドレ スを表します。 recipient_list に入っているユーザは、お互いに他のユー ザをメールの “To:” フィールドで見られます。
  • fail_silently: ブール型の値です。 False なら send_mailsmtplib.SMTPException 例外を出すようになります。 送出されうる例外のリストは smtplib ドキュメントを参照してくださ い。いずれの例外も SMTPException のサブクラスです。
  • auth_user: オプションです。 SMTP サーバでの認証に使うユーザ名です。 この値を指定しなければ、 Django は EMAIL_HOST_USER 設定を使います。
  • auth_password: オプションです。 SMTP サーバでの認証に使うパスワー ドです。この値を指定しなければ、 Django は EMAIL_HOST_PASSWORD 設 定を使います。
  • connection: オプションです。メール送信に使うバックエンドです。 明示しなければデフォルトのバックエンドが使われます。詳細はドキュメントの Email backends を参照してください。

send_mass_mail()

send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)

django.core.mail.send_mass_mail() は一括メール (mass email) の送信 用の関数です。この関数の定義は以下の通りです

datatuple はタプルで、各要素は以下の形式になっています:

(subject, message, from_email, recipient_list)

fail_silently, auth_user および auth_passwordsend_mail() と同じです。

datatuple の各要素ごとに個別のメールメッセージを作成して送信します。 send_mail() と同様、同じ recipient_list に入ってい る受信者は、他の受信者を “To:” フィールドで見られます。

例えば下記のコードでは、2つのメールがそれぞれ複数の宛先に一斉送信されます。 しかし、メールサーバへの接続は1つだけ開かれます。:

message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])
message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])
send_mass_mail((message1, message2), fail_silently=False)

send_mass_mail() と send_mail()

send_mass_mail()send_mail() の大きな違いは send_mail() は実行の度にメールサーバに 接続するのに対し、 send_mass_mail() は全てのメッセージの 送信に一つの接続を使う点です。このため、 send_mass_mail() の方が少しだけ効率的です。

mail_admins()

mail_admins(subject, message, fail_silently=False, connection=None, html_message=None)

django.core.mail.mail_admins()ADMINS に書かれたサイト管理者 へのメール送信を行うためのショートカットです。

mail_admins() はサブジェクトの先頭に EMAIL_SUBJECT_PREFIX の 設定値を付加します。デフォルトは "[Django] " です。

メールの “From:” ヘッダには SERVER_EMAIL の設定値が入ります。

このメソッドは利便性と可読性のために用意されています。

リリースノートを参照してください

html_message が指定されているなら、結果のメールは multipart/alternative メールになります。 text/plain タイプの messagetext/html タイプの html_message から なります。

mail_managers()

mail_managers(subject, message, fail_silently=False, connection=None, html_message=None)

django.core.mail.mail_managers()mail_admins() と同じですが、メールを MANAGERS 設定に書かれたサイトマネジャに送信します。

以下の例は、単一のメールを john@example.comjane@example.com に送信 します。両方の宛先が “To:” に表示されます:

send_mail('Subject', 'Message.', 'from@example.com',
    ['john@example.com', 'jane@example.com'])

以下の例は、単一のメールを john@example.comjane@example.com に送信 しますが、受け取り人はそれぞれ別々のメッセージを受け取ります:

datatuple = (
    ('Subject', 'Message.', 'from@example.com', ['john@example.com']),
    ('Subject', 'Message.', 'from@example.com', ['jane@example.com']),
)
send_mass_mail(datatuple)

ヘッダインジェクションの抑制

ヘッダインジェクション とは、スクリプトが生成したメッセージの “To:” や “From:” に、攻撃者が余分なメールヘッダを挿入するというセキュリティ侵害 です。

上記で解説した Django のメール機能では、ヘッダの値に改行を使えないよう にしてヘッダインジェクションを防御しています。 subject, from_email および recipient_list が (Unix, Windows または Mac 形式の) 改行を含む場 合、メール送信関数 ( send_mail() など) は django.core.mail.BadHeaderError 例外 (ValueError のサブクラス) を送 出します。このため、メールは送信されません。メール送信関数に渡すデー タの検証はユーザに任されています。

message の文字列の先頭にヘッダが入っている場合、ヘッダは単にメッセー ジ本文の先頭部分として出力されます。

以下に示すのは、 subject, message および from_email をリクエス トの POST データから受け取り、メールを admin@example.com に送信し、終了した ら “/contact/thanks/” にリダイレクトする例です:

from django.core.mail import send_mail, BadHeaderError

def send_email(request):
    subject = request.POST.get('subject', '')
    message = request.POST.get('message', '')
    from_email = request.POST.get('from_email', '')
    if subject and message and from_email:
        try:
            send_mail(subject, message, from_email, ['admin@example.com'])
        except BadHeaderError:
            return HttpResponse('Invalid header found.')
        return HttpResponseRedirect('/contact/thanks/')
    else:
        # 実際にはフォームクラスを使って適切な検証エラーを
        # 取得するべきでしょう。
        return HttpResponse('Make sure all fields are entered and valid.')

EmailMessage クラス

Django の send_mail() および send_mass_mail() 関数は、実際には EmailMessage クラスに対して薄いラッパをかぶせたものに すぎません。

send_mail() をはじめとしたラッパ関数から利用できる 機能は、 EmailMessage クラスで提供している全ての 機能をカバーしているわけではありません。BCC への宛先を指定やファイルの添付、 マルチパート形式メールの送信などを行いたい場合には、 EmailMessage インスタンスを直接生成する必要があり ます。

Note

send_mail()`() がこのような、いささかややこしい仕様 なのは、設計上の事情によるものです。 send_mail()`() などの関数はもともと単なる Django 向けの単純なメールインタフェースでしか ありませんでした。その後、指定できるパラメタが少しづつふえてきたのです。 今となっては、メールメッセージを扱うためのよりオブジェクト指向の設計に移行 して、 send_mail()`() は互換性のためだけにおいておく 方が有意義でしょう。

EmailMessage はメールメッセージ自体の生成に関わり ます。 メールバックエンド は、メールの送信に関わり ます。

便宜上、 EmailMessage は単純な send() メソッド を単一のメールを送信するために提供しています。複数のメッセージを送りたいときは、 メールバックエンドAPIは 他の手段を提供しています

EmailMessage オブジェクト

class EmailMessage

EmailMessage クラスは以下のパラメタ (固定引数を使 う場合には以下に示す順番に指定します) で初期化します。パラメタは全て省略可能 で、 send() メソッドを呼び出す前であればいつでも設定しなおせます。

引数 cc が追加されました。
  • subject: メールの題名です。
  • body: メール本文です。平文テキストのメッセージでなければなりません。
  • from_email: 送信者のアドレスです。 fred@example.com 形式でも Fred <fred@example.com> 形式でもかまいません。省略すると、 DEFAULT_FROM_EMAIL の設定値を使います。
  • to: 受信者アドレスのリストまたはタプルです。
  • bcc: メールを送信する際に “Bcc” ヘッダに指定するアドレスのリスト
    またはタプルです。
  • connection: メールバックエンドのインスタンスです。一つの SMTP 接 続を使い回して複数のメッセージを送信したい場合に指定します。この引数を省略する と、 send() を呼び出す瞬間に新しい接続を生成します。
  • attachments: メールに添付するデータのリストです。リストの各要素は、 email.MIMEBase.MIMEBase のインスタンスか、 (filename, content, mimetype) からなるタプルです。
  • headers: メッセージに追加するヘッダの辞書です。ヘッダ名をキーに、 ヘッダ値を値にします。このパラメタを使うのなら、指定したヘッダがメー ルメッセージ中で正しいヘッダとして扱われるように気をつけねばなりませ ん。
  • cc: 受信者アドレスのリストまたはタプルです。メール送信時の “Cc” ヘッダに 使われます。

例を示します:

email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
            ['to1@example.com', 'to2@example.com'], ['bcc@example.com'],
            headers = {'Reply-To': 'another@example.com'})

EmailMessage クラスのインスタンスには以下のようなメソッドがあります:

  • send(fail_silently=False) メソッドはメッセージを送信します。メールが作成さ れたときに接続が指定されれば、その接続が使われます。接続がなければ、デフォルト バックエンドのインスタンスが生成され、使われます。 fail_silentlyTrue にすると、メッセージ送信に失敗した場合に例外を送出します。

  • message()django.core.mail.SafeMIMEText クラス (Python の email.MIMEText.MIMEText クラスのサブクラス) または django.core.mail.SafeMIMEMultipart クラスのインスタンスを生成します。 このオブジェクトには送信するメッセージが入っています。 EmailMessage クラスを拡張する必要がある場合、 おそらくこのメソッドをオーバライドして、所望の内容を MIME オブジェクト内に 配置することになるでしょう。

  • recipients() はメッセージの全ての宛先からなるリストを返します。この 宛先リストは、 tobcc に指定した全ての宛先が入ります。 EmailMessage をサブクラス化する際、このメソッドも オーバライドする必要があるかもしれません。というのも、 SMTP サーバはメッセージ 送信時に全ての宛先を知る必要があり、全ての宛先はこのメソッドを介して返さねば ならないからです。

  • attach() を呼び出すと、新たなファイル添付用パートを生成してメッセー ジに追加します。 attach() の呼び出しかたは 2 通りあります:

    • attach() に引数を一つだけ指定し、 email.MIMEBase.MIMEBase のインスタンスを渡します。このインスタンスの内容は最終的なメッセージ に直接挿入されます。

    • 別の方法として、 attach() に 3 つの引数、 filename, content および mimetype を渡します。 filename は添付する ファイルの名前で、これはメール中で表示される添付ファイルの名前になり ます。 content は添付パート中に入るデータで、 mimetype は添 付内容の MIME タイプです。 mimetype を省略すると、ファイル名を元 に推測を行います。

      例を示します:

      message.attach('design.png', img_data, 'image/png')
      
  • attach_file() を呼び出すと、ファイルシステム上のファイルから添付パー トを生成します。 attach_file() の引数には添付したいファイルのパスを 指定します。オプションとして、添付ファイルの MIME タイプも指定できます。 MIME タイプを省略すると、ファイル名をもとに推測を行います。簡単な使い方 を示すと、以下のようになります:

    message.attach_file('/images/weather_map.png')
    

拡張コンテンツ形式のメールを送信する

メールの内容をいくつかのバージョンに分けて送信すると便利な場合があります。 古典的な例でいえば、テキスト形式と HTML 形式の両方でメールを送信するような 場合です。 複数バージョンのメールを同時に送るには、 EmailMultiAlternatives クラス を使います。このクラスは EmailMessage のサブクラスで、 attach_alternative() メソッドを使ってメールのメッセージ本文に別のバージョ ンの本文を追加できます。 attach_alternative() 以外は、(クラスをインスタ ンス化するときの初期化メソッドも含めて) EmailMessage と全く同じです。

テキストと HTML を組み合わせて送信したければ、以下のように書けます:

from django.core.mail import EmailMultiAlternatives

subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

デフォルトでは、 EmailMessagebody パラメタの MIME タイプは "text/plain" です。実践的には、このパラメタは変更せずにおいた 方がよいでしょう。なぜなら、メールを受信した人が使っているメールクライアントソフ トに関係なくメッセージを読めるよう保証できるからです。とはいえ、メールの読み手 が拡張コンテンツ形式 (alternative content type) のメッセージを扱えると分かっ ている場合には、 EmailMessagecontent_subtype 属性を使って、主メッセージのコンテンツタイプを変更できます。メールのメジャー コンテンツタイプは常に "text" ですが、サブタイプは以下のように変更できます:

msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html"  # メインのコンテンツは text/html になります。
msg.send()

メールバックエンド

リリースノートを参照してください

メールを送るのは、実際にはメールバックエンドが扱っています。

メールバックエンドクラスには以下のようなメソッドがあります:

  • open() 永続するメール送信接続をインスタンス化します。
  • close() 現在のメール送信接続を閉じます。
  • send_messages(email_messages) EmailMessage オブジェクトを送信します。接続が開かれていないときは暗黙的に接続が開かれ、 メール送信後に閉じられます。 接続がすでに開かれているときは、メール送信後も 接続は開かれたままになります。

メールバックエンドのインスタンスを得る

django.core.mailget_connection() 関数はメールバックエンドの インスタンスを、あなたが使えるように返します。

get_connection(backend=None, fail_silently=False, *args, **kwargs)

デフォルトで get_connection()EMAIL_BACKEND で指定された メールバックエンドのインスタンスを返します。引数 backend を指定した 場合は、そのバックエンドのインスタンスを返します。

fail_silently 引数は、バックエンドがエラーを扱うかどうかを指定できます。 fail_silently が True のときは、メール送信プロセス中の例外が無視されます。

それ以外の引数は、メールバックエンドのコンストラクタに直接渡されます。

いくつかのメール送信バックエンドが Django には付属しています。SMTPバックエンド (デフォルト)以外のバックエンドは、テストと開発時にのみ有効です。特別なメール送信 が必要な場合は、 自分でメールバックエンドを書いてください

SMTP バックエンド

これはデフォルトのバックエンドです。メールは SMTP サーバを通して送信されます。 サーバのアドレスと認証情報は EMAIL_HOSTEMAIL_PORTEMAIL_HOST_USEREMAIL_HOST_PASSWORDEMAIL_USE_TLS 設定を設定ファイルに書いてください。

SMTP バックエンドは古くから Django のデフォルトです。 明示的に指定したいときは以下のように設定ファイルに書いてください:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

SMTPConnection objects

先のバージョン 1.2 では、 Django は SMTPConnection クラスを提供していました。このクラスは SMTP を直接制御してメールを送信する方法 を提供します。このクラスは、汎用のメールバックエンドAPIが採用さたので廃止され ました。

後方互換性のために SMTPConnection は SMTP バックエンドの別名として django.core.mail で依然使えます。

コンソールバックエンド

実際にメールを送信する代わりに、コンソールバックエンドはただメールを書く だけです。コンソールバックエンドに書かれたメールは標準出力に送られます。 デフォルトでは、コンソールバックエンドは stdout に書きます。 接続を構成するときに stream キーワード引数を与えると、他のストリームなどの オブジェクトも使えます。

コンソールバックエンドを指定するには以下を設定ファイルに記述してください:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

コンソールバックエンドは製品での使用を意図していません。開発時に使える、利便性の ため提供されるものです。

ファイルバックエンド

ファイルバックエンドはメールをファイルに書き込みます。ファイルバックエンドが 新しいセッションを開く度に、新しいファイルは作られます。ファイルが書き込まれる ディレクトリは、 EMAIL_FILE_PATH 設定か file_path キーワードの どちらかで決められます。これは get_connection() との接続 が作成されるときに決まります。

ファイルバックエンドを指定するには以下を設定ファイルに記述してください:

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/app-messages' # 適切な値に変えてください。

ファイルバックエンドは製品での使用を意図していません。開発時に使える、利便性の ため提供されるものです。

メモリバックエンド

'locmem' バックエンドはメッセージを django.core.mail モジュールの特殊な 属性に格納します。 outbox 属性は最初のメッセージが送られたときに作られます。 EmailMessage インスタンスのリストがそれぞれのメッセージ として送られます。

メモリバックエンドを指定するには以下を設定ファイルに記述してください:

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

メモリバックエンドは製品での使用を意図していません。開発やテスト時に使える、 利便性のため提供されるものです。

ダミーバックエンド

名前が示すように、ダミーバックエンドはメッセージに対して何もしません。

ダミーバックエンドを指定するには以下を設定ファイルに記述してください:

EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

ダミーバックエンドは製品での使用を意図していません。開発時に使える、利便性の ため提供されるものです。

カスタムメールバックエンドを定義する

メールがどのようにして送られるかを変更する必要があるなら、あなた自身のメールバッ クエンドを書いてください。設定ファイルの EMAIL_BACKEND 設定には、 あなたが書いたバックエンドへの Python インポートパスを指定してください。

カスタムメールバックエンドは django.core.mail.backends.base モジュールにあ る BaseEmailBackend のサブクラスであるべきです。カスタムメールバックエンド は send_messages(email_messages) メソッドを実装しなければなりません。この メソッドは EmailMessage インスタンスを受け取り、正常 に送信されたメッセージの数を返します。カスタムメールバックエンドが永続するセッ ションか接続をもてるようにするには、 open() および close() メソッドも実 装する必要があります。リファレンス実装のために smtp.EmailBackend を参考にして ください。

複数のメールを送信する

SMTP 接続の確立と切断(もしくは他のどのネットワーク接続もそうですが)は重い処理 です。多くのメールを送る必要があるなら、 SMTP 接続を再利用するのは納得できます。 メールを送る度に接続を確立して切断するのは良い方法ではないでしょう。

接続を再利用できるようにメールバックエンドに指定する方法は2つあります。

第一に、 send_messages() メソッドを使う方法があります。 send_messages()EmailMessage インスタンス (もしくはサブクラス) の リストを受け取り、1つの接続を使ってそれら全てを送信します。

例えば get_notification_email() 関数を使えば、定期送信するメールを EmailMessage オブジェクトのリストで返してくれるので、 そのまま send_messages を使って送信することができます:

from django.core import mail
connection = mail.get_connection()   # デフォルトのメール接続を使います。
messages = get_notification_email()
connection.send_messages(messages)

この例では、 send_messages() は接続をバックエンドで開き、メッセージのリスト を送信し、さらに接続を切断します。

2つ目の方法はメールバックエンドの open()close() メソッドを手動で使っ て接続をコントロールすることです。 send_sessages() では手動で接続を開いたり 閉じたりコントロールできません。すでに接続が開かれているときは手動で接続を開いた ということなので、閉じるタイミングをコントロールできます:

from django.core import mail
connection = mail.get_connection()

# 手動で接続を開きます。
connection.open()

# メールメッセージを作成します。さっき作った接続で使います。
email1 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
                          ['to1@example.com'], connection=connection)
email1.send() # Send the email

# さらに二つ作成します。
email2 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
                          ['to2@example.com'])
email3 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
                          ['to3@example.com'])

# 二つのメールを一つの呼び出しで送信します。
connection.send_messages([email2, email3])
# send_messages() が接続を閉じなかったので未だに開かれています。
# なので手動で閉じる必要があります。
connection.close()

メール送信のテスト

Django に一切のメール送信をしてほしくないときがあります。例えば、 Web サイトの 開発をしているとき、何千ものメールを送信してほしくないと思います。しかし適切な 条件の下で適切な相手に、正しい内容のメールを送るのを認めたい場合があるかもしれま せん。

プロジェクトのメールの扱いをテストする最も簡単な方法は console を使うこと です。このバックエンドはすべてのメールを標準出力にリダイレクトします。これで メールの内容を検査することができます。

file メールバックエンドも開発時には使えます。このバックエンドはすべての SMTP コネクションのコンテンツをファイルにダンプします。なので暇なときに検査 できます。

他にも “無口な (dumb)” SMTP サーバを使う方法があります。この SMTP サーバはロー カルでメールを受け取って端末に表示しまが、送信はなにもしません。 Python のビル ドインで、1つのコマンドでできます:

python -m smtpd -n -c DebuggingServer localhost:1025

このコマンドはローカルホストのリスニングポート 1025 で SMTP サーバ を開始しま す。このサーバはすべてのメールのヘッダ、ボディーを標準出力に書き出します。そし て必要なのは EMAIL_HOSTEMAIL_PORT をそれらしく設定し ます。以上です。

ローカルでのメールの処理やテストの詳細については、 Python ドキュメントの smtpd を参照してください。

SMTPConnection

class SMTPConnection

Deprecated since version 1.2.

SMTPConnection クラスは汎用のメールバックエンドAPIが採用されたので廃止されま した。

後方互換性のために SMTPConnection は依然使えます。 django.core.mailSMTP バックエンド の 別名として存在します。これから書くコードには get_connection() を使うべきです。