E メールを送信する

Pythonでは smtplib モジュールを使って E メールを比較的簡単に送ることができますが、Django はさらにいくつかの軽いラッパーを用意しています。これらのラッパーは、 E メールをよりすばやく送信したり、開発中に E メール送信をテストしたり、SMTP を使用できないプラットフォームをサポートしたりするために用意されています。

コードは django.core.mail モジュールにあります。

簡単な例

以下の 2 行にて:

from django.core.mail import send_mail

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

メールは、SMTP ホストと EMAIL_HOSTEMAIL_PORT 設定内で指定されたポートを使用して送信されます。EMAIL_HOST_USEREMAIL_HOST_PASSWORD 設定がセットされている場合は、SMTP サーバーの認証に使われます。そして、EMAIL_USE_TLSEMAIL_USE_SSL 設定はセキュアコネクションが使われるかどうかをコントロールします。

注釈

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

send_mail()

send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)[ソース]

E メール送信のもっともシンプルな方法は、django.core.mail.send_mail() を使うことです。

subjectmessagefrom_emailrecipient_list の 4 つの引数は必須です。

  • subject: 文字列です。

  • message: 文字列です。

  • from_email: 文字列です。

  • recipient_list: 文字列のリストで、それぞれの E メールアドレスです。recipient_list の各メンバーは、E メールメッセージの “To:” 内の他の受信者を見ることができます。

  • fail_silently: 真偽値です。False の場合、send_mailsmtplib.SMTPException を投げます。発生しうる例外のリストについては、smtplib ドキュメントを参照してください。これらの例外は、すべて SMTPException のサブクラスです。

  • auth_user: SMTP サーバー認証のためのユーザー名で、省略可能です。指定されなかった場合、Django EMAIL_HOST_USER 設定の値を使います。

  • auth_password: SMTP サーバー認証のためのパスワードで、省略可能です。指定されなかった場合、Django は EMAIL_HOST_PASSWORD 設定の値を使います。

  • connection: E メール送信のために使うバックエンドで、省略可能です。指定されなかった場合、デフォルトのバックエンドのインスタンスが使われます。詳しくは E メールのバックエンド を参照してください。

  • html_message: html_message が指定された場合、送信される E メールは multipart/alternative となります。messagetext/plain コンテンツタイプと html_messagetext/html コンテンツタイプです。

戻り値は送信に成功したメッセージの数です (1 つだけメッセージを送信する場合もあるので、01 になることもあります)。

send_mass_mail()

send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)[ソース]

django.core.mail.send_mass_mail() は、大量の E メール送信を扱うために用意されています。

datatuple はタプルで、それぞれの要素は以下の形式で表されます:

(subject, message, from_email, recipient_list)

fail_silentlyauth_userauth_password の 3 つは、send_mail() と同じ機能です。

datatuple のそれぞれ分割された要素は、分割された E メールメッセージを作ります。send_mail() における挙動と同じく、recipient_list 内の受信者は E メールのメッセージにある “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() はすべてのメッセージに対して 1 つだけ接続を使います。これにより、send_mass_mail() の方が若干効率がよくなっています。

mail_admins()

mail_admins(subject, message, fail_silently=False, connection=None, html_message=None)[ソース]

django.core.mail.mail_admins() は、ADMINS 設定で定義されているサイト管理者 (admin) に対して E メールを送信するためのショートカットです。

mail_admins() prefixes the subject with the value of the EMAIL_SUBJECT_PREFIX setting, which is "[Django] " by default.

The “From:” header of the email will be the value of the SERVER_EMAIL setting.

This method exists for convenience and readability.

If html_message is provided, the resulting email will be a multipart/alternative email with message as the text/plain content type and html_message as the text/html content type.

mail_managers()

mail_managers(subject, message, fail_silently=False, connection=None, html_message=None)[ソース]

django.core.mail.mail_managers() は、mail_admins() とほぼ同じで、MANAGERS 設定で定義されているサイト管理者 (manager) に Eメールを送信します。

