# `smtpd` --- SMTP サーバー

ソースコード: Lib/smtpd.py

このモジュールは SMTP (email) サーバを実装するためのいくつかのクラスを提供しています。

参考

The aiosmtpd package is a recommended replacement for this module. It is based on `asyncio` and provides a more straightforward API. `smtpd` should be considered deprecated.

サーバの実装がいくつかあります。一つはジェネリックで何もしない実装で、オーバーライドすることが出来ます。他の二つは特定のメール送信方策を提供しています。

また、SMTPChannel を拡張して SMTP クライアントとの特定の相互作用挙動を実装することができます。

コードは RFC 5321 に加え、RFC 1870 SIZE と RFC 6531 SMTPUTF8 拡張をサポートしています。

## SMTPServer オブジェクト

class `smtpd.``SMTPServer`(localaddr, remoteaddr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)

  新たな `SMTPServer` オブジェクトを作成し、それをローカルのアドレス localaddr に関連づけ (bind) ます。 このオブジェクトは remoteaddr を上流の SMTP リレー先とします。 localaddr と remoteaddr のどちらも (host, port) タプルである必要があります。 このクラスは `asyncore.dispatcher` を継承しており、インスタンス化時に自身を `asyncore` のイベントループに登録します。

  data_size_limit には `DATA` コマンドが受け取る最大のバイト数を指定します。 `None` や `0` の場合上限はありません。

  map is the socket map to use for connections (an initially empty dictionary is a suitable value). If not specified the `asyncore` global socket map is used.

  enable_SMTPUTF8 determines whether the `SMTPUTF8` extension (as defined in RFC 6531) should be enabled. The default is `False`. When `True`, `SMTPUTF8` is accepted as a parameter to the `MAIL` command and when present is passed to `process_message()` in the `kwargs['mail_options']` list. decode_data and enable_SMTPUTF8 cannot be set to `True` at the same time.

  decode_data specifies whether the data portion of the SMTP transaction should be decoded using UTF-8. When decode_data is `False` (the default), the server advertises the `8BITMIME` extension (RFC 6152), accepts the `BODY=8BITMIME` parameter to the `MAIL` command, and when present passes it to `process_message()` in the `kwargs['mail_options']` list. decode_data and enable_SMTPUTF8 cannot be set to `True` at the same time.

  `process_message`(peer, mailfrom, rcpttos, data, **kwargs)

    このクラスでは `NotImplementedError` 例外を送出します。受信したメッセージを使って何か意味のある処理をしたい場合にはこのメソッドをオーバライドしてください。コンストラクタの remoteaddr に渡した値は `_remoteaddr` 属性で参照できます。 peer はリモートホストのアドレスで、 mailfrom はメッセージエンベロープの発信元 (envelope originator) 、 rcpttos はメッセージエンベロープの受信対象、そして data は電子メールの内容が入った(RFC 5321 形式の)文字列です。

    decode_data コンストラクタ引数が `True` の場合、 data 引数はユニコード文字列です。`False` の場合は bytes オブジェクトです。

    kwargs is a dictionary containing additional information. It is empty if `decode_data=True` was given as an init argument, otherwise it contains the following keys:

    > mail_options:

    >   `MAIL` コマンドが受け取る全ての引数のリストです (要素は大文字の文字列です; 例えば `['BODY=8BITMIME', 'SMTPUTF8']`)。

    > rcpt_options:

    >   `RCPT` コマンドのものである点以外は mail_options と同じです。今のところ `RCPT TO` オプションはサポートされていないため、これは常に空のリストです。

    将来の仕様改善によって kwargs 辞書にキーが追加される可能性があるため、 `process_message` の実装で追加のキーワード引数を受け取るには `**kwargs` シグニチャを使うべきです。

    通常の `250 Ok` 応答には `None` を返します。そうでない場合求められる応答を RFC 5321 形式の文字列で返します。

  `channel_class`

    これを派生クラスでオーバーライドすることで、SMTP クライアントを管理するのにカスタムの `SMTPChannel` を使います。

  バージョン 3.4 で追加: map コンストラクタ引数。

  バージョン 3.5 で変更: localaddr および remoteaddr は IPv6 アドレスを持てるようになりました。

  バージョン 3.5 で追加: The decode_data and enable_SMTPUTF8 constructor parameters, and the kwargs parameter to `process_message()` when decode_data is `False`.

  バージョン 3.6 で変更: decode_data がデフォルトで `False` になりました。

## DebuggingServer オブジェクト

class `smtpd.``DebuggingServer`(localaddr, remoteaddr)

  新たなデバッグ用サーバを生成します。引数は `SMTPServer` と同じです。メッセージが届いても無視し、標準出力に出力します。

