## libmilter/mfapi.h

libmilter/mfapi.h — libmilter互換API

## Functions

#define | SM_LM_VRS_MAJOR()
#define | SM_LM_VRS_MINOR()
#define | SM_LM_VRS_PLVL()
int | smfi_opensocket ()
int | smfi_register ()
int | smfi_main ()
int | smfi_setbacklog ()
int | smfi_setdbg ()
int | smfi_settimeout ()
int | smfi_setconn ()
int | smfi_stop ()
int | smfi_version ()
char * | smfi_getsymval ()
int | smfi_setreply ()
int | smfi_setmlreply ()
int | smfi_addheader ()
int | smfi_chgheader ()
int | smfi_insheader ()
int | smfi_chgfrom ()
int | smfi_addrcpt ()
int | smfi_addrcpt_par ()
int | smfi_delrcpt ()
int | smfi_progress ()
int | smfi_replacebody ()
int | smfi_quarantine ()
int | smfi_setpriv ()
void * | smfi_getpriv ()
int | smfi_setsymlist ()

## Types and Values

#define | SMFI_VERSION
#define | MI_SUCCESS
#define | MI_FAILURE
typedef | SMFICTX
typedef | SMFICTX_PTR
typedef | smfiDesc_str
typedef | smfiDesc_ptr
typedef | sfsistat
#define | bool
#define | true
#define | false
struct | smfiDesc
#define | SMFIF_ADDHDRS
#define | SMFIF_CHGBODY
#define | SMFIF_MODBODY
#define | SMFIF_ADDRCPT
#define | SMFIF_DELRCPT
#define | SMFIF_CHGHDRS
#define | SMFIF_QUARANTINE
#define | SMFIF_CHGFROM
#define | SMFIF_ADDRCPT_PAR
#define | SMFIF_SETSYMLIST
#define | SMFIS_CONTINUE
#define | SMFIS_REJECT
#define | SMFIS_DISCARD
#define | SMFIS_ACCEPT
#define | SMFIS_TEMPFAIL
#define | SMFIS_NOREPLY
#define | SMFIS_SKIP
#define | SMFIS_ALL_OPTS
#define | SMFIM_CONNECT
#define | SMFIM_HELO
#define | SMFIM_ENVFROM
#define | SMFIM_ENVRCPT
#define | SMFIM_DATA
#define | SMFIM_EOM
#define | SMFIM_EOH
#define | SMFIP_NOCONNECT
#define | SMFIP_NOHELO
#define | SMFIP_NOMAIL
#define | SMFIP_NORCPT
#define | SMFIP_NOBODY
#define | SMFIP_NOHDRS
#define | SMFIP_NOEOH
#define | SMFIP_NR_HDR
#define | SMFIP_NOHREPL
#define | SMFIP_NOUNKNOWN
#define | SMFIP_NODATA
#define | SMFIP_SKIP
#define | SMFIP_RCPT_REJ
#define | SMFIP_NR_CONN
#define | SMFIP_NR_HELO
#define | SMFIP_NR_MAIL
#define | SMFIP_NR_RCPT
#define | SMFIP_NR_DATA
#define | SMFIP_NR_UNKN
#define | SMFIP_NR_EOH
#define | SMFIP_NR_BODY
#define | SMFIP_HDR_LEADSPC

## 説明

libmilter/mfapi.hはSendmailのlibmilter互換APIを提供します。Sendmailのlibmilterの代わりにこのライブラリを使用することができます。milter.orgのAPIドキュメントもみてください。

## Functions

### SM_LM_VRS_MAJOR()

    #define SM_LM_VRS_MAJOR(version) (((version) & 0x7f000000) >> 24)

Extracts major version number from `version` .

#### Parameters

version | バージョン番号。 |

#### Returns

メジャーバージョン番号。

### SM_LM_VRS_MINOR()

    #define SM_LM_VRS_MINOR(version) (((version) & 0x007fff00) >> 8)

Extracts minor version number from `version` .

#### Parameters

version | バージョン番号。 |

#### Returns

マイナーバージョン番号。

### SM_LM_VRS_PLVL()

    #define SM_LM_VRS_PLVL(version)                ((version) & 0x0000007f)