以下の例は、john@example.comjane@example.com に単一の E メールを送信します。両方とも “To:” 内で見られます:

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

以下の例は、john@example.comjane@example.com に E メールを送信しますが、受信者はどちらも別々の E メールを受け取ります:

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

ヘッダインジェクションを防止する

ヘッダインジェクション は、攻撃者が 、スクリプトで生成された E メールメッセージの “To:” と “From:” をコントロールするために、E メールヘッダを挿入してしまうセキュリティ上の脆弱性です。

上述した Django の E メール機能は、ヘッダー値の改行を禁止することによってヘッダインジェクションを防ぎます。 subjectfrom_emailrecipient_list のいずれかに 改行 (Unix、Windows ないし Mac のスタイル) が含まれている場合、email 関数 (例えば send_mail()) は django.core.mail.BadHeaderError (ValueError のサブクラス) 投げます。そして、それゆえに、E メールを送信しません。E メール関数にデータを渡す前に内容を検証しておくことは、開発者の責任となります。

message が文字列の最初にヘッダを含む場合、ヘッダは単に E メールメッセージの最初のビットとして表示されます。

以下は、リクエストの POST データから subjectmessagefrom_email を取得し、それを admin@example.com に送信し、完了したら “/contact/thanks/” にリダイレクトする一例です:

from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect

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:
        # In reality we'd use a form class
        # to get proper validation errors.
        return HttpResponse('Make sure all fields are entered and valid.')

EmailMessage クラス

Django の send_mail()send_mass_mail() 関数は EmailMessage クラスを実際に使うための小さなラッパーです。

EmailMessage クラスの機能のすべてが send_mail() やその他のラッパーで使用可能というわけではありません。高度な機能を使いたい場合 (例えば BCC の利用、ファイル添付やマルチパートの E メールなど) EmailMessage のインスタンスを直接作成する必要があります。

注釈

これは設計特性です。send_mail() およびその関連の関数は、元は Django が提供した唯一のインタフェースでした。しかし、受け入れるパラメータのリストが次第に肥大化してきてしまったので、よりオブジェクト指向的な設計に移行し、元の関数は後方互換性確保のためだけに残すことになりました。

EmailMessage は、 Eメールメッセージ自体を作成する義務があります。それから、E メールのバックエンド は、E メールを送信する義務があります。

For convenience, EmailMessage provides a simple send() method for sending a single email. If you need to send multiple messages, the email backend API provides an alternative.

EmailMessage オブジェクト

class EmailMessage[ソース]

EmailMessage クラスは、以下のパラメータで (省略可能な引数が使われた場合、その順番で) 初期化されます。全てのパラメータは省略可能で、send() メソッドを呼ぶ前のタイミングでセットされます。

  • subject: E メールの表題の行です。

  • body: 本文のテキストです。プレーンテキストメッセージです。

  • from_email: 送信者のアドレスです。fred@example.comFred <fred@example.com> の両方が使用可能です。省略した場合、DEFAULT_FROM_EMAIL 設定が使われます。

  • to: 受信者のリストないしタプルです。

  • bcc: Eメールを送信するときに “Bcc” ヘッダ内で使われるアドレスのリストないしタプルです。

  • connection: E メールバックエンドのインスタンスです。複数のメッセージに同一の接続を使いたいときに指定してください。省略した場合、send() が呼ばれるときに新しい接続が生成されます。

  • attachments: メッセージに添付されるファイルのリストです。email.MIMEBase.MIMEBase のインスタンスか、 (filename, content, mimetype) のトリプルのどちらかで指定できます。

  • headers: メッセージに追加するヘッダーのディクショナリです。キーはヘッダ名、値はヘッダ値です。E メールメッセージに対して適切なヘッダ名と値にするのは、呼び出す側の責任です。対応する属性は extra_headers です。

  • Eメールを送信するときに “cc” ヘッダ内で使われる受信者のアドレスのリストないしタプルです。

  • reply_to: Eメールを送信するときに “Reply-To” ヘッダ内で使われる受信者のアドレスのリストないしタプルです。

