20.12. "smtplib" --- SMTP プロトコルクライアント
************************************************

**ソースコード:** Lib/smtplib.py

======================================================================

"smtplib" モジュールは、SMTPまたはESMTPのリスナーデーモンを備えた任意
のインターネット上のホストにメールを送るために使用することができる
SMTPクライアント・セッション・オブジェクトを定義します。 SMTPおよび
ESMTPオペレーションの詳細は、 **RFC 821** (Simple Mail Transfer
Protocol) や **RFC 1869** (SMTP Service Extensions)を調べてください。

class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])

   "SMTP" インスタンスはSMTPコネクションをカプセル化し、 SMTPとESMTPの
   命令をサポートをします。オプションであるhostとportを与えた場合は、
   SMTPクラスのインスタンスが作成されると同時に、 "connect()" メソッド
   を呼び出し初期化されます。"connect()" 呼び出しが成功コード以外を返
   した場合、 "SMTPConnectError" 例外が送出されます。*local_hostname*
   を指定する場合、これは HELO/EHLO コマンドでのローカルホストの FQDN
   として使われます。指定しない場合はローカルホスト名は
   "socket.getfqdn()" が使われます。オプションの *timeout* 引数を与え
   る場合、コネクションの接続時などのブロックする操作におけるタイムア
   ウト時間を秒数で設定します。(指定されなかった場合は、グローバルのデ
   フォルトタイムアウト設定が利用されます)。タイムアウトに達すると
   "socket.timeout" 例外が送出されます。

   For normal use, you should only require the initialization/connect,
   "sendmail()", and "SMTP.quit()" methods. An example is included
   below.

   バージョン 2.6 で変更: *timeout* が追加されました

class smtplib.SMTP_SSL([host[, port[, local_hostname[, keyfile[, certfile[, timeout]]]]]])

   "SMTP_SSL" のインスタンスは "SMTP" のインスタンスと全く同じように動
   作します。 "SMTP_SSL" は、接続の最初の段階からSSLが要求され、
   "starttls()" では対応できない場合にのみ利用されるべきです。 *host*
   が指定されなかった場合は、localhostが利用されます。 *port* が指定さ
   れなかった場合は、標準の SMTP-over-SSL ポート(465) が利用されます。
   *local_hostname* は "SMTP" クラスのものと同じです。 *keyfile* と
   *certfile* もオプションで、SSL接続のための、PEMフォーマットのプライ
   ベートキーと、証明パス (certificate chain) ファイルを指定することが
   できます。オプションの *timeout* 引数を与える場合、コネクションの接
   続時などのブロックする操作におけるタイムアウト時間を秒数で設定しま
   す (指定されなかった場合は、グローバルのデフォルトタイムアウト設定
   が利用されます)。タイムアウトに達すると "socket.timeout" 例外が送出
   されます。

   バージョン 2.6 で追加.

class smtplib.LMTP([host[, port[, local_hostname]]])

   ESMTPに非常に似ているLMTPプロトコルは、SMTPクライアントに基づいてい
   ます。 LMTPにはよくUnixソケットが利用されるので、 "connect()" メソ
   ッドは通常の host:port サーバーと同じようにUnixソケットもサポートし
   ています。*local_hostname* は "SMTP" クラスのものと同じです。 Unix
   ソケットを指定するには、 *host* 引数に、 '/' で始まる絶対パスを指定
   します。

   認証は、通常のSMTP機構を利用してサポートされています。 Unixソケット
   を利用する場合、LMTPは通常認証をサポートしたり要求したりはしません
   。しかし、あなたが必要であれば、利用することができます。

   バージョン 2.6 で追加.

このモジュールの例外には次のものがあります:

exception smtplib.SMTPException

   このモジュールで提供される全ての例外クラスのベースクラスです。

exception smtplib.SMTPServerDisconnected

   この例外はサーバが突然コネクションを切断するか、もしくは "SMTP" イ
   ンスタンスを生成する前にコネクションを張ろうとした場合に上げられま
   す。