Extracts patch level from `version` .

#### Parameters

version | バージョン番号。 |

#### Returns

パッチレベル。

### smfi_opensocket ()

    int
    smfi_opensocket (bool remove_socket);

MTAからの接続されるソケットを作成します。

通常は、`smfi_opensocket()`を明示的に呼ぶ必要はありません。ソケットは`smfi_main()`の中で暗黙的に作られます。

失敗条件は以下の通りです。

- smfi_register() hasn't called successfully.

- smfi_setconn() hasn't called successfully.

- smfi_opensocket() fails to remove existing UNIX domain socket if connection spec is for UNIX domain socket and `remove_socket` is true.

- smfi_opensocket() fails to create the new socket.

milter.orgの smfi_opensocketも見てください。

#### Parameters

remove_socket | 新しいソケットを作る前に、既存のUNIXドメインソケットを削除しようとするかどうか。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_register ()

    int
    smfi_register (struct smfiDesc description);

milterの実装をコールバックとして登録します。

失敗条件は以下の通りです。

- 互換性のないxxfi_version。

- 不正なxxfi_flagsの値。

milter.orgの smfi_registerも見てください。

#### Parameters

description | milterの説明。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_main ()

    int
    smfi_main (void);

イベントループに入ります。milterは`smfi_main()`を呼ぶ前に、`smfi_register()`、`smfi_setconn()`などで初期化していなければいけません。

失敗条件は以下の通りです。

- ソケットの作成に失敗したとき。

milter.orgの smfi_mainも見てください。

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_setbacklog ()

    int
    smfi_setbacklog (int backlog);

listen(2)で使われるmilterの接続キューの最大長を設定します。

失敗条件は以下の通りです。

- `backlog` <= 0.

milter.orgの smfi_setbacklogも見てください。

#### Parameters

backlog | 処理待ちの接続キューの最大長。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_setdbg ()

    int
    smfi_setdbg (int level);

ログレベルを設定します。`level`が0ならすべてのログメッセージが抑制されます。大きい値を指定すればするほど多くのログメッセージが出力されます。

milter.orgの smfi_setdbgも見てください。

#### Parameters

level | ログレベル。 |

#### Returns

常に`MI_SUCCESS`。

### smfi_settimeout ()

    int
    smfi_settimeout (int timeout);

入出力のタイムアウト時間を秒で設定します。既定値は7210秒です。`timeout` == 0は待たないことを意味します。"永遠に待つ"ではありません。

milter.orgの smfi_settimeoutも見てください。

#### Parameters

timeout | タイムアウト値を秒で指定します。 |

#### Returns

常に`MI_SUCCESS`。

### smfi_setconn ()

    int
    smfi_setconn (char *connection_spec);

接続指定を設定します。

`connection_spec`の書式は以下のいずれかです。

- "unix:/PATH/TO/SOCKET": UNIXドメインソケット。

- "inet:PORT"、"inet:PORT@HOST_NAME"、"inet:PORT@IP_ADDRESS": IPv4。

- "inet6:PORT"、"inet6:PORT@HOST_NAME"、"inet6:PORT@IP_ADDRESS": IPv6。

失敗条件は以下の通りです。

- 不正な形式。

- `connection_spec`が`NULL`。

milter.orgの smfi_setconnも見てください。

#### Parameters

connection_spec | MTAと通信するための接続指定。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_stop ()

    int
    smfi_stop (void);

milterを中止します。これ以上の接続を受け付けませんが、処理中の接続は最後まで続けます。

milter.orgの smfi_stopも見てください。

#### Returns

常に`MI_SUCCESS`。

### smfi_version ()

    int
    smfi_version (unsigned int *major,
                  unsigned int *minor,
                  unsigned int *patch_level);

libmilterのバージョンを取得します。バージョンはビルド時のlibmilterのバージョンではなくて、実行時に使用しているバージョンです。

milter.orgの smfi_versionも見てください。

#### Parameters

major | メジャーバージョンを返すアドレス。 |
minor | マイナーバージョンを返すアドレス。 |
patch_level | パッチレベルを返すアドレス。 |

#### Returns

常に`MI_SUCCESS`。