For example:

from django.core.mail import EmailMessage

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

クラスには以下のメソッドがあります:

  • send(fail_silently=False) はメッセージを送信します。E メールの構築時に接続が指定された場合、その接続が使用されます。 それ以外の場合は、デフォルトのバックエンドがインスタンス化され、使用されます。 キーワード引数 fail_silentlyTrue の場合、メッセージの送信中に投げられた例外は破棄されます。 受信者の空のリストは例外を投げません。

  • message()django.core.mail.SafeMIMEText オブジェクト (Python の email.MIMEText.MIMEText クラスのサブクラスです) か、送信メッセージを保持する django.core.mail.SafeMIMEMultipart オブジェクトを構築します。EmailMessage クラスを拡張する必要がある場合は、このメソッドをオーバーライドして、お望みのコンテンツを MIME オブジェクトに入れることをお勧めします。

  • recipients() は、toccbcc のいずれかの属性に記録されている、メッセージの全ての受信者のリストを返します。サブクラス化するときには、メッセージの送信時に SMTP サーバが受信者の完全な一覧を必要とするため、このメソッドもオーバーライドする必要があります。クラス内で受信者を指定する別の方法を追加する場合は、このメソッドからも返される必要があります。

  • attach() は新しい添付ファイルを作成し、メッセージに追加します。attach() を呼ぶには以下の 2 つの方法があります:

    • email.MIMEBase.MIMEBase のインスタンスである単一の引数を引き渡します。生成されるメッセージに直接挿入されます。

    • もしくは、attach() の 3 つの引数を引き渡します: filenamecontentmimetype です。filename は、E メール内に表示される添付ファイルの名前です。content``は、添付ファイル内に含まれるデータです。``mimetype は添付ファイルに対する MIME タイプで、省略可能です。mimetype を省略した場合、MIME コンテンツタイプは添付ファイルのファイル名から推測されます。

      For example:

      message.attach('design.png', img_data, 'image/png')
      

      message/rfc822mimetype を指定した場合、django.core.mail.EmailMessageemail.message.Message も受け入れます。

      さらに、message/rfc822 添付ファイルは RFC 2046#section-5.2.1 の Base64 エンコード違反とはなりません。これは、EvolutionThunderbird 内の添付ファイルの表示での問題の原因となります。

  • attach_file() は、あなたのファイルシステムにあるファイルを使って新しい添付ファイルを作成します。添付するファイルのパスとともに呼び出してください。MIME タイプも指定できますが省略可能です。MIME タイプを省略した場合、ファイル名から推測されます。最も簡単な使い方は以下の通りです:

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

代替のコンテンツタイプを送信する

E メール内にコンテンツの複数のバージョンを入れておくのが便利です; 古典的な手法では、メッセージをテキストと HTML の両方のバージョンで送信します。 Django の E メールのライブラリで、EmailMultiAlternatives を使ってこれを実現できます。この EmailMessage のサブクラスには、attach_alternative() があり、E メール内のメッセージ本文の別バージョンを追加することができます。(クラスの初期化を含む) 他のメソッドは 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()

デフォルトでは、EmailMessage 内の body パラメータの MIME タイプは "text/plain" です。この設定だとメールクライアントにかかわらず全ての受信者が E メールを読むことができるので、このままにしておくのが実用的です。しかし、受信者が代替のコンテンツタイプを扱えることが確かな場合には、EmailMessagecontent_subtype 属性を使ってメインのコンテンツタイプを変更することもできます。主なタイプは常に "text" ですが、サブタイプを変更することができます。例えば:

msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html"  # Main content is now text/html
msg.send()

E メールのバックエンド

