# 21.18. `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 拡張をサポートしています。

## 21.18.1. 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)

    Raise a `NotImplementedError` exception. Override this in subclasses to do something useful with this message. Whatever was passed in the constructor as remoteaddr will be available as the `_remoteaddr` attribute. peer is the remote host's address, mailfrom is the envelope originator, rcpttos are the envelope recipients and data is a string containing the contents of the e-mail (which should be in RFC 5321 format).

    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 is now `False` by default.

## 21.18.2. DebuggingServer オブジェクト

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

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

## 21.18.3. PureProxy オブジェクト

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

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

## 21.18.4. MailmanProxy Objects

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

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

## 21.18.5. 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 で変更: The decode_data and enable_SMTPUTF8 parameters were added.

  バージョン 3.6 で変更: decode_data is now `False` by default.

  `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 | コマンドが実装されていないことを報告します。