### smfi_getsymval ()

    char *
    smfi_getsymval (SMFICTX *context,
                    char *name);

現在のmilterセッションコンテキスト中での`name`というマクロ名の値を返します。`smfi_getsymval()`はxxfi_XXXコールバックの中で使えます。（例えば、`xxfi_connect()`、`xxfi_helo()`など）

`name`が"i"のように1文字でない場合は、"{if_name}"のようにかっこ（"{"と"}"）で囲みます。

milter.orgの smfi_getsymvalも見てください。Sendmailの既定のマクロもそのページに載っています。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
name | マクロ名。 |

#### Returns

もしあれば`name`というマクロ名の値、なければ`NULL`。

### smfi_setreply ()

    int
    smfi_setreply (SMFICTX *context,
                   char *return_code,
                   char *extended_code,
                   char *message);

エラー応答コードを設定します。4xx `return_code`は`SMFIS_TEMPFAIL`のときに使います。5xx `return_code`は`SMFIS_REJECT`のときに使います。

失敗条件は以下の通りです。

- `return_code`が4xxでも5xxでもない。

- `extended_code`が4.x.xでも5.x.xでもない。

milter.orgの smfi_setreplyも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
return_code | 3桁のSMTPエラー応答コード。（RFC 2821）4xxと5xxだけが使えます。 |
extended_code | 拡張応答コード（RFC 1893/2034）または`NULL`。4.x.xと5.x.xだけが使えます。 |
message | SMTP応答のテキスト部分または`NULL`。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_setmlreply ()

    int
    smfi_setmlreply (SMFICTX *context,
                     const char *return_code,
                     const char *extended_code,
                     ...);

エラー応答コードを設定します。4xx `return_code`は`SMFIS_TEMPFAIL`のときに使います。5xx `return_code`は`SMFIS_REJECT`のときに使います。

失敗条件は以下の通りです。

- `return_code`が4xxでも5xxでもない。

- `extended_code`が4.x.xでも5.x.xでもない。

milter.orgの smfi_setmlreplyも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
return_code | 3桁のSMTPエラー応答コード。（RFC 2821）4xxと5xxだけが使えます。 |
extended_code | 拡張応答コード（RFC 1893/2034）または`NULL`。4.x.xと5.x.xだけが使えます。 |
... | SMTP応答のテキスト部分の一行。最後に`NULL`を指定すること。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_addheader ()

    int
    smfi_addheader (SMFICTX *context,
                    char *name,
                    char *value);

現在のメッセージのヘッダリストにヘッダを追加します。`smfi_addheader()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `name`が`NULL`。

- `value`が`NULL`。

- `xxfi_eom()`以外のところで呼ばれた。

- `SMFIF_ADDHDRS`フラグが`smfi_register()`の中でも、`xxfi_negotiate()`でも指定されていない。

- ネットワークエラー発生。

milter.orgの smfi_addheaderも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
name | ヘッダ名。 |
value | ヘッダ値。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_chgheader ()

    int
    smfi_chgheader (SMFICTX *context,
                    char *name,
                    int index,
                    char *value);

Changes a header that is located at `index` in headers that all of them are named `name` . If `value` is `NULL`, the header is deleted. `smfi_chgheader()` can be called in `xxfi_eom()`.

失敗条件は以下の通りです。

- `name`が`NULL`。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_CHGHDRS`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_chgheaderも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
name | ヘッダ名。 |
index | the index of headers that all of them are named `name` . (1-based) |
value | ヘッダ値。ターゲットのヘッダを削除する場合は`NULL`を指定してください。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_insheader ()

    int
    smfi_insheader (SMFICTX *context,
                    int index,
                    char *name,
                    char *value);

ヘッダの`index`番目にヘッダを挿入します。`smfi_insheader()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `name`が`NULL`。

- `value`が`NULL`。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_ADDHDRS`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_insheaderも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
index | 挿入されるヘッダの位置。0は先頭に追加するという意味になります。 |
name | ヘッダ名。 |
value | ヘッダ値。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_chgfrom ()

    int
    smfi_chgfrom (SMFICTX *context,
                  char *mail,
                  char *arguments);