exception smtplib.SMTPResponseException

   SMTPのエラーコードを含んだ例外のクラスです。これらの例外はSMTPサー
   バがエラーコードを返すときに生成されます。エラーコードは
   "smtp_code" 属性に格納されます。また、 "smtp_error" 属性にはエラー
   メッセージが格納されます。

exception smtplib.SMTPSenderRefused

   送信者のアドレスが弾かれたときに上げられる例外です。全ての
   "SMTPResponseException" 例外に、 SMTPサーバが弾いた'sender'アドレス
   の文字列がセットされます。

exception smtplib.SMTPRecipientsRefused

   全ての受取人アドレスが弾かれたときに上げられる例外です。各受取人の
   エラーは属性 "recipients" によってアクセス可能で、
   "SMTP.sendmail()" が返す辞書と同じ並びの辞書になっています。

exception smtplib.SMTPDataError

   SMTPサーバが、メッセージのデータを受け入れることを拒絶した時に上げ
   られる例外です。

exception smtplib.SMTPConnectError

   サーバへの接続時にエラーが発生した時に上げられる例外です。

exception smtplib.SMTPHeloError

   サーバーが "HELO" メッセージを弾いた時に上げられる例外です。

exception smtplib.SMTPAuthenticationError

   SMTP 認証が失敗しました。最もあり得る可能性は、サーバーがユーザ名/
   パスワードのペアを受付なかった事です。

参考:

  **RFC 821** - Simple Mail Transfer Protocol
     SMTP のプロトコル定義です。このドキュメントでは SMTP のモデル、操
     作手順、プロトコルの詳細についてカバーしています。

  **RFC 1869** - SMTP Service Extensions
     SMTP に対する ESMTP 拡張の定義です。このドキュメントでは、新たな
     命令による SMTP の拡張、サーバによって提供される命令を動的に発見
     する機能のサポート、およびいくつかの追加命令定義について記述して
     います。


20.12.1. SMTP オブジェクト
==========================

"SMTP" クラスインスタンスは次のメソッドを提供します:

SMTP.set_debuglevel(level)

   コネクション間でやりとりされるメッセージ出力のレベルをセットします
   。メッセージの冗長さは *level* に応じて決まります。

SMTP.docmd(cmd[, argstring])

   サーバへコマンド *cmd* を送信します。オプション引数 *argstring* は
   スペース文字でコマンドに連結します。

   戻り値は、整数値のレスポンスコードと、サーバからの応答の値をタプル
   で返します。 (サーバからの応答が数行に渡る場合でも一つの大きな文字
   列で返します。)

   通常、この命令を明示的に使う必要はありませんが、自分で拡張するする
   時に使用するときに役立つかもしれません。

   応答待ちのときに、サーバへのコネクションが失われると、
   "SMTPServerDisconnected" が上がります。

SMTP.connect([host[, port]])

   ホスト名とポート番号をもとに接続します。デフォルトはlocalhostの標準
   的なSMTPポート(25番)に接続します。もしホスト名の末尾がコロン("':'")
   で、後に番号がついている場合は、「ホスト名:ポート番号」として扱われ
   ます。このメソッドはコンストラクタにホスト名及びポート番号が指定さ
   れている場合、自動的に呼び出されます。戻り値は、この接続の応答内で
   サーバによって送信された応答コードとメッセージの2要素タプルです。

SMTP.helo([hostname])

   SMTPサーバに "HELO" コマンドで身元を示します。デフォルトでは
   hostname引数はローカルホストを指します。サーバーが返したメッセージ
   は、オブジェクトの "helo_resp" 属性に格納されます。

   通常は "sendmail()" が呼びだすため、これを明示的に呼び出す必要はあ
   りません。