## PureProxy オブジェクト

class `smtpd.``PureProxy`(localaddr, remoteaddr)

  新たな単純プロキシ (pure proxy) サーバを生成します。引数は `SMTPServer` と同じです。全てのメッセージを remoteaddr にリレーします。このオブジェクトを動作させるとオープンリレーを作成してしまう可能性が多分にあります。注意してください。

## MailmanProxy Objects

class `smtpd.``MailmanProxy`(localaddr, remoteaddr)

  新たな単純プロキシサーバを生成します。引数は `SMTPServer` と同じです。全てのメッセージを remoteaddr にリレーしますが、 ローカルの mailman の設定に remoteaddr がある場合には mailman を使って処理します。このオブジェクトを動作させるとオープンリレーを 作成してしまう可能性が多分にあります。注意してください。

## SMTPChannel オブジェクト

class `smtpd.``SMTPChannel`(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)

  サーバと一つの SMTP クライアント間の通信を管理する `SMTPChannel` オブジェクトを新たに生成します。

  conn and addr are as per the instance variables described below.

  data_size_limit には `DATA` コマンドが受け取る最大のバイト数を指定します。 `None` や `0` の場合上限はありません。

  enable_SMTPUTF8 determines whether the `SMTPUTF8` extension (as defined in RFC 6531) should be enabled. The default is `False`. decode_data and enable_SMTPUTF8 cannot be set to `True` at the same time.

  A dictionary can be specified in map to avoid using a global socket map.

  decode_data specifies whether the data portion of the SMTP transaction should be decoded using UTF-8. The default is `False`. decode_data and enable_SMTPUTF8 cannot be set to `True` at the same time.

  To use a custom SMTPChannel implementation you need to override the `SMTPServer.channel_class` of your `SMTPServer`.

  バージョン 3.5 で変更: 引数 decode_data と enable_SMTPUTF8 が追加されました.

  バージョン 3.6 で変更: decode_data がデフォルトで `False` になりました。

  `SMTPChannel` は以下のインスタンス変数を持っています:

  `smtp_server`

    このチャンネルを生成した `SMTPServer` を保持します。

  `conn`

    クライアントに接続しているソケットオブジェクトを保持します。

  `addr`

    Holds the address of the client, the second value returned by `socket.accept`

  `received_lines`

    Holds a list of the line strings (decoded using UTF-8) received from the client. The lines have their `"\r\n"` line ending translated to `"\n"`.

  `smtp_state`

    Holds the current state of the channel. This will be either `COMMAND` initially and then `DATA` after the client sends a "DATA" line.

  `seen_greeting`

    Holds a string containing the greeting sent by the client in its "HELO".

  `mailfrom`

    Holds a string containing the address identified in the "MAIL FROM:" line from the client.

  `rcpttos`

    Holds a list of strings containing the addresses identified in the "RCPT TO:" lines from the client.

  `received_data`

    Holds a string containing all of the data sent by the client during the DATA state, up to but not including the terminating `"\r\n.\r\n"`.

  `fqdn`

    Holds the fully-qualified domain name of the server as returned by `socket.getfqdn()`.

  `peer`

    Holds the name of the client peer as returned by `conn.getpeername()` where `conn` is `conn`.

  The `SMTPChannel` operates by invoking methods named `smtp_<command>` upon reception of a command line from the client. Built into the base `SMTPChannel` class are methods for handling the following commands (and responding to them appropriately):

  コマンド | 行う動作
  --- | ---
  HELO | クライアントのグリーティングを受け取り `seen_greeting` に格納します。サーバを基本コマンドモードに設定します。
  EHLO | クライアントのグリーティングを受け取り `seen_greeting` に格納します。サーバを拡張コマンドモードに設定します。
  NOOP | 何もしません。
  QUIT | 接続をきれいに閉じます。
  MAIL | "MAIL FROM:" シンタックスを受け取り提供されたアドレスを `mailfrom` として保存します。拡張コマンドモードでは RFC 1870 SIZE 属性を受け取り data_size_limit の値に基づき適切に応答します。
  RCPT | "RCPT TO:" シンタックスを受け取り提供されたアドレスを `rcpttos` リストに格納します。
  RSET | `mailfrom`, `rcpttos`, `received_data` をリセットしますが、グリーティングはリセットしません。
  DATA | 内部状態を `DATA` に設定し、クライアントからの残りの行を終端子 `"\r\n.\r\n"` を受け取るまで `received_data` に格納します。
  HELP | 最小の情報をコマンドシンタックスで返します。
  VRFY | コード 252 (サーバはアドレスが有効か分かりません) を返します。
  EXPN | コマンドが実装されていないことを報告します。