実際の E メール送信は、Eメールバックエンドによって処理されます。

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

  • open() は、長寿命の E メール送信の接続をインスタンス化します。

  • close() は、現在の E メール送信の接続を閉じます。

  • send_messages(email_messages) は、EmailMessage オブジェクトのリストを送信します。接続が開いていない場合、暗黙的に接続を開き、その後に接続を閉じます。接続がすでに開いている場合は、メールが送信された後も開いたままにします。

コンテキストマネジャーとしても使うことができ、必要に応じて自動的に open()close() 呼びます:

from django.core import mail

with mail.get_connection() as connection:
    mail.EmailMessage(
        subject1, body1, from1, [to1],
        connection=connection,
    ).send()
    mail.EmailMessage(
        subject2, body2, from2, [to2],
        connection=connection,
    ).send()

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

django.core.mail 内の get_connection() 関数は、利用可能な E メールバックエンドのインスタンスを返します。

get_connection(backend=None, fail_silently=False, *args, **kwargs)[ソース]

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

fail_silently 引数は、バックエンドがエラーをどのように扱うかをコントロールします。fail_silently が True の場合、E メール送信プロセスの間に発生した例外は何の通知もされずに無視されます。

他の全ての引数は、E メールバックエンドのコンストラクタに直接引き渡されます。

Django には複数の E メール送信バックエンドを付属しています。SMTP バックエンド (デフォルトです) を除いて、これらのバックエンドはテストと開発のみで役立ちます。特別な E メール送信が必要な場合には、独自の E メールバックエンドを記述する を参照してください。

SMTP バックエンド

class backends.smtp.EmailBackend(host=None, port=None, username=None, password=None, use_tls=None, fail_silently=False, use_ssl=None, timeout=None, ssl_keyfile=None, ssl_certfile=None, **kwargs)

デフォルトのバックエンドです。E メールは SMTP サーバを通して送信されます。

引数が None の場合、各引数に対する値は、以下のそれぞれの設定から取得されます:

SMTP バックエンドは、Django によって継承されるデフォルトの構成です。明示的に指定したい場合は、設定内で以下の通り記述してください:

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

指定しなかった場合は、デフォルトの timeoutsocket.getdefaulttimeout() によって指定されたものになり、デフォルトは None (タイムアウトなし) になります。

コンソールバックエンド

実際の E メールを送信する代わりに、コンソールバックエンドは単に標準出力に送信される E メールを書き込みます。 デフォルトでは、コンソールバックエンドは stdout に書き込みます。 接続を構築するときに stream キーワード引数を指定することで、別のストリーム的なオブジェクトを使用できます。

このバックエンドを指定するには、設定内に以下の通り記述してください:

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

このバックエンドはプロダクトでの使用を想定していません – 開発中の利便性のために提供されています。

ファイルバックエンド

ファイルバックエンドは、E メールをファイルに書き込みます。新しいファイルは、このバックエンド上で開いたそれぞれの新しいセッションに対して作成されます。ファイルが書き込まれるディレクトリは、 get_connection() で 接続を生成したときに EMAIL_FILE_PATH 設定ないし file_path キーワードから取得されます。

このバックエンドを指定するには、設定内に以下の通り記述してください:

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location

このバックエンドはプロダクトでの使用を想定していません – 開発中の利便性のために提供されています。

インメモリーバックエンド

'locmem' バックエンドは、 django.core.mail モジュールの特別な属性内にメッセージを保持します。outbox 属性は最初のメッセージが送信されるときに生成されます。送信される書くメッセージに対する EmailMessage インスタンスのリストです。

このバックエンドを指定するには、設定内に以下の通り記述してください:

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

このバックエンドはプロダクトでの使用を想定していません – 開発とテストにおける利便性のために提供されています。

ダミーバックエンド

名前が示すように、ダミーバックエンドはメッセージに何もしません。このバックエンドを指定するには、設定内に以下の通り記述してください:

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

このバックエンドはプロダクトでの使用を想定していません – 開発中の利便性のために提供されています。

独自の E メールバックエンドを定義する