SMTP.ehlo([hostname])

   "EHLO" を利用し、ESMTPサーバに身元を明かします。デフォルトでは
   hostname引数はローカルホストのFQDNです。また、ESMTPオプションのため
   に応答を調べたものは、 "has_extn()" に備えて保存されます。また、幾
   つかの情報を属性に保存します: サーバーが返したメッセージは
   "ehlo_resp" 属性に、 "does_esmtp" 属性はサーバーがESMTPをサポートし
   ているかどうかによって true か false に、 "esmtp_features" 属性は辞
   書で、サーバーが対応しているSMTP サービス拡張の名前と、もしあればそ
   のパラメータを格納します。

   "has_extn()" をメールを送信する前に使わない限り、明示的にこのメソッ
   ドを呼び出す必要があるべきではなく、 "sendmail()" が必要とした場合
   に呼ばれます。

SMTP.ehlo_or_helo_if_needed()

   このメソッドは、現在のセッションでまだ "EHLO" か "HELO" コマンドが
   実行されていない場合、 "ehlo()" and/or "helo()" メソッドを呼び出し
   ます。このメソッドは先に ESMTP "EHLO" を試します。

   "SMTPHeloError"
      サーバーが "HELO" に正しく返事しなかった.

   バージョン 2.6 で追加.

SMTP.has_extn(name)

   *name* が拡張SMTPサービスセットに含まれている場合には "True" を返し
   、そうでなければ "False" を返します。大小文字は区別されません。

SMTP.verify(address)

   "VRFY" を利用してSMTPサーバにアドレスの妥当性をチェックします。妥当
   である場合はコード250と完全な **RFC 822** アドレス(人名)のタプルを
   返します。それ以外の場合は、400以上のエラーコードとエラー文字列を返
   します。

   注釈: ほとんどのサイトはスパマーの裏をかくためにSMTPの "VRFY" は
     使用不 可になっています。

SMTP.login(user, password)

   認証が必要なSMTPサーバにログインします。認証に使用する引数はユーザ
   名とパスワードです。まだセッションが無い場合は、 "EHLO" または
   "HELO" コマンドでセッションを作ります。ESMTPの場合は "EHLO" が先に
   試されます。認証が成功した場合は通常このメソッドは戻りますが、例外
   が起こった場合は以下の例外が上がります:

   "SMTPHeloError"
      サーバーが "HELO" に正しく返事しなかった.

   "SMTPAuthenticationError"
      サーバがユーザ名/パスワードでの認証に失敗した。

   "SMTPException"
      どんな認証方法も見付からなかった。

