revision-up-to: | 8961 (1.0) |
---|
Python の smtplib ライブラリ を使えば、比較的簡単に電子メールを送信でき ますが、 Django ではこのライブラリへの軽量ラッパを二つ用意して、電子メール の送信を極めて素早くおこなえるようにしています。
コードは: 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 設定の値に設定されます。
電子メールを送信する最も簡単な方法は django.core.mail.send_mail() 関数です。この関数の定義は以下の通りです:
- send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None)¶
subject, message, from_email および recipient_list は必須の パラメタです。
django.core.mail.send_mass_mail() は一括電子メール (mass e-mail) の送信 用の関数です。この関数の定義は以下の通りです:
- send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None)¶
datatuple はタプルで、各要素は以下の形式になっています:
(subject, message, from_email, recipient_list)
fail_silently, auth_user および auth_password は send_mail() と同じです。
datatuple の各要素ごとに個別の電子メールメッセージを作成して送信します。 send_mail() と同様、同じ recipient_list に入っている受信者は、他の 受信者を "To:" フィールドで見られます。
send_mass_mail() と send_mail() の大きな違いは、 send_mail() は実行の度にメールサーバに接続するのに対し、 send_mass_mail() は全ての メッセージの送信に一つの接続を使う点です。このため、 send_mass_mail() の方が少しだけ効率的です。
django.core.mail.mail_admins() は ADMINS に書かれたサイト管 理者への電子メール送信を行うためのショートカットです。関数の定義は以下の通 りです:
- mail_admins(subject, message, fail_silently=False)¶
mail_admins() はサブジェクトの先頭に EMAIL_SUBJECT_PREFIX の 設定値を付加します。デフォルトは "[Django] " です。
電子メールの "From:" ヘッダには SERVER_EMAIL の設定値が入ります。
このメソッドは利便性と可読性のために用意されています。
django.core.mail.mail_managers() は mail_admins と同じですが、 電子メールを MANAGERS に書かれたサイトマネジャに送信します 関数は以下のように定義されています:
.. function:: mail_managers(subject, message, fail_silently=False)
以下の例は、単一の電子メールを john@example.com と jane@example.com に送信 します。両方の宛先が "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 形式の) 改行を含む場 合、電子メール送信関数 (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.')
Django の send_mail() および send_mass_mail() 関数は、実際には django.core.mail の EmailMessage クラスや SMTPConnection クラス に対して薄いラッパをかぶせたものにすぎません。 Django からメールを送信する 方法をカスタマイズしたければ、これらのクラスをサブクラス化してやりたいこと を実現できます。
Note
send_mail() をはじめとしたラッパ関数から利用できる機能は、 EmailMessage クラスで提供している全ての機能をカバーしているわけでは ありません。BCC への宛先を指定やファイルの添付、マルチパート形式メール の送信を行いたい場合には、 EmailMessage インスタンスを直接生成する 必要があります。
send_mail() がこのようないささかややこしい仕様なのは、設計上の事情 によるものです。 send_mail() などの関数はもともと単なる Django 向け の単純なメールインタフェースでしかありませんでした。その後、 send_mail() に指定できるパラメタが少しづつふえてきたのです。今となっ ては、メールメッセージを扱うためのよりオブジェクト指向の設計に移行して、 send_mail() は互換性のためだけにおいておく方が有意義でしょう。
一般に、 EmailMessage はメールメッセージ自体の生成に関わります。 SMTPConnection はメール送信処理におけるネットワーク接続に関わっています。 このことは、同じ接続 (SMTPConnection インスタンス) を再利用すれば、複数 のメッセージを一括送信できることを示しています。
EmailMessage クラスは以下のパラメタ (固定引数を使う場合には以下に示す順 番に指定します) で初期化します。パラメタは全て省略可能で、 send() メソッ ドを呼び出す前であればいつでも設定しなおせます。
例を示します:
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) メソッドを呼び出すと、 connection 属 性に指定した接続を使ってメッセージを送信します。接続がなければ、自動的 に新たな接続を生成して使います。 fail_silently を True にすると、 メッセージ送信に失敗した場合に例外を送出します。
message() は django.core.mail.SafeMIMEText クラス (Python の email.MIMEText.MIMEText クラスのサブクラス) または django.core.mail.SafeMIMEMultipart クラスのインスタンスを生成します。 このオブジェクトには送信するメッセージが入っています。 EmailMessage クラスを拡張する必要がある場合、おそらくこのメソッドを オーバライドして、所望の内容を MIME オブジェクト内に配置することになるで しょう。
recipients() はメッセージの全ての宛先からなるリストを返します。この 宛先リストは、 to と bcc に指定した全ての宛先が入ります。 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()
デフォルトでは、 EmailMessage の body パラメタの MIME タイプは "text/plain" です。実践的には、このパラメタは変更せずにおいた方がよいで しょう。なぜなら、メールを受信した人が使っているメールクライアントソフトに 関係なくメッセージを読めるよう保証できるからです。とはいえ、メールの読み手 が拡張コンテンツ形式 (alternative content type) のメッセージを扱えると分かっ ている場合には、 EmailMessage の content_subtype 属性を使って、主メッ セージのコンテンツタイプを変更できます。メールのメジャーコンテンツタイプは 常に "text" ですが、サブタイプは以下のように変更できます:
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
SMTPConnection クラスの初期化は、SMTP サーバのホスト、ポート、SMTP 接続 を行うユーザ名、そしてパスワードを指定して初期化でき、それぞれのパラメタは host, port, username, password オプションで指定します。パラ メタを省略すると、設定ファイルから値を読み出します。
たくさんの数のメッセージを一度に送信したいなら、 SMTPConnection クラス の send_messages() メソッドが便利です。このクラスは EmailMessage ク ラス (またはサブクラス) のインスタンスのリストを引数にとり、一つの SMTP 接 続で一度に送信します。例えば、 get_notification_email() という関数があ り、この関数が定期的に送信されるメールの入った EmailMessage オブジェク トのリストを返すとしましょう。メッセージは以下のようにして一括送信できます:
connection = SMTPConnection() # デフォルトの設定で接続を作成
messages = get_notification_email()
connection.send_messages(messages)
Aug 31, 2012