送信者のアドレスを変更します。`smfi_chgfrom()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `mail`が`NULL`。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_CHGFROM`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_chgfromも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
mail | 新しい送信者のアドレス。 |
arguments | ESMTPの追加の引数。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_addrcpt ()

    int
    smfi_addrcpt (SMFICTX *context,
                  char *recipient);

宛先アドレスを追加します。`smfi_addrcpt()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `recipient`が`NULL`。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_ADDRCPT`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_addrcptも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
recipient | 新しい宛先アドレス。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_addrcpt_par ()

    int
    smfi_addrcpt_par (SMFICTX *context,
                      char *recipient,
                      char *arguments);

追加のESMTP引数付きで宛先アドレスを追加します。`smfi_addrcpt_par()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `recipient`が`NULL`。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_ADDRCPT_PAR`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_addrcpt_parも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
recipient | 宛先アドレス。 |
arguments | ESMTPの追加の引数。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_delrcpt ()

    int
    smfi_delrcpt (SMFICTX *context,
                  char *recipient);

宛先のアドレスを削除します。`smfi_delrcpt()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `recipient`が`NULL`。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_DELRCPT`フラグが設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_delrcptも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
recipient | 宛先アドレス。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_progress ()

    int
    smfi_progress (SMFICTX *context);

現在の接続を維持します。`smfi_progress()`は`xxfi_eom()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_progressも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_replacebody ()

    int
    smfi_replacebody (SMFICTX *context,
                      unsigned char *new_body,
                      int new_body_size);

Replaces the current body data with `new_body` . `smfi_replacebody()` can be called in `xxfi_eom()`.

失敗条件は以下の通りです。

- `new_body` == `NULL` and `new_body_size` > 0. FIXME: not-implemented yet.

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_CHGBODY`が設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_replacebodyも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
new_body | 新しい本文のデータ。 |
new_body_size | the size of `new_body` . |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_quarantine ()

    int
    smfi_quarantine (SMFICTX *context,
                     char *reason);

Quarantines the current message with `reason` . `smfi_quarantine()` can be called in `xxfi_eom()`.

失敗条件は以下の通りです。

- `reason`が`NULL`または空。FIXME: 未実装。

- `xxfi_eom()`以外で呼ばれた。FIXME: 未実装。

- `smfi_register()`あるいは`xxfi_negotiate()`で`SMFIF_QUARANTINE`が設定されていない。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_quarantineも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
reason | 隔離理由。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_setpriv ()

    int
    smfi_setpriv (SMFICTX *context,
                  void *data);

プライベートなデータを設定します。

失敗条件は以下の通りです。

- `context`が不正。FIXME: 未実装。

milter.orgの smfi_setprivも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
data | プライベートなデータ。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

### smfi_getpriv ()

    void *
    smfi_getpriv (SMFICTX *context);

プライベートなデータを取得します。

失敗条件は以下の通りです。

- `context`が不正。FIXME: 未実装。

milter.orgの smfi_getprivも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |

#### Returns

`smfi_setpriv()`で設定したプライベートなデータか`NULL`。

### smfi_setsymlist ()

    int
    smfi_setsymlist (SMFICTX *context,
                     int state,
                     char *macros);

要求するマクロのリストを設定します。`smfi_setsymlist()`は`xxfi_negotiate()`の中で呼ぶことができます。

失敗条件は以下の通りです。

- `state`が不正。FIXME: 未実装。

- `macros`が`NULL`または空。FIXME: 未実装。

- `state`の要求マクロリストがすでに設定されている。FIXME: 未実装。

- `xxfi_negotiate()`以外から呼ばれた。FIXME: 未実装。

- ネットワークエラー発生。

milter.orgの smfi_setsymlistも見てください。

#### Parameters

context | 現在のmilterセッションのコンテキスト。 |
state | `SMFIM_CONNECT`のようなSMFIM_XXXとして定義された状態。 |
macros | "{rcpt_mailer} {rcpt_host}"のような空白で区切られたマクロ名のリスト。 |

#### Returns

成功した場合は`MI_SUCCESS`、そうでない場合は`MI_FAILURE`。

## Types and Values

### SMFI_VERSION

    #  define SMFI_VERSION 0x01000001

