| revision-up-to: | 11321 (1.1) unfinished |
|---|
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 で設定できます。
ノート
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 からメールを送信する 方法をカスタマイズしたければ、これらのクラスをサブクラス化してやりたいこと を実現できます。
ノート
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)
The are times when you do not want Django to send e-mails at all. For example, while developing a website, you probably don't want to send out thousands of e-mails -- but you may want to validate that e-mails will be sent to the right people under the right conditions, and that those e-mails will contain the correct content.
The easiest way to test your project's use of e-mail is to use a "dumb" e-mail server that receives the e-mails locally and displays them to the terminal, but does not actually send anything. Python has a built-in way to accomplish this with a single command:
python -m smtpd -n -c DebuggingServer localhost:1025
This command will start a simple SMTP server listening on port 1025 of localhost. This server simply prints to standard output all email headers and the email body. You then only need to set the EMAIL_HOST and EMAIL_PORT accordingly, and you are set.
For more entailed testing and processing of e-mails locally, see the Python documentation on the SMTP Server.
Aug 19, 2010