メールを送信する¶
Python では smtplib
モジュールを使ってメールを比較的簡単に送ることができますが、Django はさらにいくつかの軽いラッパーを用意しています。これらのラッパーは、 メールをよりすばやく送信したり、開発中にメール送信をテストしたり、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,
)
設定内の EMAIL_HOST
と EMAIL_PORT
で指定された SMTP ホストとポートを使用して、メールが送信されます。EMAIL_HOST_USER
と EMAIL_HOST_PASSWORD
が指定されている場合は、SMTP サーバーの認証に使われます。そして、EMAIL_USE_TLS
と EMAIL_USE_SSL
設定により、セキュアコネクションを使うかどうかをコントロールします。
注釈
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, html_message=None)[ソース]¶
メールを送信するもっとも簡単な方法は、django.core.mail.send_mail()
を使うことです。
subject
、message
、from_email
、recipient_list
の 4 つの引数は必須です。
subject
: 文字列。message
: 文字列。from_email
: 文字列。recipient_list
: メールアドレスを表す文字列のリスト。recipient_list
の各メンバーは、メールメッセージの 「To:」 フィールドで他の受信者を見ることができます。fail_silently
: 真偽値。False
の場合、send_mail
はsmtplib.SMTPException
を投げます。発生しうる例外については、smtplib
ドキュメントを参照してください。これらの例外は、すべてSMTPException
のサブクラスです。auth_user
: SMTP サーバー認証のためのユーザー名で、省略可能。指定されなかった場合、DjangoEMAIL_HOST_USER
設定の値を使います。auth_password
: SMTP サーバー認証のためのパスワードで、省略可能。指定されなかった場合、Django はEMAIL_HOST_PASSWORD
設定の値を使います。connection
: メール送信のために使うバックエンドで、省略可能。指定しなかった場合、デフォルトのバックエンドのインスタンスが使われます。詳しくは メールのバックエンド を参照してください。html_message
:html_message
が指定された場合、送信されるメールは multipart/alternative となり、text/plain コンテンツタイプを持つmessage
と text/html コンテンツタイプを持つhtml_message
を合わせ持つものになります。
返り値は、送信に成功したメッセージの数です (送信されるメッセージが 1 つだけの場合もあるため、0
や 1
になることもあります)。
send_mass_mail()
¶
-
send_mass_mail
(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)[ソース]¶
django.core.mail.send_mass_mail()
は、大量のメール送信を扱うために用意されています。
datatuple
はメッセージの集合を表すタプルです。タプル内の各要素は、それぞれ1種類のメッセージを表すタプルであり、次の形式を持ちます。
(subject, message, from_email, recipient_list)
fail_silently
、auth_user
、auth_password
の 3 つは、send_mail()
と同じように機能します。
datatuple
に含まれる各要素は、最終的には別々のメールメッセージとなります。send_mail()
における挙動と同じく、recipient_list
内の受信者は、メールメッセージの 「To:」 フィールドに書かれている他の受信者のアドレスを見ることができます。
たとえば、次のコードは異なる 2 つのメッセージを 異なる 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()
¶
django.core.mail.mail_admins()
は、ADMINS
設定で定義されているサイト管理者 (admin) に対してメールを送信するためのショートカットです。
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()
¶
django.core.mail.mail_managers()
は、mail_admins()
とほぼ同じで、MANAGERS
設定で定義されているサイト管理者 (manager) にメールを送信します。
例¶
以下の例は、john@example.com と jane@example.com に1つのメールを送信します。2人とも 「To:」 内に宛先が見られます。
send_mail(
'Subject',
'Message.',
'from@example.com',
['john@example.com', 'jane@example.com'],
)
次の例は、john@example.com と jane@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 のスタイル) が含まれている場合、email 関数 (例えば send_mail()
) は django.core.mail.BadHeaderError
(ValueError
のサブクラス) 投げるため、メールは送信されません。メール送信を行う関数にデータを渡す前に、開発者は責任を持ってすべてのデータを検証しておく必要があります。
message
が文字列の最初にヘッダを含む場合、ヘッダは単にメールメッセージの最初のビットとして表示されます。
次の例は、リクエストの POST データから subject
、message
、from_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 の利用、ファイル添付やマルチパートのメールなど) EmailMessage
のインスタンスを直接作成する必要があります。
注釈
これは設計特性です。send_mail()
およびその関連の関数は、元は Django が提供した唯一のインタフェースでした。しかし、受け入れるパラメータのリストが次第に肥大化してきてしまったので、よりオブジェクト指向的な設計に移行し、元の関数は後方互換性確保のためだけに残すことになりました。
EmailMessage
はメールメッセージ本体を作成する役割を担っており、その後、メールのバックエンド がメールを送信する役目を果たします。
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
オブジェクト¶
EmailMessage
クラスは、以下のパラメータで (省略可能な引数が使われた場合、その順番で) 初期化されます。全てのパラメータは省略可能で、send()
メソッドを呼ぶ前のタイミングでセットされます。
subject
: メールの件名の行。body
: 本文のテキスト。プレーンテキストのメッセージでなければなりません。from_email
: 送信者のアドレス。fred@example.com
とFred <fred@example.com>
の2つの形式が使用できます。省略した場合、DEFAULT_FROM_EMAIL
設定が使われます。to
: 受信者のメールアドレスのリストまたはタプル。bcc
: メールを送信するときに 「Bcc」 ヘッダ内で使われるメールアドレスのリストまたはタプル。connection
: メールバックエンドのインスタンス。複数のメッセージに同一の接続を使いたいときに指定します。省略した場合、send()
が呼ばれる時に新しい接続が生成されます。attachments
: メッセージに添付されるファイルのリスト。email.MIMEBase.MIMEBase
のインスタンスか、(filename, content, mimetype)
のトリプルのどちらかで指定できます。headers
: メッセージに追加するヘッダーの辞書。キーはヘッダ名、値はヘッダ値です。メールメッセージに対して適切なヘッダ名と値にするのは、呼び出す側の責任です。対応する属性はextra_headers
です。- メールを送信するときに 「Cc」 ヘッダ内で使われる、受信者のアドレスのリストまたはタプル。
reply_to
: メールを送信するときに 「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)
はメッセージを送信します。メールの構築時に接続が指定された場合、その接続が使用されます。 それ以外の場合は、デフォルトのバックエンドがインスタンス化され、使用されます。 キーワード引数fail_silently
がTrue
の場合、メッセージの送信中に投げられた例外は破棄されます。 受信者の空のリストは例外を投げません。message()
はdjango.core.mail.SafeMIMEText
オブジェクト (Python のemail.MIMEText.MIMEText
クラスのサブクラスです) か、送信メッセージを保持するdjango.core.mail.SafeMIMEMultipart
オブジェクトを構築します。EmailMessage
クラスを拡張する必要がある場合は、このメソッドをオーバーライドして、お望みのコンテンツを MIME オブジェクトに入れることをお勧めします。recipients()
は、to
、cc
、bcc
のいずれかの属性に記録されている、メッセージの全ての受信者のリストを返します。サブクラス化するときには、メッセージの送信時に SMTP サーバが受信者の完全な一覧を必要とするため、このメソッドもオーバーライドする必要があります。クラス内で受信者を指定する別の方法を追加する場合は、このメソッドからも返される必要があります。attach()
は新しい添付ファイルを作成し、メッセージに追加します。attach()
を呼ぶには2 つの方法があります。email.MIMEBase.MIMEBase
のインスタンスである単一の引数を引き渡します。生成されるメッセージに直接挿入されます。もしくは、
attach()
の 3 つの引数を引き渡します:filename
、content
、mimetype
です。filename
は、メール内に表示される添付ファイルの名前です。content``は、添付ファイル内に含まれるデータです。``mimetype
は添付ファイルに対する MIME タイプで、省略可能です。mimetype
を省略した場合、MIME コンテンツタイプは添付ファイルのファイル名から推測されます。For example:
message.attach('design.png', img_data, 'image/png')
message/rfc822
のmimetype
を指定した場合、django.core.mail.EmailMessage
とemail.message.Message
も受け入れます。For a
mimetype
starting withtext/
, content is expected to be a string. Binary data will be decoded using UTF-8, and if that fails, the MIME type will be changed toapplication/octet-stream
and the data will be attached unchanged.さらに、
message/rfc822
添付ファイルは RFC 2046#section-5.2.1 の Base64 エンコード違反とはなりません。これは、Evolution と Thunderbird 内の添付ファイルの表示での問題の原因となります。
attach_file()
は、あなたのファイルシステムにあるファイルを使って新しい添付ファイルを作成します。添付するファイルのパスとともに呼び出してください。MIME タイプも指定できますが省略可能です。MIME タイプを省略した場合、ファイル名から推測されます。最も簡単な使い方は以下の通りです:message.attach_file('/images/weather_map.png')
For MIME types starting with
text/
, binary data is handled as inattach()
.
Added the fallback to MIME type application/octet-stream
when binary
data for a text/*
attachment cannot be decoded.
代替のコンテンツタイプを送信する¶
メール内にコンテンツの複数のバージョンを入れておくのが便利です; 古典的な手法では、メッセージをテキストと HTML の両方のバージョンで送信します。 Django のメールのライブラリで、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"
です。この設定だとメールクライアントにかかわらず全ての受信者がメールを読むことができるので、このままにしておくのが実用的です。しかし、受信者が代替のコンテンツタイプを扱えることが確かな場合には、EmailMessage
の content_subtype
属性を使ってメインのコンテンツタイプを変更することもできます。主なタイプは常に "text"
ですが、サブタイプを変更することができます。例えば:
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
メールのバックエンド¶
実際のメール送信は、メールバックエンドによって処理されます。
メールバックエンドのクラスには以下のメソッドがあります:
open()
は、長寿命のメール送信の接続をインスタンス化します。close()
は、現在のメール送信の接続を閉じます。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()
メールバックエンドのインスタンスを取得する¶
django.core.mail
内の get_connection()
関数は、利用可能なメールバックエンドのインスタンスを返します。
デフォルトでは、get_connection()
を呼び出すと EMAIL_BACKEND
内で指定されたメールバックエンドのインスタンスを返します。backend
引数を指定した場合、そのバックエンドがインスタンス化されます。
fail_silently
引数は、バックエンドがエラーをどのように扱うかをコントロールします。fail_silently
が True の場合、メール送信プロセスの間に発生した例外は何の通知もされずに無視されます。
他の全ての引数は、メールバックエンドのコンストラクタに直接引き渡されます。
Django には複数のメール送信バックエンドを付属しています。SMTP バックエンド (デフォルトです) を除いて、これらのバックエンドはテストと開発のみで役立ちます。特別なメール送信が必要な場合には、独自のメールバックエンドを記述する を参照してください。
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)¶ デフォルトのバックエンド。メールは SMTP サーバを通して送信されます。
引数が
None
の場合、各引数に対する値は、以下のそれぞれの設定から取得されます。host
:EMAIL_HOST
port
:EMAIL_PORT
username
:EMAIL_HOST_USER
password
:EMAIL_HOST_PASSWORD
use_tls
:EMAIL_USE_TLS
use_ssl
:EMAIL_USE_SSL
timeout
:EMAIL_TIMEOUT
ssl_keyfile
:EMAIL_SSL_KEYFILE
ssl_certfile
:EMAIL_SSL_CERTFILE
SMTP バックエンドは、Django によって継承されるデフォルトの構成です。明示的に指定したい場合は、設定内で以下の通り記述してください:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
指定しなかった場合は、デフォルトの
timeout
はsocket.getdefaulttimeout()
によって指定されたものになり、デフォルトはNone
(タイムアウトなし) になります。
コンソールバックエンド¶
実際のメールを送信する代わりに、コンソールバックエンドは単に標準出力に送信されるメールを書き込みます。 デフォルトでは、コンソールバックエンドは stdout
に書き込みます。 接続を構築するときに stream
キーワード引数を指定することで、別のストリーム的なオブジェクトを使用できます。
このバックエンドを指定するには、設定内に以下の通り記述してください:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
このバックエンドはプロダクトでの使用を想定していません – 開発中の利便性のために提供されています。
ファイルバックエンド¶
ファイルバックエンドは、メールをファイルに書き込みます。新しいファイルは、このバックエンド上で開いたそれぞれの新しいセッションに対して作成されます。ファイルが書き込まれるディレクトリは、 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'
このバックエンドはプロダクトでの使用を想定していません – 開発中の利便性のために提供されています。
独自のメールバックエンドを定義する¶
メール送信の方法を変更する必要がある場合、独自のメールバックエンドを記述することができます。設定ファイル内の EMAIL_BACKEND
設定が独自のバックエンドのクラスへの Python のインポートパスとなります。
独自のメールバックエンドは、django.core.mail.backends.base
にある BaseEmailBackend
をサブクラス化して作ります。独自のメールバックエンドには send_messages(email_messages)
メソッドを実装する必要があります。このメソッドは EmailMessage
インスタンスのリストを受け取り、送信に成功したメッセージの数を返します。バックエンドに持続瀬的なセッションや接続の概念がある場合は、open()
メソッドと close()
メソッドも実装する必要があります。実装のリファレンスについては smtp.EmailBackend
を参照してください。
複数のメールを送信する¶
SMTP 接続 (またはその他のネットワーク接続) の確立とクローズは、負荷の高い処理です。 送信するメールがたくさんある場合は、メールを送信するたびに接続の生成と破棄を繰り返すのではなく、SMTP 接続を再利用する方が効率的です。
メールバックエンドに接続を再利用するよう通知するには、2 つの方法があります。
1つ目は、send_messages()
メソッドを使う方法です。send_messages()
は EmailMessage
インスタンス (ないしサブクラス) のリストを取得し、この全てを単一の接続を使って送信します。
例えば、定期的なメール送信を表す EmailMessage
オブジェクトのリストを返す get_notification_email()
と呼ばれる関数がある場合、send_messages を 1度呼び出すだけでこれらのメールを送信することができます:
from django.core import mail
connection = mail.get_connection() # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)
この例では、send_messages()
を呼び出してバックエンドの接続を開き、メッセージのリストを送信した後、再び接続を閉じています。
2つ目のアプローチは、メールバックエンドの 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()
開発用にメールを設定する¶
Django に電子メールをまったく送信させたくない場合もあるでしょう。たとえば、ウェブサイトの開発中に数千通のメールを送信したくはないでしょう。しかし、適切な条件で適切な人々にメールが送信され、これらのメールが正しい内容を含んでいるか検証したいことがあるかもしれません。
ローカル開発用にメールを設定する最も簡単な方法は、コンソール メールバックエンドを使うことです。このバックエンドは全てのメールを stdout にリダイレクトし、メールの内容を調べます。
ファイル メールバックエンドも開発に役立ちます – このバックエンドは全ての SMTP 接続をファイルにダンプし、都合の良いときに調べられるようにします。
もう 1 つのアプローチは、」dumb」 SMTP サーバを使うことです。これは、メールをローカルで受け取りターミナルに表示しますが、実際には何も送信しません。Python には、単一のコマンドでこれを実行するビルトインの方法があります。
python -m smtpd -n -c DebuggingServer localhost:1025
このコマンドは、localhost の ポート 1025 でリッスンするシンプルな SMTP サーバを開始します。このサーバは、単にすべてのメールヘッダーと E メール本文を標準出力に出力します。 EMAIL_HOST
と EMAIL_PORT
をそれに応じて設定するだけで済みます。 SMTP サーバのオプションの詳細については、smtpd
モジュールの Python ドキュメントを参照してください。
アプリケーションでのメール送信のユニットテストについては、テストのドキュメントの Email services セクションを参照してください。