libmilterのバージョン番号。

### MI_SUCCESS

    #define MI_SUCCESS 0

操作が成功したことを示します。

### MI_FAILURE

    #define MI_FAILURE (-1)

操作が失敗したことを示します。

### SMFICTX

    typedef struct smfi_str  SMFICTX;

milterセッションの情報を持っています。`SMFICTX`は各milterセッション毎に作成されます。`SMFICTX`はlibmilter APIの中でもっとも重要なオブジェクトです。

### SMFICTX_PTR

    typedef struct smfi_str *SMFICTX_PTR;

`SMFICTX`のポインタ型。

### smfiDesc_str

    typedef struct smfiDesc smfiDesc_str;

milterの情報を持っています。`smfi_register()`で`smfiDesc_str`使います。

### smfiDesc_ptr

    typedef struct smfiDesc *smfiDesc_ptr;

`smfiDesc_str`のポインタ型です。

### sfsistat

    typedef int sfsistat;

コールバックが返す応答ステータスを示します。

利用可能な応答ステータスは以下のどれかです。

- `SMFIS_CONTINUE`

- `SMFIS_REJECT`

- `SMFIS_DISCARD`

- `SMFIS_ACCEPT`

- `SMFIS_TEMPFAIL`

- `SMFIS_NOREPLY`

- `SMFIS_SKIP`

- `SMFIS_ALL_OPTS`

### bool

    #      define bool int

真偽値型。

### true

    #      define true 1

真の値。

### false

    #      define false 0

偽の値。

### struct smfiDesc

    struct smfiDesc {
        char          *xxfi_name;
        int            xxfi_version;
        unsigned long  xxfi_flags;

        sfsistat (*xxfi_connect)   (SMFICTX     *context,
                                       char        *host_name,
                                       _SOCK_ADDR  *address);
        sfsistat (*xxfi_helo)      (SMFICTX    *context,
                                       char       *fqdn);
        sfsistat (*xxfi_envfrom)   (SMFICTX    *context,
                                       char      **arguments);
        sfsistat (*xxfi_envrcpt)   (SMFICTX    *context,
                                       char      **arguments);
        sfsistat (*xxfi_header)    (SMFICTX    *context,
                                       char       *name,
                                       char       *value);
        sfsistat (*xxfi_eoh)       (SMFICTX    *context);
        sfsistat (*xxfi_body)      (SMFICTX    *context,
                                       unsigned char *data,
                                       size_t     data_size);
        sfsistat (*xxfi_eom)       (SMFICTX    *context);
        sfsistat (*xxfi_abort)     (SMFICTX    *context);
        sfsistat (*xxfi_close)     (SMFICTX    *context);
        sfsistat (*xxfi_unknown)   (SMFICTX    *context,
                                       const char *command);
        sfsistat (*xxfi_data)      (SMFICTX    *context);
        sfsistat (*xxfi_negotiate) (SMFICTX    *context,
                                       unsigned long  actions,
                                       unsigned long  steps,
                                       unsigned long  unused0,
                                       unsigned long  unused1,
                                       unsigned long *actions_output,
                                       unsigned long *steps_output,
                                       unsigned long *unused0_output,
                                       unsigned long *unused1_output);
    };

`smfiDesc` is used by `smfi_register()` to register a milter.

If `xxfi_name` is `NULL`, "Unknown" is used as default milter name.

`xxfi_version` must be specified `SMFI_VERSION`.

Here are the available `xxfi_flags` values:

- `SMFIF_ADDHDRS`: The milter may call `smfi_addheader()`.

- `SMFIF_CHGHDRS`: The milter may call `smfi_chgheader()`.

- `SMFIF_CHGBODY`: The milter may call `smfi_chgbody()`.

- `SMFIF_ADDRCPT`: The milter may call `smfi_addrcpt()`.

- `SMFIF_ADDRCPT_PAR`: The milter may call `smfi_addrcpt_par()`.

- `SMFIF_DELRCPT`: The milter may call `smfi_delrcpt()`.

- `SMFIF_QUARANTINE`: The milter may call `smfi_quarantine()`.

- `SMFIF_CHGFROM`: The milter may call `smfi_chgfrom()`.