SMTP.starttls([keyfile[, certfile]])

   TLS(Transport Layer Security)モードでSMTPコネクションを出し、全ての
   SMTPコマンドは暗号化されます。これは "ehlo()" をもう一度呼びだすと
   きにするべきです。

   *keyfile* と *certfile* が提供された場合に、 "socket" モジュールの
   "ssl()" 関数が通るようになります。

   もしまだ "EHLO" か "HELO" コマンドが実行されていない場合、このメソ
   ッドは ESMTP "EHLO" を先に試します。

   バージョン 2.6 で変更.

   "SMTPHeloError"
      サーバーが "HELO" に正しく返事しなかった.

   "SMTPException"
      サーバーが STARTTLS 拡張に対応していない。

   バージョン 2.6 で変更.

   "RuntimeError"
      実行中の Python インタプリタで、SSL/TLS サポートが利用できない。

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])

   メールを送信します。必要な引数は **RFC 822** のfromアドレス文字列、
   **RFC 822** のtoアドレス文字列またはアドレス文字列のリスト、メッセ
   ージ文字列です。送信側は "MAIL FROM" コマンドで使用される
   *mail_options* の ESMTPオプション("8bitmime" のような)のリストを得
   るかもしれません。全ての "RCPT" コマンドで使われるべきESMTPオプショ
   ン (例えば "DSN" コマンド)は、 *rcpt_options* を通して利用すること
   ができます。(もし送信先別にESMTPオプションを使う必要があれば、メッ
   セージを送るために "mail()" 、 "rcpt()" 、 "data()" といった下位レ
   ベルのメソッドを使う必要があります。)

   注釈: 配送エージェントは *from_addr* 、 *to_addrs* 引数を使い、メ
     ッセー ジのエンベロープを構成します。 "SMTP" はメッセージヘッダを
     修正し ません。

   まだセッションが無い場合は、 "EHLO" または "HELO" コマンドでセッシ
   ョンを作ります。ESMTPの場合は "EHLO" が先に試されます。また、サーバ
   がESMTP対応ならば、メッセージサイズとそれぞれ指定されたオプションも
   渡します。(featureオプションがあればサーバの広告をセットします)
   "EHLO" が失敗した場合は、ESMTPオプションの無い "HELO" が試されます
   。

   このメソッドは最低でも1つの受信者にメールが受け入れられたときは普通
   に戻りますが、そうでない場合は例外を投げます。このメソッドが例外を
   投げられなければ、誰かが送信したメールを得るべきです。また、例外を
   投げれなかった場合は、拒絶された受取人ごとへの1つのエントリーと共に
   、辞書を返します。各エントリーは、サーバーによって送られたSMTPエラ
   ーコードおよびエラーメッセージのタプルを含んでいます。

   このメソッドは次の例外を上げることがあります:

   "SMTPRecipientsRefused"
      全ての受信を拒否され、誰にもメールが届けられませんでした。例外オ
      ブジェクトの "recipients" 属性は、受信拒否についての情報の入った
      辞書オブジェクトです。 (辞書は少なくとも一つは受信されたときに似
      ています)。

   "SMTPHeloError"
      サーバーが "HELO" に正しく返事しなかった.

   "SMTPSenderRefused"
      サーバが *from_addr* を受理しませんでした。

   "SMTPDataError"
      サーバが予期しないエラーコードを返しました (受信拒否以外)。

   また、この他の注意として、例外が上がった後もコネクションは開いたま
   まになっています。

SMTP.quit()

   SMTPセッションを終了し、コネクションを閉じます。 SMTP "QUIT" コマン
   ドの結果を返します。

   バージョン 2.6 で変更: 結果を返すようになりました

下位レベルのメソッドは標準SMTP/ESMTPコマンド "HELP" 、 "RSET" 、
"NOOP" 、 "MAIL" 、 "RCPT" 、 "DATA" に対応しています。通常これらは直
接呼ぶ必要はなく、また、ドキュメントもありません。詳細はモジュールのコ
ードを調べてください。


20.12.2. SMTP 使用例
====================

次の例は最低限必要なメールアドレス('To' と 'From')を含んだメッセージを
送信するものです。この例では **RFC 822** ヘッダの加工もしていません。
メッセージに含まれるヘッダは、メッセージに含まれる必要があり、特に、明
確な'To'、と'From'アドレスはメッセージヘッダに含まれている必要がありま
す。

   import smtplib

   def prompt(prompt):
       return raw_input(prompt).strip()

   fromaddr = prompt("From: ")
   toaddrs  = prompt("To: ").split()
   print "Enter message, end with ^D (Unix) or ^Z (Windows):"

   # Add the From: and To: headers at the start!
   msg = ("From: %s\r\nTo: %s\r\n\r\n"
          % (fromaddr, ", ".join(toaddrs)))
   while 1:
       try:
           line = raw_input()
       except EOFError:
           break
       if not line:
           break
       msg = msg + line

   print "Message length is " + repr(len(msg))

   server = smtplib.SMTP('localhost')
   server.set_debuglevel(1)
   server.sendmail(fromaddr, toaddrs, msg)
   server.quit()

注釈: 多くの場合、 "email" パッケージの機能を使って email メッセージ
  を構築 し、それを文字列に変換して、 "sendmail()" で送信する、という
  手順を用 います。 email: 使用例 を参照してください。