E メール送信の方法を変更する必要がある場合、独自の E メールバックエンドを記述することができます。設定ファイル内の EMAIL_BACKEND 設定が独自のバックエンドのクラスへの Python のインポートパスとなります。

独自の E メールバックエンドは、django.core.mail.backends.base にある BaseEmailBackend をサブクラス化して作ります。独自の E メールバックエンドには send_messages(email_messages) メソッドを実装する必要があります。このメソッドは EmailMessage インスタンスのリストを受け取り、送信に成功したメッセージの数を返します。バックエンドに持続瀬的なセッションや接続の概念がある場合は、open() メソッドと close() メソッドも実装する必要があります。実装のリファレンスについては smtp.EmailBackend を参照してください。

複数の E メールを送信する

SMTP 接続 (またはその他のネットワーク接続) を確立して閉じることは、負荷の高い処理です。 送信する E メールがたくさんある場合は、E メールを送信するたびに接続の生成と破棄を繰り返すのではなく、SMTP 接続を再利用する方が効率的です。

E メールバックエンドに接続を再利用するよう通知するには、2 つの方法があります。

1 つめは、send_messages() メソッドを使う方法です。send_messages()EmailMessage インスタンス (ないしサブクラス) のリストを取得し、この全てを単一の接続を使って送信します。

例えば、周期的な E メール送信を表す EmailMessage オブジェクトのリストを返す get_notification_email() と呼ばれる関数がある場合、send_messages を 1 度呼び出せばこれらの E メールを送信することができます:

from django.core import mail
connection = mail.get_connection()   # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)

この例では、``send_messages()``を呼び出してバックエンドの接続を開き、メッセージのリストを送信して、最後に接続を閉じます。

2 つめのアプローチは、E メールバックエンドの open() メソッドと close() メソッドを使って手動で接続をコントロールする方法です。send_messages() は、すでに接続が開いている場合、自動で接続を開いたり閉じたりはしません。手動で接続を開いた場合、閉じるタイミングを自分でコントロールできます。例えば:

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

# Manually open the connection
connection.open()

# Construct an email message that uses the connection
email1 = mail.EmailMessage(
    'Hello',
    'Body goes here',
    'from@example.com',
    ['to1@example.com'],
    connection=connection,
)
email1.send() # Send the email

# Construct two more messages
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'],
)

# Send the two emails in a single call -
connection.send_messages([email2, email3])
# The connection was already open so send_messages() doesn't close it.
# We need to manually close the connection.
connection.close()

開発用に E メールを設定する

Django に電子メールをまったく送信させたくない場合もあります。たとえば、ウェブサイトを開発しているときには、多くのメール送信などしたくないでしょう – しかし、適切な条件で適切な人々にメールが送信され、これらの E メールが正しい内容を含むことを検証したいはずです。

ローカル開発用に E メールを設定する最も簡単な方法は、コンソール E メールバックグランドを使うことです。このバックエンドは全ての E メールを stdout にリダイレクトし、メールの内容を調べます。

ファイル E メールバックエンドも開発に役立ちます – このバックエンドは全ての SMTP 接続をファイルにダンプし、都合の良いときに調べることができるようにします。

もう 1 つのアプローチは、”dumb” SMTP サーバを使うことです。これは、E メールをローカルで受け取りターミナルに表示しますが、実際には何も送信しません。Python には、単一のコマンドでこれを実行するビルトインの方法があります:

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

このコマンドは、localhost の ポート 1025 でリッスンするシンプルな SMTP サーバを開始します。このサーバは、単にすべての E メールヘッダーと E メール本文を標準出力に出力します。 EMAIL_HOSTEMAIL_PORT をそれに応じて設定するだけで済みます。 SMTP サーバのオプションの詳細については、smtpd モジュールの Python ドキュメントを参照してください。

アプリケーションでの E メール送信のユニットテストについては、テストのドキュメントの Email services セクションを参照してください。

Back to Top