- `SMFIF_SETSMLIST`: The milter may call `smfi_setsymlist()`.

They can be used together by bitwise OR.

All callbacks (e.g. `xxfi_helo()`, `xxfi_envfrom()` and so on) may be `NULL`. If a callback is `NULL`, the event is just ignored the milter.

#### Members

char *`xxfi_name`; | The name of the milter. |
int `xxfi_version`; | The version code of the milter. |
unsigned long `xxfi_flags`; | The flags of the milter. Available values are SMFIF_*. |
`xxfi_connect` () | See `xxfi_connect()`. |
`xxfi_helo` () | See `xxfi_helo()`. |
`xxfi_envfrom` () | See `xxfi_envfrom()`. |
`xxfi_envrcpt` () | See `xxfi_envrcpt()`. |
`xxfi_header` () | See `xxfi_header()`. |
`xxfi_eoh` () | See `xxfi_eoh()`. |
`xxfi_body` () | See `xxfi_body()`. |
`xxfi_eom` () | See `xxfi_eom()`. |
`xxfi_abort` () | See `xxfi_abort()`. |
`xxfi_close` () | See `xxfi_close()`. |
`xxfi_unknown` () | See `xxfi_unknown()`. |
`xxfi_data` () | See `xxfi_data()`. |
`xxfi_negotiate` () | See `xxfi_negotiate()`. |

### SMFIF_ADDHDRS

    #define SMFIF_ADDHDRS     0x00000001L

milterは`smfi_addheader()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_CHGBODY

    #define SMFIF_CHGBODY     0x00000002L

milterは`smfi_chgbody()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_MODBODY

    #define SMFIF_MODBODY     SMFIF_CHGBODY

`SMFIF_CHGBODY`と同じ。

### SMFIF_ADDRCPT

    #define SMFIF_ADDRCPT     0x00000004L

milterは`smfi_addrcpt()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_DELRCPT

    #define SMFIF_DELRCPT     0x00000008L

milterは`smfi_delrcpt()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_CHGHDRS

    #define SMFIF_CHGHDRS     0x00000010L

milterは`smfi_chgheader()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_QUARANTINE

    #define SMFIF_QUARANTINE  0x00000020L

milterは`smfi_quarantine()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_CHGFROM

    #define SMFIF_CHGFROM     0x00000040L

milterは`smfi_chgfrom()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_ADDRCPT_PAR

    #define SMFIF_ADDRCPT_PAR 0x00000080L

milterは`smfi_addrcpt_par()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIF_SETSYMLIST

    #define SMFIF_SETSYMLIST  0x00000100L

milterは`smfi_setsymlist()`を呼ぶかもしれません。

`smfiDesc`と`xxfi_negotiate()`とmilter.orgのsmfi_registerも見てください。

### SMFIS_CONTINUE

    #define SMFIS_CONTINUE    0

現在の処理を継続します。

各コールバック（`xxfi_connect()`、`xxfi_helo()`など）とmilter.orgのコールバックの返値の説明も見てください。

### SMFIS_REJECT

    #define SMFIS_REJECT      1

現在処理中のターゲットを拒否します。

各コールバック（`xxfi_connect()`、`xxfi_helo()`など）とmilter.orgのコールバックの返値の説明も見てください。

### SMFIS_DISCARD

    #define SMFIS_DISCARD     2

現在処理中のターゲットを受け入れて、だまって破棄します。

各コールバック（`xxfi_envfrom()`、`xxfi_envrcpt()`など）とmiler.orgのコールバックの返値の説明も見てください。

### SMFIS_ACCEPT

    #define SMFIS_ACCEPT      3

現在処理中のターゲットを受け入れます。

各コールバック（`xxfi_connect()`、`xxfi_helo()`など）とmilter.orgのコールバックの返値の説明も見てください。

### SMFIS_TEMPFAIL

    #define SMFIS_TEMPFAIL    4

現在のターゲットに対して、一時的な障害ステータスを返します。

各コールバック（`xxfi_connect()`、`xxfi_helo()`など）とmilter.orgのコールバックの返値の説明も見てください。

### SMFIS_NOREPLY

    #define SMFIS_NOREPLY     7

MTAに返答しません。

各コールバック（`xxfi_connect()`、`xxfi_helo()`など）とmilter.orgのコールバックの返値の説明も見てください。

### SMFIS_SKIP

    #define SMFIS_SKIP        8

残りの本文を省略します。`xxfi_body()`の中でだけ使えます。

milter.orgのコールバックの返値の説明も見てください。

### SMFIS_ALL_OPTS

    #define SMFIS_ALL_OPTS    10

MTAから受け取ったすべてのネゴシエーションオプションを使います。これは`xxfi_negotiate()`の中でだけ使えます。

### SMFIM_CONNECT

    #define SMFIM_CONNECT          0

`xxfi_connect()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_HELO

    #define SMFIM_HELO          1

`xxfi_helo()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_ENVFROM

    #define SMFIM_ENVFROM          2

`xxfi_envfrom()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_ENVRCPT

    #define SMFIM_ENVRCPT          3

`xxfi_envrcpt()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_DATA

    #define SMFIM_DATA          4

`xxfi_data()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_EOM

    #define SMFIM_EOM          5

`xxfi_eom()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIM_EOH

    #define SMFIM_EOH          6

`xxfi_eoh()`のプロトコル段階であることを示します。

`smfi_setsymlist()`も見てください。

### SMFIP_NOCONNECT

    #define SMFIP_NOCONNECT       0x00000001L

MTAは`xxfi_connect()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NOHELO

    #define SMFIP_NOHELO          0x00000002L

MTAが`xxfi_helo()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NOMAIL

    #define SMFIP_NOMAIL          0x00000004L

MTAが`xxfi_mail()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NORCPT

    #define SMFIP_NORCPT          0x00000008L

MTAが`xxfi_rcpt()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NOBODY

    #define SMFIP_NOBODY          0x00000010L

### SMFIP_NOHDRS

    #define SMFIP_NOHDRS          0x00000020L

MTAが`xxfi_header()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NOEOH

    #define SMFIP_NOEOH           0x00000040L

MTAが`xxfi_eoh()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_HDR

    #define SMFIP_NR_HDR          0x00000080L

milterが`xxfi_header()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NOHREPL

    #define SMFIP_NOHREPL         SMFIP_NR_HDR

`SMFIP_NR_HDR`と同じ。

### SMFIP_NOUNKNOWN

    #define SMFIP_NOUNKNOWN       0x00000100L

MTAが`xxfi_unknown()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NODATA

    #define SMFIP_NODATA          0x00000200L

MTAが`xxfi_data()`の情報を送信しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_SKIP

    #define SMFIP_SKIP            0x00000400L

MTAが`xxfi_body()`での`SMFIS_SKIP`をサポートしていることを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_RCPT_REJ

    #define SMFIP_RCPT_REJ        0x00000800L

MTAは拒否した宛先も送信し、`xxfi_envrcpt()`が呼び出されることを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_CONN

    #define SMFIP_NR_CONN         0x00001000L

milterが`xxfi_connect()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_HELO

    #define SMFIP_NR_HELO         0x00002000L

milterが`xxfi_helo()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_MAIL

    #define SMFIP_NR_MAIL         0x00004000L

milterが`xxfi_envfrom()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_RCPT

    #define SMFIP_NR_RCPT         0x00008000L

milterが`xxfi_envrcpt()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_DATA

    #define SMFIP_NR_DATA         0x00010000L

milterが`xxfi_data()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_UNKN

    #define SMFIP_NR_UNKN         0x00020000L

milterが`xxfi_unknown()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_EOH

    #define SMFIP_NR_EOH          0x00040000L

milterが`xxfi_eoh()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_NR_BODY

    #define SMFIP_NR_BODY         0x00080000L

milterが`xxfi_body()`に返答しないことを示します。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。

### SMFIP_HDR_LEADSPC

    #define SMFIP_HDR_LEADSPC     0x00100000L

`xxfi_header()`コールバックが':'の後のスペース付きでヘッダの値を受けとることを示します。例は`xxfi_header()`を見てください。

このフラグは`xxfi_negotiate()`の`steps_output`で取得・設定できます。