sendmailのインストールと設定


目次

はじめに
電子メールの形式
エンベロープ
MUAからsendmailへの流れ
SMTPの体験実験
sendmail.cfとDNS
nslookupコマンド
インストール作業の流れ
前準備
 ・ネームサーバに関する注意点
 ・Berkeley DBのインストール
 ・その他のツール群
コンパイルとインストール
 ・Buildスクリプトの実行
 ・ファイルの許可モードの確認
sendmail.cfの設定
 ・CFのパッケージの入手
 ・サイトのホスト構成を考える
 ・末端ホストでのsendmail.cfの設定
 ・スプールホストでのsendmail.cfの設定
sendmail.cfの概要
 ・書換えルールと配信エージェント
 ・ルールセット
 ・マクロ変数
 ・その他の構成要素
アドレステスト・モード
 ・マクロの内容の表示
 ・配信エージェントの選択状況の確認
 ・アドレスの書換えの確認
 ・メールのリレー制限に関する確認
エイリアス・ファイルの利用
 ・エイリアス・ファイルの形式
 ・エイリアス・ファイルの更新
 ・ループの回避
 ・必須エイリアス
 ・プログラム起動の場合のユーザーID
 ・エンベロープ送信人アドレスの自動設定
メール配送系の構築
 ・ハブホストの利用
 ・ハブホスト構築の利点(セキュリティの確保)
 ・端末型ダイヤルアップ環境
  fetchmailの利用

一つ前へ


はじめに

 電子メール(E-mail)は、コンピュータ・ネットワーク上で人間どうしが情報交換をする手段として頻繁に用いられており、比較的長い歴史があります。電子メールの配送処理をおこなうためのプログラムとしては、長年にわたって sendmail がひろく用いられてきました。しかし、sendmail の設定のややこしさにつまづく方も多いのではないでしょうか。
 メールシステムの構築は、Webサーバの立ち上げなどに比べて難しい場合が多いようです。その理由として、Webサーバはホスト単位で運用できるのに対し、メールシステムの構築はサイト内のホストをすべて有機的に結びつける作業で、各ホストを単体で考えるだけでは適切な解が導けないということがあります。
 sendmail は、電子メールシステムの歴史とともに発展してきており、いろいろな要求に対応できる柔軟なプログラムになってきています。その代わり、設定に際してはそれなりの知識を必要とします。特に、設定ファイルの中心である sendmail.cf は、さまざまなメールアドレス形式を扱えるように、一種のプログラミング言語ともいえる構造になっています。一見すると不可解な文字列の並ぶファイルですが、安心してください。いまでは sendmail.cf を自動生成するためのツールがいくつかあり、それらを使えば sendmail.cf 自体の文法を知らなくても設定ができます。
 なかでも、中村素典氏によるCFがたいへん便利です。典型的な運用形態で使うのであれば、最低限の設定だけで sendmail.cf を自動的に作成できます。

電子メールの形式

 電子メールのフォーマットはRFC822という文書によって定められており、図1のような形式になっています(昨今では、MIME(Multipurpose Mail Extensions,RFC2045〜2049)を用いたメールもよくつかわれますが、メールの配送処理にはほとんど関係がないため、ここでは触れません。
 
図1 電子メールの例

Date: Thu, 8 Apr 1999 16:18:24 +0900 (JST)
From: osaru@west.tbn.ntt.co.jp
Subject:小型記憶装置 Clik! 、アイオメガが 5 月発売
To: gorila@east.tbn.ntt.co.jp
Cc: banana@west.tbn.ntt.co.jp
Message-Id: <199904080718.QAA05172@west.tbn.ntt.co.jp>

■◎小型記憶装置「Clik!」を5月発売

1通のメールメッセージは "ヘッダ(hrader)" 部と "ボディ(body)" 部とで構成されます。ヘッダ部はメッセージの先頭から最初の空行までの部分で、残りがボディ部になります。ユーザがメールを読み書きする際には、かならずしもヘッダ部とボディ部が連続して表示されるとはかぎりませんが、内部的にはヘッダ部とボディ部はこのように一連のものです。
 ヘッダ部には "To:" や "Cc:"(Carbon Copyの略) などのフィールドを書くことができます。あるユーザーがほかの誰かにメールを出す際には、To: または Cc: のフィールド中で相手のメールアドレスを指定します。1つの To: 行や Cc: 行に複数のメールアドレスをカンマで区切って列挙したり、To: 行(や Cc:行) 自体を複数回記述することもできます。To: 行には "そのメールのおもな宛先" を書き、同内容のメールを送りたい相手がいれば Cc: 行にそれらの人のアドレスを書くという使い分けをするのが一般的です。しかし配送の際には、To: 行に書かれた宛先もCc: 行に書かれた宛先も同じように扱われます。
 また、ヘッダ部には "From:" というフィールドもあり、ここに差出人のアドレスを書きます。通常は、このフィールドはユーザがメールを読み書きする際に用いるツール(MUA:Mail User Agent) が自動的に生成して付加します。

エンベロープ

 前節でみたように、ユーザは宛先のメールアドレスをヘッダ中の To: や Cc: に指定します。単純に考えると、配送処理をおこなうプログラムはこれらのヘッダを参照して配送先を決定するように思えます。しかし、実際は違います。実際の配送先の決定に際しては To: や Cc: を直接利用するのではなく、メール配送時にエンベロープ(Envelope) と呼ばれる情報を別にもち、そちらを参照するようになっています。メール本体のヘッダフィールドは書き換えずに、エンベロープを書き換えながら配送することになります。
理由は、もしAさんがBさんCさんにメールを送ろうとして、「To:B,C」と宛先を指定して送信したとします。するとBさんとCさんのメールサーバにメールが配送されるのですが、To:フィールドを参照すると、同じメールを、BさんのメールサーバはCさんのメールサーバに送り、CさんのメールサーバはBさんのメールサーバに送りと、互いに配送を繰り返してしまい、何通も同じものが両方のアドレスに届くことになるからです。
 ユーザがメールの読み書きに用いるツールをMUAというのに対し、メールの配送を担当する sendmail のようなプログラムをMTA(Mail Tranport Agent) といいます。MTAは、基本的にはヘッダに書いてある情報は参照せず、エンベロープを利用して配送をおこないます。ユーザがMUAからメールを発信する際に、MUAがヘッダから情報を抽出してエンベロープを設定し、MTAへ渡すようになっています(MUAの実装によっては、ヘッダからエンベロープを作るというよりは、「宛先」などの欄に記入した内容をもとに、ヘッダとエンベロープの双方を同時に生成するようになっている場合も考えられます)。
 ヘッダとエンベロープの区別を利用した仕組みとしては、ほかにも Bcc:(Blind Carbon Copy)フィールドやメーリングリストなどがあります。Bcc: は、To: や Cc: と同じくメールの宛先を記述するためのフィールドですが、MUAはエンベロープ情報を抽出したのち Bcc: の行を消去してからMTAに渡します。これにより、「このメールはXさんにも同時に送っているのだが、その事実は秘匿したい」といった発信者の要求にも対応できます。また、メーリングリストを作って一定のメンバー間でメールをやりとりする場合、通常は To: フィールドにメーリングリストのアドレスが入ったまま各メンバーに配送されます。この場合もエンベロープが活躍します。
 エンベロープには、上記のような受信人(Envelope Recipient) の情報以外に、送信人(Envelope Sender) の情報もあります。メールの配送の途中で事故などがあった場合に、MTAはその旨を "エラーメール" として報告しますが、その際にエンベロープの送信人の情報が利用されます。
 エンベロープの送信人は、基本的にはMUAが From: フィールドから情報を抽出して設定するので、通常は発信者本人にエラーが報告されます。これに対し、メーリングリストにおいては、メーリングリストのサーバに届いてから各メンバーに配送するあいだのエラーは、発信者ではなくメーリングリストの管理者に送るのが適当です。よって、メーリングリストのサーバでは、エンベロープの送信人を書き直すようにするのが一般的です。

MUAからsendmailへの流れ

 前節で、メール本体とエンベロープが区別されていることは分かりました。それでは、エンベロープの情報は実際にはどのようにして sendmail に通知されるのでしょうか。
 sendmail には、大きく分けて次の2つの起動形態があります。
 
◆ユーザコマンドとして起動され、1通ぶんのメールの処理をおこなう。
◆OS起動時に -bd オプションを付けて起動される。以後はデーモンとして動き続け、ほかのホストからのメールを受け付ける。
 
 古くからUNIX上で用いられてきたMUAとして、mail コマンド(mailコマンドには2種類あります、MUAとして使うためのmailコマンド(BSDベースのUNIXであれば /usr/ucb/mail などに置かれ、UCB-mail などと呼ばれる)と、ローカルのスプールに書き込む際に用いるための mail コマンド(/bin/mail などに置かれ、通称 bin-mail) です。後者は通常ユーザが直接用いることはなく、sendmail などが内部的に利用するだけです。最近のOSでは、mail.local という名前で /usr/libexec などに存在するものもあります)があります。これはメール発信時に内部で sendmail を起動するので、前者のタイプの動作をおこなうことになります。この場合、エンベロープの受信人は、sendmail 実行時のコマンドライン引数として与えられ、エンベロープの送信人はその sendmail を実行時のコマンドライン引数として与えられ、エンベロープの送信人はその sendmail を実行したユーザIDから抽出されます。
 これに対し、ネットワークを経由してMTA間でメールを配送する際には、SMTP(Simple Mauil Transfer Protocol、RFC821) が利用されます。デーモンモードで起動された sendmail は、SMTPによる接続を待ち受ける状態になり、外部からのメールを受け付けて処理します。SMTPは、MTA間だけでなく、MUAからMTAにメールを渡す際にも用いることができます。MH(Message Handler) などのMUAは、デフォルトの設定では自分自身が動作しているホスト上のMTAに対してSMTPを使ってメールを発信します(MHでは、swndmail コマンドを起動して発信するか、直接SMTPで発信するかを設定で選ぶことができます。詳しくはMHのマニュアルのmh-tailorの項(man mh-tailor)を参照してください)。Windows95 などで動くMUAならば、SMTPでほかのホスト上のMTAの向けて発信します。次節で、SMTPがエンベロープ情報をやりとりする仕組みを開設します。
 

SMTPの体験実験

 sendmailが動いているホストに対して実際にメールを出してみる実験を通じて、SMTPの概要をつかんでみましょう。例として、mail.kaisya.co.jp というホスト上の yokozuna@kaisya.co.jp さんにメールを送ることにしましょう(ドメイン名やIPアドレスはすべて架空のものです)。以下の操作は user.kaisya.co.jp というホストからおこなっているとし、発信者は koshino@kaisya.co.jp さんであるとします。
 まず、次のようにタイプして下さい。

% telnet mail.kaisya.co.jp smtp

 すると、つぎのようなメッセージが出るはずです。

220 mail.kaisya.co.jp ESMTP Sendmail.....(以下略)

 SMTPは、最初にHELOというコマンドでこちらのホスト名を申告するというやりとりから始まります。

HELO user.kaisya.co.jp
250 mail.kaisya.co.jp Hello user.kaisya.co.jp [xx.xx.xx.xx] pleased to meet you

 ただし、この際に申告したホスト名はたいした意味をもたず、実際にはSMTP接続元のホストのIPアドレスから本当のホスト名を自動的に調べます。
 次に、エンベロープの送信人と受信人の情報を、それぞれ "MAIL From:" コマンドと "RCPT To:" コマンドで通知します。

MAIL From:<koshino@kaisya.co.jp>
250 <koshino@kaisya.co.jp>... Sender ok
RCPT To:<yokozuna@kaisya.co.jp>
250 <yokozuna@kaisya.co.jp>... Recipient ok

 RCPT To:コマンドを複数繰り返すことで、複数の受信人を指定することもできます。ここで "Recipient ok" ではなく "User unknown" と出た場合は、メールアドレスのユーザ名(@より左)の部分が誤っていることが考えられます。"Relay operation rejected" と出た場合は、後述する不正リレー対策のチェックにより、メールの配送が拒否されたことを意味しています(この実験のように "部外者ではない" ホストやメールアドレスを用いているにもかかわらずRelay operation rejected のメッセージが出てしまった場合は、sendmail.cf の設定が間違っていることになります)。
 あとは、DATAコマンドでメール本体を入力します。ヘッダも含めたメール本体ですから、To: や From: も入力する必要があります。メール本体の終りは、ピリオドのみの行を入力することによって示します(これとメール本体に含まれるピリオドのみの行を区別するために、SMTPではピリオドで始まる行にはピリオドを先頭にもう1個加えてから送信します。このピリオドは受信側で取り除かれるので、メールの内容には影響しません)。

DATA
354 Enter mail, end with "." on a line by itself
From: koshino@kaisya.co.jp
To: yokozuna@kaisya.co.jp
Subject: test mail
   ←空行を入力
This is a test mail.
. 
250 NAA123456 Massage accepted for delivery

 このあとに続けてまたMAIL From: から始めれば、別のメールを送ることもできます。終了するには、QUITコマンドを送ります。

QUIT
221 mail.kaisya.co.jp closing connection

 
 これでメールが送信されます。上記のうち、エンベロープの受信人を自分のメールアドレスにしておけば、届いたメールを読むことができます。これを使って確認してみてください。エラーメールも自分のところに届くように、エンベロープの送信人も自分にしておくのがいいでしょう。

sendmail.cfとDNS

 ここまで、MUAから発信されたメールはどうのようにして最初のMTAに渡されるのかは分かりました。メールを受け取ったMTAは、次にそのメールをどう扱うべきかを知る必要があります。これには2つの要素が関係します。1つはMTA自身の設定ファイルで、sendmail の場合は sendmail.cf ファイルが該当します。もう1つは DNS(Domain Name System) です。
 DNSが普及する以前は、sendmail によるメールの配送はもっぱら sendmail.cf ファイルによって設定されていました。各ホストの sendmail.cf ファイルに個別にメールの扱いを設定するわけです。しかし、この方法はホストの台数が増えると破掟してしまいます。もちろん、経路を木構造の形に整理するなどして工夫することは可能です。実際に、過去にはそのようにして運営されていたホストが多かったのですが、それでもかなりの頻度で設定変更をする必要があります。
 そのため、現在ではDNSを利用するのが一般的です。DNSは、ドメイン名とIPアドレスの対応関係を知るためのものですが、"メールアドレスの@から右側の部分" と "そのアドレスを扱うべき担当ホスト" の対応関係もこれに登録することができます。この対応をMX(Mail eXchange)といいます。
 sendmail では、DNSを利用するか否かにかかわらず、配送相手の決定にはまず sendmail.cf を利用します。sendmail.cf での判定の結果、DNSを利用すべきだとされた場合には、MXを利用して配送先が決定されます。
 ここで重要な点があります。それは、あるメールを "自分で受け取るべきかどうか" については、sendmail.cf で判定する必要があるということです。たとえば、kaisya.co.jp 宛のメールを mail.kaisya.co.jp というホストで受け取りたい場合、この対応をDNSにMXとして登録するだけでは駄目で、mail.kaisya.co.jp の sendmail.cf で "kaisya.co.jp宛は自分で受け取る" という設定をしなければなりません。
 自分で受け取るべきアドレス以外にも、ファイアウォール内での配送やUUCPを用いた配送の際には、それに関する設定を sendamil.cf でおこなう必要が生じる場合もあります。逆に、そのホスト上で特別扱いする必要のない部分については自動的にMXを利用して配送してくれるので、sendamil.cf ではそういった特別な部分だけ設定すればいいのです。

nslookupコマンド

 MX について知るために、nslookup コマンドを使ってみましょう。特別なオプションを指定せずに nslookup コマンドを実行すると、通常の「ドメイン名からIPアドレスへの対応」を知ることができます。たとえば、mail.kaisya.co.jp というホストのIPアドレスは次のようにして得ることができます(ホスト名の末尾にピリオド(.)を付けて指定してください)。

% nslookup mail.kaisya.co.jp.
Server: ns.kaisya.co.jp
Address: 123.45.67.1

Name:  mail.kaisya.co.jp
Address: 123.45.67.8

 上記では、ns.kaisya.co.jp というネームサーバに問い合せた結果、mail.kaisya.co.jp という文字列に対し、123.45.67.8 というIPアドレスが対応していることが判明しました。つまり、IPアドレス 123.45.67.8 の代わりに。ホスト名 mail.kaisya.co.jp を使ってもよいということです。この仕組みのおかげで、ping や telnet など、多くのコマンドでIPアドレスとホスト名の両方を使うことができます。
 これに対し、メールアドレスの@より右側の部分は、IPアドレスの代わりの文字列(ホスト名)とはかぎりません。たとえば、koshino@kaisya.co.jp というメールアドレスの kaisya.co.jp の部分を指定して nslookup コマンドを実行してみると、以下のようにIPアドレスがなにも出力されないという結果になります(ネームサーバ側の設定しだいでは、*** No address (A) records available for ... などと出力されることもあります)。

% nslookup kaisya.co.jp.
Server: ns.kaisya.co.jp
Address: 123.45.67.1

Name:  kaisya.co.jp

 同じ部分に対し、-type=mx というオプションを指定して nslookup を実行すると以下のようになります。

% nslookup -type=mx kaisya.co.jp.
Server: ns.kaisya.co.jp
Address: 123.45.67.1

kaisya.co.jp preference = 10,mail exchanger = mail.kaisya.co.jp
kaisya.co.jp preference = 20,mail exchanger = ns.kaisya.co.jp
kaisya.co.jp nameserver = ns.kaisya.co.jp
mail.kaisya.co.jp   internet address = 123.45.67.8
ns.kaisya.co.jp    internet address = 123.45.67.1

 この例では、担当ホスト(mail exchanger) として mail.kaisya.co.jp と ns.kaisya.co.jp の2つが指定されています。これは、username@kaisya.co.jp がメールアドレスとして指定された場合、これらのうちどちらかのホストにメールを送信すべきである、という対応がDNSに書かれていることを意味します。各ホストには優先度(preference) という数値が付いています。これは、メールを受信すべきホストが障害などでダウンしていたときに、とりあえず別のホストで受け取っておくことができるようにするための機構です。
 MTAがMXにもとづいて配送先を決定する場合、得られたホストの候補のうち優先度の数値が小さいものを優先し、それが駄目ならば優先度の数値が大きいほうに配送します。たとえば上記の例で、なんらかの障害で mail.kaisya.co.jp がダウンしているときに、誰かが koshino@kaisya.co.jp 宛にメールを出したとすると、そのメールはいったん ns.kaisya.co.jp に送られます。
 そのあと、ns.kaisya.co.jp がこのメールを再度MXにもとづいて配送しようとします。そのとき、MXを調べると配送先に自分自身(ns.kaisya.co.jp)が含まれていることが判明するはずです。この場合は、自分より優先度の高い(数値の小さい)ホストのほうへ配送しようとします。この機構によって、メールは最終的に優先度の最も高いホストにたどり着きます。
 結局、mail.kaisya.co.jp が回復するまでユーザにはメールが届きませんから、優先度の低いホストを準備する意味はないように感じるかもしれません。しかし、受け取るべきホストがすべてダウンしている場合、メールは送信側のキューに蓄えられ、一定期間が経過すると消されます。この期間の設定は送信側しだいなので、短期間で消されてしまう可能性もあります。この危険を避けるために、MXのホストを複数準備するのが一般的です。
 sendmail では、あるドメイン名に対して MX レコードが登録されていなかった場合は、代わりにAレコード(通常のホスト名とIPアドレスの対応)を直接利用するようになっています。そのため、ホスト名そのものをメールアドレス(の@の右側)として使うことも一応はできます。しかし、この機構は過去との互換性のためと考えるべきで、今後はメールアドレスとして利用するドメインに対しては、かならずMXを登録するようにしたほうがいいでしょう(MXの検索の結果得られたホスト名については再度MXを引くことはないので、MXレコードの左辺と右辺がまったく同じでもかまいません)。

インストール作業の流れ
 いよいよ実際の作業に入りましょう。作業の流れは、およそ次のような手順になります。

1.前準備
sendmail が利用するネームサーバの確認
(必要なら)Berkeley DB のインストール
コンパイル時に必要なツールのインストール
2.コンパイルとインストール
(a)Buildスクリプトの実行
(b)su で root になってインストール
3.各種の設定作業
(a)各種ファイルの許可モードの確認
(b)CFを利用した sendmail.cf の作成
(c)(必要なら)DNSへのMXの登録
4.デーモンの起動、メールの送信テストなど

 作業の概要に関しては、JPCERT/CC の Web ページで公開されているインストール・ガイドも参考になります。これはhttp://www.jpcert.or.jp/whatsnew.htmlからたどれる場所にあります。

前準備

ネームサーバに関する注意点
 前述のとうり sendmail は DNS を利用します。ネームサーバのソフトウェアとしては、ISC(Internet Software Consortium)のBINDというソフトウェアに含まれる named プログラムがひろく利用されており、これが標準添付されているOSもあります(OSによっては in.named の名前になっているものもあります)。旧いBINDにはセキュリティ上の欠陥が指摘されています(詳細はhttp://www.jpcert.or.jp/whatsnew.htmlにあります)。これに該当する場合は、BINDのほうもバージョンアップしましょう。現在使われているBINDには BIND4.x系と BIND8.x系のものがあります。
 現在動作している named のバージョン確認には、SCCS(Source Code Control System)の what コマンドが使えます。たとえば、利用しているのが /usr/sbin/named なら、

% what /usr/sbin/named

のようにタイプすれば、named プログラムの各種ソースファイルのバージョンと、BIND自体のバージョンが表示されます。
 sendmail がDNSを利用する際には、ネームサーバとして /etc/resolv.conf ファイルに記述されたホストが利用されます。自分のサイトに新たにネームサーバをインストールした場合には、/etc/resolv.conf ファイルの設定変更を忘れないようにしましょう。/etc/resolv.conf ファイルは、DNSを利用する各アプリケーションが個別に読み込みます。通常は起動後に1回読むだけなので、デーモンの場合は再起動しなければならないことが多く、注意が必要です。

Berkeley DBのインストール
 sendmailは、電子メールアドレスのエイリアス(aliases) などの処理にデータベース・ライブラリを利用します。データベース・ライブラリにはさまざまなタイプのものがありますが、sendmail はそれらのうち ndbm や Berkeley DB に対応しています。いずれかがインストールされていれば、sendmail をコンパイルすることができます。ndbm は多くのOSに添付されているので、通常はこちらを利用すればよいでしょう。ただし、メールを頻繁にやりとりするようなホスト上では、エイリアスなどでデータベース・ライブラリを酷使しがちです。このようなホストで効率的にメールを処理したい場合は、Berkeley DB を使います。
 Berkeley DB には、いくつかのバージョンがあります。従来からよく使われてきたのは db-1.85 や db-1.86 です。sendmail-8.8.x ではこれよりも新しい Berkeley DB には対応していませんでした。そのため、このバージョンをインストールしているサイトも多いのではないかと思います。しかし、このバージョンにはバグが指摘されており、sendmail を運用するうえでのセキュリティ・ホールとなる可能性があります。sendmail とともに新しいものに入れ替えましょう。sendmail-8.9.x は、バージョン2.3.15 以降の Berkeley DB に対応しています。
 Berkeley DB のインストールは簡単です。パッケージを展開したあと、次のように操作するだけです。


% cd build.unix
% sh ../dist/configure
% make
% su
# make install

 これで、libdb.a が /usr/local/lib に、関連するインクルード・ファイルが /usr/local/include にインストールされます。また、いくつかのユーティリティ・プログラムが /usr/local/bin 以下にインストールされます。

その他のツール群
 sendmail にはオンライン・マニュアルが付属していますが、sendmail のコンパイル時にはこれらのファイルを groff を用いて整形するようになっています。groff が手許にない場合、OSに nroff が付属していればそちらを使うことも可能です。


コンパイルとインストール
 まず、sendmail のパッケージを入手します。http://www.sendmail.org/が公式のホームページですが、国内でもftp://ftp.kyoto.wide.ad.jp/sendmail/などでミラーしています。
 現時点での最新バージョンは、sendmail.8.9.1.tar.gz です。一部のMUAではMIMEを扱う際のバッファ長に問題があり、sendmail 側でそれに対応するためのパッチとして sendmail.8.9.1a.patch というファイルがあります。ただしこのパッチは不完全なようで、これを用いるにはさらに ftp://ftp.kyoto.wide.ad.jp/sendmail/sendmail.8.9.1a.unofficial.patch というパッチも当てる必要があります。作業例を以下に示します。


% gzip −cd sendmail.8.9.1.tar.gz | tar xvf −
% cd sendmail-8.9.1/arc
% patch < ../../sendmail.8.9.1a.patch
% patch < ../../sendmail.8.9.1a.unofficial.patch


Buildスクリプトの実行
 sendmail のコンパイルは、src ディレクトリで Build というスクリプトを実行するだけです。これで、自動的にOSの種別を判定して make までおこなってくれます。
 ただし、Berkeley DB や BIND 付属のリゾルバ・ライブラリを利用する場合などは、ライブラリやインクルード・ファイルのパスを以下のように指定します(旧いバージョンの Berkeley DB には ndbm.h というヘッダ・ファイルが付属していました。これと、OS付属の ndbm.h という名前がぶつかってしまい、sendmail のコンパイルがうまくできないことがあります。この場合は、旧い Berkeley DB の ndbm.h (/usr/local/include などにある)を消去して、Berkeley DB を新しいものに入れ替えてください)。


% sh Build −I/usr/local/include/ -L/usr/local/lib

 より細かな制御をおこないたいのであれば、BuildTools/README ファイルの記述に従って siteconfig.m4 というファイルを書き、Build スクリプト実行時に指定することができます。たとえば groff を nroff で代用したい場合は、次のような内容の siteconfig.m4 ファイルを src ディレクトリに作ります。


% APPENDDEF('confMANDOC','-man')
% APPENDDEF('confNROFF','nroff')

 そして、次のようにして Build を実行します(必要なら −L や −I も指定してください)。


% sh Build −f siteconfig.m4

 obj.OSname.architecture という名前のディレクトリ(obj.SunOS.5.6.sun4 など)が自動的に生成され、コンパイルはそこで実行されます。別のOS用のバイナリを作る際にも、作業ディレクトリが NFS で共有されているならば、同じ src ディレクトリで Build を実行してかまいません。
 コンパイル中に何か失敗し、最初からやりなおしたい場合には、この obj.OSname.architecture ディレクトリをまるごと削除します。

 あとはインストールですが、これも Build スクリプトを用いて、次のように実行します。


% su
# sh Build install

ファイルの許可モードの確認
 最近のバージョンの sendmail は、セキュリティ対策として各種の設定ファイルやディレクトリに対する書込み許可が不必要に多いと起動しないようになっています。具体的には、以下のディレクトリやファイルに root 以外のユーザが書き込めるようになっていてはいけません。

●sendmail.cf ファイルと、/からそこにたどり着くパスに含まれるすべてのディレクトリ(/etcなど)
●aliases ファイルと、/からそこにたどり着くパスに含まれるすべてのディレクトリ(/etcなど)
●キュー・ディレクトリ(デフォルトでは /var/spool/mqueue ) と、/からそこにたどり着くパスに含まれるすべてのディレクトリ(/var、/ver/spool など)
●sendmail 自身のプログラム・ファイルと、/からそこにたどり着くパスに含まれるすべてのディレクトリ(/usr、/usr/sbin など)

 aliases ファイルからインクルードして利用するファイルも、これと似た制約を受けます。具体的には、インクルードされるファイル自体の所有者は一般ユーザでもかまいませんが、所有者以外の書込みは禁止され、ファイルにたどり着くすべてのパスは root のみが書込み可でないといけません。また、NFSで別のホストのディスクを利用している場合も問題になることが多いので、これらのファイルはローカルディスクに置くようにしましょう。
 ただし、どうしてもグループ権限で書込みを許可したいファイルなどがあるのなら、CF で sendmail.cf を作成する際に DontBlameSendmail を指定して、sendmail にこのチェックをさせないようにすることも可能です。これについては、CF の doc ディレクトリ以下にあるドキュメントを参照してください。

sendmail.cfの設定

 では、実際に sendmail.cf を書く段階に入ります。ここでは CF を用いることにします。
 CF はたいへんよくできたツールです。必要最低限の設定だけで、ほかの部分についてはデフォルトのままでもさまざまな要素を加味した sendmail.cf を生成してくれます。とくに CF-3.7W からは、メールの不正中継への対策がデフォルトで含まれるようになったので、これについても複雑に考える必要はありません。典型的な運用形態のサイトならば、簡単な設定だけですみます。
 しかし、ほかのさまざまな状況にも対応できるようにするには、sendmail.cf の基本的な構造は知っておいたほうがよいでしょう。たとえば、CFを用いて sendmail.cf を作ったとしても、正しく動作するかを確認するには sendmail 自身のアドレステストモードの機能を使うことになります。これを使うには sendmail.cf 自体の仕組みをある程度理解していなくてはなりません。
 sendmail.cfの概要はこちらで説明しています。

CFのパッケージの入手
 CF の利用には Perl が必要です。バージョン4か5のどちらかがあれば大丈夫です。
 CF のパッケージの現時点での最新バージョンは CF-3.7Wpl2.tar.gz です。これを使うには、以下の2つのパッチを適用する必要があります。

  ●CF-3.7Wpl2-smtpcheck.patch1
  ●CF-3.7Wpl2-smtpcheck.patch2

 上記のパッチとパッケージ本体(CF-3.7Wpl2.tar.gz)はすべて ftp://ftp.kyoto.wide.ad.jp/mail/CF/ にあります。
 これを入手して展開すると、CF-3.7Wpl2 という名前のディレクトリができます。その後パッチを当てます。以下にその手順を示します。


% gzip −cd CF-3.7Wpl2.tar.gz | tar xvf −
% cd CF-3.7Wpl2/Master
% patch < ../CF-3.7Wpl2-smtpcheck.patch1
% patch < ../CF-3.7Wpl2-smtpcheck.patch2

 パッチを当て終ったら、CF-3.7Wpl2 という名前のディレクトリにある README.jpn ファイルに、最初にやるべきことが書かれているので、それに従って作業をします。
 Makefile の最初のほうにある PERL変数の行で、perlコマンドの名前(perl5、jperl など)を設定します。次に、このディレクトリで Perl が実行パスにある状態で、


% make cleantools
% make tools

 を実行します。これで CF を使う準備ができました。

 基本的な使い方は、まず filename.def という名前(filenameの部分はどんなものでもよい) の設定ファイルを作成し、そのあとに make filename.cf を実行します。すると、def ファイルに対応する sendmail.cf 形式のファイルが作られます(filename.cfになります)。したがって、まずサイト内の各ホスト用の sendmail.cf を作るための def ファイルを記述する必要があります。
 詳しい解説は、doc ディレクトリの下にある MANUAL.jpn を参照してください。このディレクトリには CF 自体の解説以外にも、メール配送に関して参考になるさまざまな情報が置かれています。

サイトのホスト構成を考える
 複数のホストがあるサイトでは、サイト内のユーザはどのホストを利用しても同じ環境でメールのやりとりができるようにすると便利です。そこで、CF での作業に先立って、「どのようなホスト構成(ホストごとの役割分担)で運用するか」についての方針を立てます。
 単純な例を紹介すると、各ユーザのメールをスプールするホスト(以下、スプールホスト)を1台準備し、中心的な処理はすべてスプールホスト上でおこないます。サイト内のほかのホストはすべてのメールをスプールホストに転送します。

末端ホストでのsendmail.cfの設定
 前述の構成では、スプールホスト以外のホストの sendmail は、もっぱらそのホスト上のユーザがメールを発信する際に用いるだけで、外部からのメールを受け取る必要はありません。このようなホストでは、CF のパッケージの Standards ディレクトリに含まれる null-v8.def をもとに設定をおこないます( sendmail のバージョンに応じて null-v?.def という名前のファイルがいくつか準備されています。どうしても旧いバージョンの sendmail のまま運用したい場合は、対応するものを使ってください。たとえば、8.8.xであれば null-v7.def を使います。対応関係は dec/README.jpn に書かれています)。
 以下の作業は、CFのパッケージを展開した際にできる CF-3.7Wpl1といったディレクトリをカレント・ディレクトリにしている状態でおこないます。まず Standards/null-v8.def をカレント・ディレクトリにコピーして、そのファイルを編集します。
 このファイルにはたくさんの設定がありますが、以下の2ヶ所を変更するだけで十分でしょう。

OS_TYPE:
Master/OSTYPEディレクトリ中に存在する各種のOSから、該当するものを1つ選びます最初はコメントアウトされた状態で書いてありますが、この行を記述したらコメント記号を取り除いてください。
SPOOL_HOST:
スプールホストをホスト名で指定します。

以上を適切な値に変更し、次のようにタイプします。


% make null-v8.cf

 すると、null-v8.cf という名前のファイルが生成されます。これを /etc/sendmail.cf にコピーします。コピーの際には、デーモンの sendmail が起動中ならそれをいったん止めて、コピーが終ったあとに sendmail が起動中ならそれをいったん止めて、コピーが終ったあとに sendmail を再起動します。作業例は以下のようになります。
 まず、現在の sendmail のプロセスIDと起動時オプションを、sendmail.pid ファイルを見て確認します(旧い sendmail では、このファイルにはプロセスIDのみが書かれている場合もあります)。このファイルは、OSによっては /etc/mail や /var/run などに作られる場合もあります。


% cat /etc/sendmail.pid
13079
/usr/lib/sendmail -bd −q1h

 確認したら、停止から再起動までをおこないます。


% su
# kill 13079
# mv /etc/sendmail.cf /etc/sendmail.cf.old
# cp null-v7.cf /etc/sendmail.cf
# /usr/lib/sendmail −bd −qh1

 同じOSのホストなら、まったく同じ sendmail.cf が利用できます。複数のOSを使っている場合は、個別に作成してください。

スプールホストでのsendmail.cfの設定
 各サイトの中心となるスプールホストでは、Standards ディレクトリにある sendmail-8v.def をもとに設定をおこないます(これも sendmail のバージョンに応じて数種類あります。バージョン8.8xの場合には sendmail-v7.def を使ってください)。
 このホストでは、以下のような項目について設定する必要があります。各項目についての詳しい説明は doc/MANUAL.jpn を参照してください。

OS_TYPE:
末端ホストの場合と同じく、OSの種類を選びます。

ACCEPT_ADDRS:
 このホストが、"自分宛" と認識すべきドメイン名を指定(複数ある場合は空白で区切って列挙)します。たとえば、前述の mail.kaisya.co.jp の例なら、username@kaisya.co.jp 宛のメールを受け取りたいので "kaisya.co.jp" を指定します。この例のように、自分自身のホスト名(FQDN:Fully Qualified Domain Name) から最初のドットまでを取り除いたものと一致するならば、ACCEPT_ADDRS='$m' と指定することも可能です。

ACCEPT_LOWER:
 ACCEPT_ADDRS='kaisya.co.jp' と設定したときに、username@kaisya.co.jp 形式だけでなく username@host.kaisya.co.jp 形式のアドレスについても自分宛と認識したい場合に、yes を指定します(デフォルトは no )。

LOWER_MATCH_STYLE:
 上記の ACCEPT_LOWER を用いる場合に、host.kaisya.co.jp の host の部分に入る文字列のパターンを制限したい場合に用います。

FROM_ADDRS:
 発信されるメールのヘッダの From: 行やエンベロープの送信人の部分に@が含まれない場合に付加されるドメイン名を指定します。通常は、前述の ACCEPT_ADDRS と同様の内容を指定します。ただし、MUA側の設定により MUAが@以下を付加してメールを発信する場合には、この設定はとくに意味をもたないことになります。

PRIVACY_FLAGS:
 SMTPコマンドなどに関する制限を指定できます。デフォルトでは authwarnings が指定されていますが、goaway の指定をおこなうことを薦めます。

LOCAL_HOST_DOMAIN:
 メールの不正中継の拒否に関連する設定です。ここで指定したドメイン名のホストからの接続については、無条件にメールの中継を許可します。前節で設定した末端ホストからメールが発信される場合はすべてのメールがスプールホストを通過することになるので、この設定でそれらのホストを許可するようにしておく必要があります。

LOCAL_HOST_IPADDR:
 LOCAL_HOST_DOMAIN と同様の機能をもちますが、ホストの指定にドメイン名でなくIPアドレスを用います。

ALLOW_RECIPIENT_DOMAIN:
 外部から受信したメールの場合に、その宛先アドレスが自分の受理すべきアドレスと縁がないものならば不正リレーとして拒否しますが、自分が受理するアドレスであれあ拒否してはいけません。これに関する設定をここでおこないます。
 このチェックは、"自分宛かどうか" の判定とは独立しておこなわれるので、本来受理すべきアドレスまで拒否してしまうことがあります。CFを使って sendmail.cf を作る場合は、前述の ACCEPT_ADDRS に指定したものなどについては自動的に ALLOW_RECIPIENT_DOMAIN に指定したのと同じ扱いになるので、ここでの指定はとくにおこなわなくても大丈夫です。
 しかし、ACCEPT_LOWER などで指定したものは自動では含まれません。また、優先度の低い MX として働くホストの場合、ACCEPT_ADDRS には書かなくても ALLOW_RECIPIENT_DOMAIN には書く必要があることも考えられます。こういった点に注意して、"拒否しすぎ" にならないように設定してください。



sendmail.cfの概要

 sendmail.cf は、設定ファイルというよりはプログラミング言語の一種と考えても差支えないほど、柔軟な記述が可能です。実際、我々が慣れ親しんだ "ユーザ名@ホスト名" の形式に限らず、設定しだいでさまざまな形式のメールアドレスを扱えるようになっています。
 この柔軟さゆえに、"ユーザ名@ホスト名" 形式の単純なメールを扱うだけで、何行もの記述が必要にもなります。しかし、アドレス形式のように基本的な部分についてはどのサイトでも事情は同じなので、sensmail.cf も似たものになります。こういった部分の設定を自動化してくれるのが、前節で述べているCFなどのツールです。
 CFなどの使い方をマスターしてしまえば、sendmail.cf 自体の構造に通じていなくてもたいていのサイトの設定は可能です。しかし、ほかのさまざまな状況にも対応できるようにするには、sendmail.cf の基本的な構造は知っておいたほうがよいでしょう。
 たとえば、CFを用いて sendmail.cf を作ったとしても、正しく動作するかを確認するには sendmail 自身のアドレステストモードの機能を使うことになります。これを使うには sendmail.cf 自体の仕組みをある程度理解していなくてはなりません。

書換えルールと配信エージェント
 sendmail.cf の記述の中心は、"メールアドレスの書換えのためのルール定義" です。書き換えるといっても、へッダ中の To: や From: フィールドの内容を本当に書き替えるような使い方はどちらかというと副次的なものです。主要な目的は、"エンベロープの受信人のメールアドレスの構造を整理して、配信エージェント(メール配送を担当するプログラム)およびその引数を決定することです。
 たとえば、mail.kaisya.co.jp というホストでは、アドレス user@kaisya.co.jp に宛てたメールを受信するものとします。このホストではそれ以外にも、同じホストからuserのみの(@以下がない)アドレスに宛てたメールも受信し、さらに "発信側では、DNSを検索してMXがみつからなければAレコードを利用する" という仕組みに対応するために、user@mail.kaisya.co.jp 形式のアドレスも受信する必要があります。
 こうした場合、mail.kaisya.co.jp 上の sendmail.cf では、

user@mail.kaisya.co.jp は user に書き換える
user@kaisya.co.jp も user に書き換える
●このような書換えを経て最終的に@が残っていれば、SMTPを配信エージェントとして外部に送信する(この場合は、@以下の部分についてDNSでMXを検索し、送信する相手を決定する)
●さもなくば、メールはこのホスト宛であるとして扱い、配信エージェントとして /bin/mail を起動し、引数としてユーザ名を渡す

という記述をおこないます。
 このような設定を sendmail.cf 流に書くと、以下のようになります。


SO
R$+@mail.kaisya.co.jp  $1
R$+@kaisya.co.jp    $1
R$+@$+          $#smtp $@$2 $:$1
R$+             $#local $:$1

Mlocal, P=/bin/mail, S=0, A=mail −d $u
Msmtp, P=[IPC], S=0, R=0, A=IPC $h

 sendmail.cf の各行は、最初の1文字によってさまざまな意味をもちます。

◆ルールセットの開始(S行)
 Sから始まる行は、ルールセットの開始行を意味します。上記の例では0番というルールセットの定義をおこなっています。ルールセット0番は、配信エージェントの決定の際に用いられます。ルールセットについての詳細は後述します。

◆書換えルール(R行)
 Rから始まる行では、ルールセットを構成するルールを記述します。具体的には、メールアドレスに対して各ルールの左辺とパターン・マッチングを行ない、パターンが合致すれば右辺のものに書き換えます。この文法の詳細は割愛しますが、sed や Perl を知っている人なら概略は把握できるのではないでしょうか。書換えを繰り返した結果、最終的に "$#" から始まる形に書き換えられ、この結果に従って配信エージェントの種類と引数の値が決定されます。

◆配信エージェント定義(M行)
 Mから始まる行では、配信エージェント名と実際のプログラムとの対応関係を記述します。上の例では、最後の2行で local と smtp という名前の2つの配信エージェントを定義しており、それらがルールセット0番のなかで参照されています(配信エージェントのうち "local" という名前には特別な意味があり、/etc/aliases を適用するなどの作業が自動的におこなわれるようになっています。また、"prog" という名前にも特別な意味があり、この2つは必ず定義する必要があります。これらの行はOSにあわせた記述をする必要がありますが、CFを用いる場合は OS_TYPE の定義に応じて自動生成されます。ただし、場合によってはOS標準添付の sendmail.cf の記述を参考に、手作業で sendmail.cf を書き直す必要が生じるかもしれません)。

ルールセット
 ルールセットには、配信エージェントを決定する0番(S0)のほかにも、発信人メールアドレスの書換えを目的とするもの(S1)、受信人メールアドレスの書換えを目的とするもの(S2)、S0,S1、S2に共通して必要な前処理をおこなうもの(S3)、S1とS2に共通の後処理をおこなうもの(S4)、エイリアス・ファイル(後述)を適用したあとに用いられるもの(S5)などがあります。さらに、最近のバージョンではメール配送のリレー制御を定義するためのルールセット(Scheck_relay など)が追加されています。
 M行のなかで "S=" および "R=" のように指示されている数値は、その配信エージェントが選択されたときに用いられるルールセットの番号を示します。S=は送信人アドレス(エンベロープとヘッダのFrom:)の書換えに関するルールを示し、R=は受信人アドレス(エンベロープとヘッダのTo:、Cc:)の書換えに関するルールを示します。
 ただし、0が指定されると "とくに書換えをおこなわない" という意味になります。エンベロープとヘッダとで違う書換えをおこなう場合には、"S=11/12" といった記述もできます(前者がエンベロープ用、後者がヘッダ用)。
 慣習的に、多くの場合S=では10〜19番のルールセットが、R=では20〜29番のルールセットが用いられます。
 以上で紹介した以外のルールセットは、sendmail 自体にとって特別な意味をもたなくても、サブルーチンとして定義したいときなどに用いることができます。CFの場合、各ルールセット番号の意味は、doc/RulesetNumbers に書かれています。
 ルールセットの適用の流れは、以下のようにまとめることができます。

●配信エージェントを選択する際
 S3 → S0
●送信人アドレスの書換えの際
 S3 → S1 → "S=" のルールセット → S4
●受信人アドレスの書換えの際
 S3 → S2 → "R=" のルールセット → S4

 さらに、配信エージェントとして local が選択された場合にはエイリアス・ファイルの展開処理をおこない、それで変化があった場合には再度この処理を最初から繰り返します。変化がなかった場合には最後にS5が適応されます。この機構は、たとえばCFで null-v?.def を利用したときに使われます。null-v?.def においては "すべてのメールをそのままスプールホストに転送する" のが基本ですが、S5を活用することによりエイリアス展開の処理だけはおこなわれるようになっています。
 ちなみに、S1とS2のルールセットは現在はほとんど用いられておらず、配信エージェントの個別の設定(S=、R=)のみが利用されることが多くなっています。


マクロ変数
 前述の sendmail.cf の例は、説明のためにかなり簡略化しました。実際には、"kaisya.co.jp" といった文字列はルール中には直接記述せず、マクロ変数を定義して、それを参照するのが一般的です。
 マクロ変数には2種類あります。D行で定義するものと、C行で定義するものです。

◆単一の値をもつマクロの定義(D行)
 Dで始まる行で定義するものは変数に1つだけ値を保持できます。たとえば、

DAkaisya.co.jp

と書けば、R行中で "$A" とすることで "kaisya.co.jp" という値を参照できます。マクロ変数名は、旧いバージョンの sendmail では1文字に制限されていましたが、最近は複数の文字を "{" と "}" で括った形式も使えるようになりました。ただし、いずれの場合もD行では変数名と値の間に空白を入れてはいけません。

◆複数の値をもつマクロの定義(C行)
 Cで始まる行で定義するものはクラスマクロと呼ばれます。1つの変数にいくつもの値を入れることができ、ルールのパターンマッチの際に "そのうちのどれか1つ" にマッチすればよい、という使い方ができます。前述の例なら、文字列 "kaisya.co.jp" と "mail.kaisya.co.jp" はどちらも同じように扱えばいいわけですから、こういうものにはクラスマクロを用います。R行では "$=A" などで参照できます。
 クラスマクロの値の定義では、別のファイルの内容を参照させることも可能です。この場合はFから始まる行を用いて、参照するファイル名を指定します(F行)。そうすると、ファイルから1行ずつ値をとってきてクラスマクロに設定してくれます。ただし、そのファイルは sendmail の起動時にしか参照されないので、内容を書き直したときは sendmail デーモンの再起動が必要になります。
 これらのマクロについては、実際に sendmail.cf を眺めてみると使われている様子が分かると思います。変数名の付け方は、ある程度慣習的なものもありますが、とくに定められているわけではありません。
 ただし、小文字の変数名は sendmail 自体が特殊な目的で用います。たとえば、j というマクロには、ホスト自身のFQDN(Fully Qualified Domain Name:インターネットのドメイン形式での完全なホスト名)が自動的に設定されます。また、W というマクロにはそこから最初のピリオドまでの部分(短いホスト名)が入り、m というマクロには残りの部分(いわゆるドメイン名)が入ります。さらに、クラスマクロ W には FQDN が自動的に追加されます。
 これらの値の設定は、sendmail の起動時に DNS の逆引き(PTRレコード)検索を利用しておこなわれます。DNSの逆引きが定義されていないなどの理由でこの検索が失敗するホスト(SunOS 5 系の場合、/etc/nsswitch.conf の設定も影響します。sendamil パッケージの src/README ファイルを参考にしてください)では、sendmail の起動に支障が生じます(念のため1分間待ってから DNS 検索に再挑戦し、それでも駄目なら起動を中止する)。こういう場合は、sendamil.cf 側で Dj、Dw、Dm、Cw の行を自分で記述すれば対処できます。CFの場合は、それぞれ OFFICIAL_NAME、MY_NAME、MY_DOMAIN、MY_ALIAS に対応します。

その他の構成要素
 ここまでで、sendmail.cf の構成要素として S行、R行、M行、D行、C行、F行があることを説明しました。これ以外にも以下のような行があります。

sendmail.cfのバージョン(V行)

 sendmail.cf の最初に書かれ、sendamil.cf 自体の文法のバージョンを示します。たとえば、sendmail-8.8 以降の機能を用いる sendmail.cf では V7 と宣言し、sendamil-8.9 以降の機能を用いる sendmail.cf では V8 と宣言します。これは、新しい sendmail で旧い sendmail.cf を使った場合に、旧バージョンの sendmail と互換の動作をおこなうための機構です。CFを用いる場合は、CF_TYPE で指定することになります。

起動時オプション(O行)

 sendmail は、起動時に -o オプションを用いてさまざまな指定ができますが、sendmail.cf のO行でも同様の設定が可能です。sendmail.cf のO行で指定できることはすべて、CFでもなんらかの変数名が対応しています。詳細はCFのマニュアル(doc/MANUAL.jpn) を参照してください。

トラステッド・ユーザー(T行)

 ユーザーコマンドとして sendamil を起動してメールを発信する場合、エンベロープでの送信人は通常、プロセスのUIDを参照して設定されます。ただし、-f オプションを用いて明示的にエンベロープを指定することも可能です。この -f オプションを使うことができるユーザーを制限する目的で、トラステッド・ユーザー(trusted user: 信頼できるユーザー) を指定する機構が用意されています。この設定を T行に記述します。CFでは TRUSTED_USER が対応します。
 この機構の細部は、sendmail のバージョンとともに変遷を経てきました。現在のバージョンでは、トラステッド・ユーザー以外のユーザーが -f オプションを利用した場合、X-Authentication-Warning:フィールドが付加されるようになっています。また、クラスマクロtを用いた定義もできるようになったので、Ftという形式が使えます。CFでが、TRUSTED_USERS_FILE_PATH が対応します。

ヘッダ形式(H行)

 From:、Date:、Message-ID: といったヘッダフィールドがない場合、sendmail によって自動的にこれらが付加されます。また、sendamil を経由するたびにReceived:ヘッダフィールドが1つずつ先頭に加えられます。このとき、各ヘッダフィールドの形式を定義するのにH行が用いられます。ただし、ヘッダフィールドごとの特性(たとえばReceived:はすでにあっても追加するなど)の違いについては、sendmail のプログラム自身が静的に決定するので、sendmail.cf で変更することはできません。CFでは、Received:の形式を FORMAT_RECEIVED で指定できます。

配送の優先度(P行)

 sendmail はメールヘッダ中に Precedence:フィールドがあると、配信キューに溜まったメール内における優先度を決定したり、配送エラーが発生した際にエラーメールを返すべきかどうかを決定したりします。その際の優先度の調節をP行で設定できますが、通常は標準的な指定を用いるべきです。これは、CFでも変更できないようになっています。

キー付きマップ(K行)

 ルール(R行)では、外部のデータベースの情報を利用した書換えができます。この機能を利用するにはK行でマップ名の定義をおこないます。CFでは、usertable の機能を用いる際などにK行が自動生成されます。
 下に、ここまでに解説した各行の意味を示します。

コマンド解説
ルールセットの開始を宣言
書換えルールを定義
配信エージェントを宣言
マクロを宣言
クロスマクロを宣言
外部ファイルからクラスマクロを宣言
sendmail.cf のバージョンを定義
起動時オプションを宣言
トラステッド・ユーザーを宣言
ヘッダ形式を宣言
配送の優先度を宣言
キー付きマップを宣言


アドレステスト・モード
 CFなどを利用して sendmail.cf を作成したら、意図したとおりに動作するかを確認します。具体的には、以下のような点を確かめる必要があるでしょう。

●いろいろなメールアドレスについて、適切な配信エージェントが選択されるか。
−自分のホストで受け取るべきアドレスに対して、正しくlocal配信エージェントが選択されるか。
−UUCPを用いた配送をおこなっているホストやファイヤウォールの場合、関連するアドレスのパターンが正しく特別扱いされる(適切な配信エージェントが選択される)ようになっているか。
●配信エージェントに応じて、ヘッダの書換えが適切になされるか。とくに、MUAがTo:やFrom:に@を付けずにメールを発信した場合に、サイト外に出て行くなら適切な補完をおこなうようになっているか。
●メールのリレーに関して、拒否すべき状況とそうでない状況を適切に区別するか。

 こういった点を確認するために、sendmail にはアドレステスト・モードがあります。このモードでは、対話的な操作によって sendmail.cf の動作を確認することができます。このモードを用いるには、−btオプション(下表)を付けて sendmail を起動します。具体的には以下のようになります。


% /usr/lib/sendmail -bt -Csendmail.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
>

 −btオプションのほかに −C(大文字)オプションも指定しています。これにより、アドレステスト・モードで用いる sendmail.cf を指定します。こうして起動すると、メッセージ(メッセージには "ruleset 3 NOT automatically invoked" という注意書きが含まれています。これは、旧い sendmail のアドレステスト・モードにあったすべてのメールアドレスの入力に対して無条件でルールセットの3番(S3)が適用されるという機構が、現在では廃止になったからです。現在は、"3.0" のように複数のルールセット名をカンマで区切って列挙することにより、複数のルールセットを自由に組み合わせてテストすることができます)のあとのプロンプトの ">" が表示されます。
 まず、アドレステスト・モードでの操作方法を知るために、たんに "?" のみを入力してみましょう。すると、コマンドの一覧が出力されます。

表 sendmailの−bオプション一覧
オプション解説
−btアドレステスト・モードを起動する
−bs標準入力経由でSMTPを起動する
−biエイルアス・ファイルのデータベースを初期化する(コマンド名 newaliases で起動しても同じ)
−bdデーモンとして起動する(25番ポートでSMTP接続を待ち受ける)
−bpキューに溜まっているメールの一覧を表示する(コマンド名 mailq で起動しても同じ)


マクロの内容の表示

 sendmail のヘルプを見ると、"$" を付ければマクロの内容を表示できることが分かります。また、"$=" を付ければクラスマクロの内容も確認できます。これを用いて、以下のような重要なマクロに適切な値が設定されていることを確認しましょう。


> $j
mail.kaisya.co.jp
> $w
mail
> $m
kaisya.co.jp
> $=w
mail
mail.kaisya.co.jp
mail.kaisya
localhost
local
[127.0.0.1]
[123.45.67.8]

配信エージェントの選択状況の確認

 ルールセット番号のあとにメールアドレスを指定すると、ルールセットを適用した結果をチェックできます。これを用いて、いくつかのアドレスについて、配信エージェントの選択が正しくおこなわれるかをテストします。
 ここで、ルールセットはカンマで区切って複数を並べることができます。配信エージェントの選択にはS3のあとにS0を用いますから、"3,0" と書くことになります。下に実験例を示します(図1)。

図1 配信エージェントの選択のテスト例

> 3,0 kikuchi
rewrite: ruleset  3  input: kikuchi
rewrite: ruleset  3 returns: kikuchi
rewrite: ruleset  0  input: kikuchi
rewrite: ruleset  0 returns: $# local $: kikuchi
> 3,0 kikuchi@mail.kaisya.co.jp
rewrite: ruleset  3  input: kikuchi @ mail . kaisya . co . jp
rewrite: ruleset 96  input: kikuchi < @ mail . kaisya . co . jp >
・・・・・・・・
rewrite: ruleset  3 returns: kikuchi
rewrite: ruleset  0  input: kikuchi
rewrite: ruleset  0 returns: $# local $: kikuchi
> 3,0 kikuchi@yoso.co.jp
rewrite: ruleset  3  input: kikuchi @ yoso . co . jp
rewrite: ruleset 96  input: kikuchi < @ yoso . co . jp >
・・・・・・・・
rewrite: ruleset 88  input: < smtp : yoso . co . jp > . kikuchi < @ yoso . co . jp >
rewrite: ruleset 88 returns: $# smtp $@ yoso . co . jp . $: kikuchi < @ yoso . co . jp >
rewrite: ruleset  0 returns: $# smtp $@ yoso . co . jp . $: kikuchi < @ yoso . co . jp >

 このように、最終的にはルールセット0において "$#" のあとに配信エージェント名が出力されるので、自分自身が受信すべきアドレスについては "local" が、外部に送るものについてはほかの配信エージェント名が出力されるのを確認してください。
 ただし、null-v8.def などを利用して作成した sendmail.cf でが S0 はかならず local になり、S5 でスプールホストへの転送をおこなうようになっています。注意してください。

アドレスの書換えの確認

 sendmail は、配信エージェントの決定後、ヘッダやエンベロープのアドレスの書換えをおこないます。この際、選択された配信エージェントに応じた S= や R= の指定が可能なので、配信エージェントごとに違う書換えをおこなうようになっている場合があります。
 たとえば、同じSMTPを利用する場合でも、"サイト内であれば To: 行や Cc: 行にドメイン名を補完しないまま転送し、サイトの外部に出るときにのみ補完をおこなう" という場合、前者と後者では異なる配信エージェントを使います。
 具体的には、sendmail.cf 中で、


Mrelay,  P=[IPC], S=11, R=29, ...
Msmtp,  P=[IPC], S=11, R=21, ...


のようにして、サイト内の別のホスト宛の場合には relay 配信エージェントを用い、サイト外のホスト宛の場合には smtp 配信エージェントを用いる、という仕組みになります。ただし、いずれも P=[IPC] という指定のため、配信の手段としてはSMTPが用いられます。

 CFを用いて sendamil.cf を作成すると、各変数に設定した値に従って書換え規則と配信エージェントが決められます。アドレステスト・モードでは、以下のような点を確認すればよいでしょう。

●どういうアドレスの場合にどの配信エージェント名が選択されるかを調べる(サイト内がどれで、サイト外がどれかなど)。
●それぞれの場合について、M行の S= と R= を調べ、そのルールセットの動作を確認する。

 たとえば、前述のような M行をもつ sendmail.cf を用いてる場合に、ある宛先アドレスについて smtp 配信エージェントが選択されたとしましょう。すると、ヘッダ中の From: については S3 → S1 → S11 → S4 が適用され、To: や Cc: については S3 → S2 → S21 → S4 が適用されることになります。この処理がうまくいくかどうかを順に確認します。
 まず、送信人アドレスについては、@がない場合に付くドメイン名が適切であるかを確認します。(図2)

図2 送信人アドレスの書換えのテスト

> 3,1,11,4 kikuchi
rewrite: ruleset  3  input: kikuchi
rewrite: ruleset  3 returns: kikuchi
rewrite: ruleset  1  input: kikuchi
rewrite: ruleset  1 returns: kikuchi
rewrite: ruleset 11  input: kikuchi
rewrite: ruleset 11 returns: kikuchi < @ kaisya . co . jp >
rewrite: ruleset  4  input: kikuchi < @ kaisya . co . jp >
rewrite: ruleset  4 returns: kikuchi @ kaisya . co . jp
> 3,1,11,4 root
rewrite: ruleset  3  input: root
rewrite: ruleset  3 returns: root
rewrite: ruleset  1  input: root
rewrite: ruleset  1 returns: root
rewrite: ruleset 11  input: root
rewrite: ruleset 11 returns: root < @ kaisya . co . jp >
rewrite: ruleset  4  input: root < @ kaisya . co . jp >
rewrite: ruleset  4 returns: root @ kaisya . co . jp

 CFの場合には、FROM_ADDRESS や SPECIAL_FROM などの設定に応じて S11 が生成されます。また、LOCAL_ADMIN_USERS に定義されたユーザー名については、上記の変数の設定とは関係なく FQDN (マクロjの値)が付加されるようになっています。これは、各ホストの cron などが自動送信するメールについて "どのホストが送信したのか" を特定しやすくするための仕組みです。
 ちなみに、LOCAL_ADMIN_USERS と同様の扱いを別のユーザー名に対してもおこないたい場合には、LOCAL_USERS に指定すればよいでしょう。
 続いて、受信人アドレスについても同様の確認をおこないます。ここで、「"To: kikuchi" なら local 配信エージェントなんだし、"To: dareka@yoso.co.jp" ならもとからドメイン名が付いているんだから、受信人アドレスの書換えは必要ないのではないか」と思われるかもしれません。しかし、


To: kikuchi, dareka@yoso.co.jp

のように、ローカルユーザーと外部のユーザーとに同時に出されたメールの場合、外部のユーザーへ送信するメールについては、


To: kikuchi@kaisya.co.jp, dareka@yoso.co.jp

のように書き換える必要があるのです。
 この場合、smtp 配信エージェントが選択されますから、R=21 が利用されることになります。そこで、図3のようにしてチェックします。

図3 受信人アドレスの書換えのテスト

> 3,2,21,4 kikuchi
rewrite: ruleset  3  input: kikuchi
rewrite: ruleset  3 returns: kikuchi
rewrite: ruleset  2  input: kikuchi
rewrite: ruleset  2 returns: kikuchi
rewrite: ruleset 21  input: kikuchi
rewrite: ruleset 21 returns: kikuchi < @ kaisya . co . jp >
rewrite: ruleset  4  input: kikuchi < @ kaisya . co . jp >
rewrite: ruleset  4 returns: kikuchi @ kaisya . co . jp


メールのリレー制限に関する確認

 バージョン8.8 以降の sendmail では、不正なメールのリレーに関するチェックをおこなうため、check_relay、check_mail、check_rcpt、check_compat というルールセットが用いられるようになりました。いずれのルールセットも、必要な状況下で sendmail 側からなんらかの入力が設定されて呼び出されます。その入力に対してメールの配送を拒否すべきときは "$# error" を返し、拒否すべき理由がないならば OK という結果を出すように sendmail.cf を作っておけば、それを利用して判定してくれる仕組みなっています。
 各ルールセットは、次のような役割を果たします。

●check_relay
SMTP 接続元のホストのドメイン名とIPアドレスの情報をもとに、そのホストに対してSMTPコマンドを許可するか否かを決定する。

●check_mail
エンベロープの送信人アドレスを入力としてとり、配送の可否のチェックをおこなう。

●check_rcpt
エンベロープの受信人アドレスを入力としてとり、配送の可否のチェックをおこなう。

●check_compat
エンベロープでの送信人と受信人の組を入力としてとり、配送の可否のチェックをおこなう。ただし、CFではこの機能は用いられていない。代わりに、check_rcpt 内で入力とマクロの値を組み合わせて同様のことを実現している。


check_relay

 このルールセットへの入力は、その sendmail に対して SMTP 接続してきたもとの IPアドレスと、DNS を逆引き検索して得られるドメイン名との組です。以下に示すように、ホスト名(ドメイン名)とIPアドレスのあいだに "$|" を挟む形式になります。


mail.kaisya.co.jp $| 123.45.67.8

 ただし、アドレステスト・モードでこのまま指定すると、"$|" の部分が "$" と "|" に分解されてしまいます。CFでは CheckDebug という "$ と | をくっつけるだけ" のルールセットが準備されているので、これも併せて利用します(図4)。

図4 check_relayルールセットのテストの例

> CheckDebug,check_relay mail.kaisya.co.jp $| 123.45.67.8
・・・・・・
rewrite: ruleset 191 returns: OK

 CFの場合は、CHECK_HOST_ALLOW、CHECK_HOST_DENY によって設定します。パターンの記述には、IPアドレスの先頭の一部を指定する方法とドメイン名の末尾の一部を指定する方法のどちらでも用いることができます(ただし、各ルールセットにとってはドメイン名もIPアドレスもただの文字列にすぎません。CFでは、CHECK_HOST_ALLOW などのいくつかの変数について、ドメイン名とIPアドレスのいずれを利用してもいいような細工がしてありますが、基本的にはまったく別のものと考える必要があります)。
 まず、CHECK_HOST_ALLOW のパターンに合致するホストは接続が許可されます。そのあとで CHECK_HOST_DENY のパターンと比較され、合致した場合は接続が拒否されます。いずれにもマッチしなかった場合は、CHECK_RELAY_DEFAULT により許可/拒否のいずれになるかが決定されます。
 通常のホストでは、SMTP接続自体を拒否する必要はありません。なぜなら、自分のホスト宛のメールはどのホストからのものでも受信したいからです。ですから、配信制限はほかのチェック機構によっておこなうべきです。
 ただし、クライアント専用のホストなどでは、DNSによりMXを別のホストに向けておけば、そのホスト自身が外部からのSMTP接続を受ける必要はなくなります。こういう場合は、CHECK_HOST_ALLOW を localhost のみに設定し、CHECK_RELAY_DEFAULT を deny にするのがよいでしょう。


check_mail

 エンベロープでの送信人、つまり SMTP の MAIL From:コマンドの情報を入力としてとるルールセットです。
 CFが生成する check_mail ルールセットは、ルールセット自体の入力のほかに、client_addr と client_name という2つのマクロの値を参照し、"これらの値が特定の組合せのときのみ拒否する" といった判定をおこないます。前者のマクロはSMTP接続元ホストのIPアドレスを保持し、後者のマクロはそれを逆引きして得られるドメイン名を保持しています。
 これらのマクロの値は sendmail によって自動的に設定されますが、アドレステスト・モードにおいては自分で設定する必要があります。マクロの値は ".D" を用いて設定することができるので、図5のように操作します。


図5 check_mailルールセットのテストの例

> .D{client_addr}123.45.67.8
> .D{client_name}mail.kaisya.co.jp
> check_mail kikuchi@mailkaisya.co.jp
・・・・・・
rewrite: ruleset 199 returns: OK

 エンベロープでの送信人の情報は送信者の手で好きなように設定できるので、悪意のある配送を拒否するための判断基準としてはあてにできません。ですから、CFで sendmail.cf を作成した場合、このルールセットでおこなうのは、"形式的にみて返信可能なアドレスであるかどうか" のチェックのみです。とくに "内部のホストからの接続時には、@のないエンベロープを用いていても許可するが、それ以外のホストからの場合には拒否する" というチェックがおこなわれます。このとき "内部のホストかどうか" の判定には、CFの LOCAL_HOST_IPADDR と LOCAL_HOST_DOMAIN が利用されます。
 類似のものとして、CLIENT_HOST_IPADDR と CLIENT_HOST_DOMAIN もあります。こちらは、"エンベロープに特定のドメイン名(通常はそのサイトのドメイン名)を用いている場合にのみ許可する" のに用います。この場合の特定のドメイン名は CLIENT_FROM_DOMAIN で接続する際に、ユーザが正しくない設定をしたままでメールを外部に発信するのを防ぐのに役立ちます。
 ただし、エイリアス・ファイルや .forward を用いて転送をおこなう機能をもったホストの場合は、外部から届いたメールがそのままのエンベロープで中継されます。そのようなホストは CLIENT_HOST_* には指定せず、前述の LOCAL_HOST_* を用いるのがよいでしょう。両方に合致した場合は LOCAL_HOST_* のほうが優先されます。


check_rcpt

 エンベロープでの受信人、つまりSMTPの RCPT To: コマンドの情報を入力としてとるルールセットです。
 このルールセットは、悪意のある配送リレーを制限する際に中心的な役割を果たします。具体的には、

●サイト内のホストから、そのサイト宛のメールの中継
●サイト内のホストから、外部サイト宛のメールの中継
●サイト外のホストから、そのサイト宛のメールの中継
●サイト外のホストから、外部サイト宛のメールの中継

のうち、最後のもののみを拒否する必要があります。このうち、"どのホストからか" についてはSMTP接続元を基準に判定し、"どこ宛のメールか" についてはエンベロープでの受信人を基準に判定します。
 このようなチェック機構を実現するために、CFでは check_mail と同様にマクロ client_addr とclient_name の値を参照します。アドレステスト・モードではあらかじめ ".D" を使って設定しておきます(同じ値を使い続けるかぎり、設定しなおす必要はありません)。図6に例を示します。

図6 check_rcpt ルールセットのテストの例

> .D{client_addr}123.45.67.8
> .D{client_name}mail.kaisya.co.jp
> check_rcpt kikuchi@mail.kaisya.co.jp
・・・・・・
rewrite: ruleset 194 returns: OK
> .D{client_addr}123.45.6.7
> .D{client_name}yoso.co.jp
> check_rcpt kikuchi@mail.kaisya.co.jp
・・・・・・
rewrite: ruleset 194 returns: OK
> check_rcpt dareka@yoso.co.jp
・・・・・・
rewrite: ruleset 194 returns: $# error ...

 CFでは、"どのホストからか" の判断については前述の LOCAL_HOST_* や CLIENT_HOST_* の設定が利用されます。これに対し、"どこ宛のメールか" について "サイト内部宛" と判断すべき部分は、ALLOW_RECIPIENT_DOMAIN で設定をおこないます。これは、あくまでエンベロープでの受信人アドレスのドメイン部分との照合をおこなうためのものです。IPアドレスを利用した設定はできないことに注意してください。
 マクロjの値(FQDN)など、"当然受理すべきアドレス" については、自動的にALLOW_RECIPIENT_DOMAIN と同様に扱われます。特別な設定(ACCEPT_LOWEW など) によって受理しているドメイン名がある場合は、ALLOW_RECIPIENT_DOMAIN に指定しなければなりません。
 また、別のドメインのための優先度の低いMXとして働くホストの場合には、そういったドメインについても配送中継を許可する必要があります。この場合は、ALLOW_RELAY_TO で設定します。これは、ALLOW_RECIPIENT_DOMAIN に指定するとほぼ同様の動作をしますが、A%B@C 形式(%-hack と呼ばれる) や @C:A@B 形式のような "ソース・ルーティング" 指定がなされたときにリレーを許可するかどうかが異なります。具体的には、REJECT_EXTERN_SRR が no のとき、上記のCの部分が ALLOW_RECIPIENT_DOMAIN に合致し、Bの部分が ALLOW_RELAY_TO に合致する場合は、接続元ホストがサイト外であってもリレーが許可されます。


エイリアス・ファイルの利用

 sendmail では、あるメールアドレスについて、ローカルに受理すべきものだと判断した場合、そのメールをたんにローカルにスプールする代わりに、別のメールアドレスに転送することができます。具体的には、sendmail.cf の OA行(最近のバージョンでは "O AliasFile" とも記述可能)で指定したファイルが "メールアドレスの変換表" として機能するようになっています。このファイルをエイリアス・ファイルといいます。多くのOSでは /etc/aliases にありますが、/etc/mail/aliases などを用いる場合もあります(sendmail.cf を見て確認してください)。
 ここでは、エイリアス・ファイルに関する注意点を簡単に説明します。

エイリアス・ファイルの形式

 エイリアス・ファイルは、次のいずれかの形式の行の羅列からなります。

ローカルアドレス: 変換後のアドレス
ローカルアドレス: 変換後のアドレス,アドレス,...
ローカルアドレス: :include:外部ファイル名

 最初の形式では、たんにアドレスに別名が付けられます。次の形式では、1つの宛先に届いたメールを複数のアドレスに配信しますから、メーリングリストとして用いることができます。最後の形式では、エイリアス・ファイル中に変換後のアドレスを直接列挙する代わりに、外部のファイルに記述することができます。
  外部のファイルを参照する場合、そのファイルの所有者を一般ユーザにすることで、"変換後のアドレス" の内容を変更するときに root 権限が不要になります。できるだけ活用しましょう。ただし、外部ファイルは次のような点に注意する必要があります。

●NFS上に置かない。
●所有者以外のユーザーが書き込めるようになっていてはいけない。

 エイリアス・ファイルに類似のものとして .forward というファイルがあります。これは各ユーザーのホーム・ディレクトリに置かれ、"そのユーザー宛に届いたメール" を転送したいときに、ユーザー自身が自由に用いることができるものです。.forward ファイルは、そのユーザー自身が所有している必要があり他人が書き込めるようになっていてはいけません。
 エイリアス・ファイルに直接書いたり :include: を用いる場合のほか、.forward ファイルを使うときも、"変換後のアドレス" の場所には、たんなるメールアドレスの代わりに次のようなものを書くこともできます。

●フルパスのファイル名(/から書き始める)
●"| プログラム名"

 ファイル名を書いた場合には、届いたメールはそのファイルに追加されていきます。よくある使い方は、/dev/null を指定して、不要なメールを捨ててしまう手法です。
 後者のようにパイプ記号(|)を用いた場合には、届いたメールは指定されたプログラムの標準入力に渡されます。これは、より柔軟にメールを処理したいときに便利です。各種のメール自動処理プログラムを用いて、次のような処理をおこなうことができます。

●メールを自動的に仕分けする。
●特定のメッセージに自動返送する。
●自動登録機能などをもったメーリングリストを運営する。

エイリアス・ファイルの更新

 sendmail は、多くのメールのエイリアス処理を効率的にこなすため、エイリアスを定義したテキストファイルを毎回読む代わりに、データベース・ライブラリを利用します(どのようなデーターベース・ライブラリを利用するかは sendmail のコンパイル時に決定されます)。
 データベース・ライブラリでは、もとのテキストデータに対して、高速に検索できる構造をした別のファイルを作ります。たとえば、NDBMライブラリを利用する場合には aliases.pag と aliases.dir というファイルが作成され、Berkeley DB ライブラリを利用する場合には aliases.db というファイルが作成されます(sendmailに -do.l というオプションをつけて起動すると、コンパイル時のオプションが表示されます。これにより、sendmail がどのタイプのデータベース・ライブラリを使っているかを確認できます)。検索が必要なときにはこれらのファイルを用います。
 ですから、エイリアス・ファイルを編集して変更した場合には、データベース・ライブラリの作るファイルも更新しなければなりません。そのためには、sendmail に -bi オプションを付けて起動します。あるいは、sendmail をインストールしたときに newaliases というコマンド名でシンボリック・リンクが張られるので、この名前で実行しても同じことが可能です。ただし、:include: で外部のファイルを参照している場合にそのファイルの内容を変更したときや、.forward の内容を変更した場合には、これを実行する必要はありません。
 経験によると、データベース・ファイルがまだ存在しない状態で newaliases を実行すると、1回目はなぜかエラーのようなメッセージが出力されるが、もう1度 newaliases を実行すると問題なく実行できる、ということがありました。新たに sendamil を利用する場合や、違うデータベース・ライブラリを使い始めた場合などには、newaliases を2回続けて実行してみてください。

ループの回避

 エイリアス・ファイルによって変換されたアドレスがやはりローカルに受信すべきアドレスであった場合、変換後のアドレスについても再度エイリアス・ファイルが適用されます。この作業は、それ以上変換できなくなるところまで繰り返されます。ですから、エイリアス・ファイルではループが発生するような定義をしてはいけません。
 よくあるのが、.forward で次のような記述をしてしまうようです(ユーザ名がkikuchiだとします)。


kikuchi, "| /usr/lib/mh/slocal -user kikuchi"

 これは、MHに付属の slocal というプログラムを用いて自動的に仕分けをすると同時に、念のために仕分け前のメールをスプールに残しておく設定ですが、このままではうまくいきません。

1.kikuchi が kikuchi と "| /usr/lib/mh/slocal ・・・" の2つに展開される。
2.そのそれぞれについて、再度エイリアスの処理がおこなわれるため、kikuchi に展開されたものが、もう1度 kikuchi と "| /usr/lib/mh/slocal ・・・" の2つに展開される。
3.さらに同じことが繰り返される。

実際には sendmail によってループの存在が検出され、このエイリアス設定自体が無効扱いになるので、不幸なループ事故は起こらずにすみます。しかし、エイリアスが無効になるため、結局 slocal は1回も起動しません。こういう場合はつぎのようにします。


\kikuchi, "| /usr/lib/mh/slocal -user kikuchi"

 先頭に"\"を付けると、そのアドレスについてはそれ以上エイリアスの展開がなされません。これにより、はじめの目標が達成されます。

必須エイリアス

 sendmail では、以下の2つのメールアドレスに対するエイリアスを必ず定義しなくてはなりません。

●Postmaster:
RFC822 の要請に従って、すべてのサイトは Postmaster というメールアドレスを受理する必要があります(大文字、小文字の違いは意味をもちません)。このアドレスは、そのサイトに関するメールの事故を別のサイトの人間が発見したときに、その旨を通知する目的で使うものです。したがって、エイリアス・ファイルでは、Postmaster に管理者のアドレスを対応させておきます。複数のアドレスでもかまいません。

●MAIL_DAEMON:
sendmail は、エラーメールを発行する際に、そのメールヘッダの From: 以下に MAIL_DAEMON という文字列(マクロnの値)を付加します。メールについて詳しくないユーザが万一 "エラーメールに返信" をしてしまった場合に備えて、MAILER-DAEMON 宛のメールを受理さえできればいいので、極端な例としては /dev/null にエイリアスしてしまってもよいでしょう。もちろん、Postmaster にエイリアスしてもかまいません。

 必須ではないのですが、root や daemon といった管理アカウントについても、適切な人間が読めるようにエイリアス定義をおこなっておくべきでしょう。ほかのサーバーソフトを運用する場合にも、サーバーごとに管理者用のエイリアスを作る場合がよくあります。たとえば、ニュースサーバーのINNの場合には usenet とnews のエイリアスを定義し、WWWのキャッシュ・サーバーのSquid ならば squid とか www-cache というアドレスを準備することになります。

プログラム起動の場合のユーザーID

 前述のように、エイリアス・ファイルでアドレスを指定する代わりにパイプ記号を用いると、プログラムを起動することができます。この場合、プログラム中からファイルを操作しますから、プロセスがどのようなユーザーIDで起動されるかが重要になります。これは、次のようになっています。

●aliases に直接記述する場合
ユーザー daemon
●:inclide: を利用する場合
そのファイルを所有するユーザー
●.forward に書かれた場合
その.forward ユーザー

エンベロープ送信人アドレスの自動設定

 メーリングリストを運営する場合、エイリアスを展開したあとで、その sendmail から各メンバーへとメールが送信されることになります。この際に配送エラーが起こった場合は、その通知先はもとのユーザーではなくメーリングリストのメンバーのアドレス登録を担当している人のほうが適切でしょう。
 これを実現するために、sendamil ではエイリアス・ファイルで次のような設定を使うことができます。例として、メーリングリストのアドレスを xxx-ml とします。


xxx-ml: :include: /usr/local/aliases/xxx-ml
owner-xxx-ml: postmaster

 このように書くと、xxx-ml 宛のメールがメンバーに配送される際、エンベロープでの送信人のアドレスは "postmaster" に設定されています(もちろん、実際の配送時には、さらにS1などの書換えルールに従ってドメイン名が補完されるなどの処理がなされます)。
 owner-xxx-ml 宛のメール自体がエラーになった場合には、sendmail はエラーメールを "owner-owner" というアドレスに配送します。ですから "owner-xxx-ml" などにはメーリングリスト個別の管理者のアドレスを設定し、owner-owner は sendmail 全体の管理者(すなわち、postmaster が該当します)にするのがよいでしょう。


メール配送系の構築

ハブホストの利用

 サイト内のユーザ数やホスト数などが増加してくると、サイトの内部をさらに複数のサブドメインに分けて運用したくなります。たとえば、ある会社において、最初は全体を1つのドメイン(kaisya.co.jp) で運用し、メールスプールも1台だけだったのが、ユーザが増えたので部ごとにサブドメインを準備し、メールスプールも各部ごとに確保したいようなときは、どのように設定すればいいのでしょうか。
 この場合、単純にメールスプールをサブドメインごとに準備すると、これまでuser@kaisya.co.jp といった形式のアドレスを利用していたユーザに対して、今後は user@xx-bu.kaisya.co.jp という形式のアドレスの利用を強いることになります。もちろん、ユーザ数が増えたのでユーザ名の衝突を避けるという目的で分割するのであればそれでもよいでしょう。しかし、たんにスプールの容量を自由に確保できるように分割する場合などは、従来のメールアドレスをそのまま利用し続けたいこともあります(もちろん、ユーザ名は従来どうり会社全体で一意となるような付け方をします)。
 そのときは、次のようなホスト構成を用います。

●従来の "会社全体でのメールスプール" を担当していたホスト(ここでは、ホスト名を hubhost.kaisya.co.jp とします)をハブホストにし、従来どおり kaisya.co.jp ドメインのMX(Mail eXchanger) とする。
●各部ごとに設けられたサブドメイン(xx-bu.kaisya.co.jp) に対応する部内ユーザ専用のメールスプールホストを1台ずつ準備し(ホスト名を spoolhost.xx-bu.kaisya.co.jp とする)、そのホストをxx-bu.kaisya.co.jp ドメインのMXとする。
●ユーザがどのホストから発信しても、従来どおり From: 以下に user@kaisya.co.jp が付くようにする。
●会社の外から user@kaisya.co.jp に出されたメールは hubhost.kaisya.co.jp に届くので、このホスト上で /etc/aliases か .forward を用いて、各部のスプールホストに転送する。

 このようにすると、メールスプールが分かれたこと以外は、従来と変わらない使用感をユーザに提供できます。
 ただし、従来は社内のユーザに対してはすべて user のみの(@以下がない)アドレスでメールを出せたのが、各部ごとにスプールホストを置いたために、他の部のユーザ宛のメールについてはドメイン部分を省略できなくなります。これは、宛先が他の部のユーザのメールはいったんハブホストに転送し、そこで /etc/aliases などの処理を施したのち各スプールホストに送ることで対処できます(これが、ハブホストと呼ばれる理由です)。ただし、この機能を用いた場合も、会社へのメールについてはハブホストを経由せず、直接スプールホストから配送されます。
 CFには、このような環境に対応するための設定変数として HUB_HOST が、ほかの関連する変数として REMOTE_USERS と NON_REMOTE_USERS があります。これを使った def ファイルの記述例を、"ハブホスト" "(各部の)スプールホスト" "その他のホスト" の3種類に分けて、下に示します。

ハブホストのdefファイル

 CF_TYPE=R8V8
 OS_TYPE=bsd4.4
 FROM_ADDRESS='$m'
 ACCEPT_ADDRS='$m'
 BITNET=auto
 LOCAL_HOST_DOMAIN='kaisya.co.jp'
 ALLOW_RELAY_TO='kaisya.co.jp'


スプールホストのdefファイル(ハブホストを用いる構成)

 CF_TYPE=R8V8
 OS_TYPE=bsd4.4
 FROM_ADDRESS='xx-bu.kaisya.co.jp'
 RECIPIENT_GENERIC=yes
 ACCEPT_ADDRS='$m'
 ACCEPT_LOWER=yes
 LOWER_MATCH_STYLE=any
 SPECIAL_FROM='kaisya.co.jp'
 SPECIAL_USERS='/etc/mail/users-in-kaisya'
 HUB_HOST='hubhost.kaisya.co.jp'
 REMOTE_USERS='/etc/mail/users-in-kaisya'
 NON_REMOTE_USERS='/etc/mail/users-in-bu'
 RELAY_LOCAL_TO_HUBHOST=no
 LOCAL_STICKY=yes
 BITNET=auto
 PRIVACY_FLAGS='goaway'
 LOCAL_HOST_DOMAIN='xx-bu.kaisya.co.jp'
 ALLOW_RECIPIENT_DOMAIN='xx-bu.kaisya.co.jp'


その他のホストのdefファイル(ハブホストを用いる構成)

 CF_TYPE=R8V8-null
 OS_TYPE=bsd4.4
 SPOOL_HOST='spoolhost.xx-bu.kaisya.co.jp'
 CHECK_HOST_ALLOW=127.0.0.1
 CHECK_HOST_ALLOW=127.0.0.1
 LOCAL_RELAY_DEFAULT=deny

 この設定では、各部用のスプールホスト(spoolhost.xx-bu.kaisya.co.jp) 上に、/etc/mail/users-in kaisya と /etc/mail/users-in-bu というファイルを準備する必要があります。前者にはすべての社内ユーザを記述し、後者に自部のユーザを全て記述します。(以下)


/etc/mail/users-in-kaisya の例

 taro
 kikuchi
 hattori
 aikawa
 watanabe
 abe


/etc/mail/users-in-bu の例

 kikuchi
 aikawa
 watanabe

 これらのうち、users-in-kaisya ファイルのメンテナンスが面倒かもしれません。これについては、ハブホストの aliases ファイルをもとに useres-in-kaisya ファイルを作成するスクリプトを作り、定期的に実行動作するようにすれば管理が楽になります。
 また、このファイルはユーザがドメイン名を省略したメールアドレスを用いた場合にのみ利用されますから、ドメイン名を省略せずに user@kaisya.co.jp としていれば、users-in-kaisya ファイルに該当アドレスの記述がなくても大丈夫です。
 以上のような設定の特徴として、第1に、spoolhost.xx-bu.kaisya.co.jp の /etc/aliases を部ごとに自由に設定できます。これにより、部ローカルのメーリングリストなどを自由に作成できます。このメーリングリストに対して部外からメールを送る場合には、当然ながら ML@xx-bu.kaisya.co.jp など、サブドメインの名前を含めたドメイン名を指定する必要があります。
 第2に、部内のローカルユーザに宛てたメールはいちいちハブホストを経由せずにスプールホスト内で処理されますから、ハブホストの負担を減らすことができます。また、ハブホストがダウンしていても部内での連絡には影響が出ません。
 第3に、From: や To: フィールドでドメイン名が省略された場合には次のような補完パターンがとられます。

●各ホストのLOCAL_ADMIN_USERS(デフォルトで設定されている変数)に該当するユーザ名については、かならずFQDNが補完される。
●スプールホストの /etc/mail/users-in-kaisya で設定したユーザ名については、部外にメールが出ていく際に、SPECIAL_FROM で指定したドメイン名が補完される。
●ユーザ名がそれ以外の文字列の場合には、部外にメールが出て行く際に、FROM_ADDRESS で指定したドメイン名が補完される。こうすると、部ローカルのメーリングリストなどで誤って kaisya.co.jp が補完されることがなくなる。

 各サイトの事情に合わせて、これらの変数を適切に設定してください。
 また、この設定を利用するには、sendmail.cf に合わせて DNS の側も適切に設定する必要があります。具体的には次のような設定をおこないます。

●kaisya.co.jp に対する MXレコードは、ハブホスト hubhost.kaisya.co.jp に向ける。
xx-bu.kaisya.co.jp に対する MX は、スプールホスト spoolhost.xx-bu.kaisya.co.jp に向ける。
xx-bu 内の他のホスト(other.xx-bu.kaisya.co.jp )に対する MX は、すべてスプールホスト spoolhost.xx-bu.kaisya.co.jp に向ける。

 この設定に用いる場合に限らず、ホストのIPアドレスをDNSに登録する(つまり、Aレコードを記述する)なら、そのすべてについて MXレコードも設定するようにしましょう。現状の sendmail は、受信人アドレスのドメイン名部分に対応する MXレコードがみつからなければAレコードを見て配送をおこなうようになっています。しかし、これは過去との互換性を保つための仕様だと考えて、MXレコードはかならず設定すべきでしょう。
 また、DNSにはワイルドカードMXレコードという仕組みも存在します。しかし、これはAレコードが存在するホストには適用されないので、ホストごとのMXレコードの記述をサボる目的で用いることはできません。一般に、防火壁内部のホスト構成を完全に隠したといった事情がないかぎり使うべきではないでしょう。

ハブホスト構築の利点(セキュリティの確保)

 ところで、外部からのメールはハブホストが受信し、そのあとでスプールホストに転送されるので、スプールホスト自体は外部からのメールを直接受け取れなくてもかまいません(ただし、部ローカルのメーリングリストに外部からメールを送れるようにする必要があるのなら、この限りではありません)。つまり、MXとして外部に公開するホストと、メールスプールをもつホストを区別することができます。
 メールスプールをもつホストは、ユーザのメールという機密情報や、POPのパスワードのデータベースなどを保持しているはずなので、防火壁内部に隠して外部からの攻撃をうけにくくしたいところです。外部に公開すべきなのはMXだけであり、スプールホストはかならずしも公開しなくてもよいという点に着目すれば、サイトのセキュリティレベルを上げることができます。
 また、メールの不正リレーに関する問題が発生するのも、内部から外部に送り出す際に通過するホストと、外部からのメールを受け取るホストが区別されていないためです。"送信時の中継専用ホスト" と "受信専用ホスト" を独立させてしまえば、前者は外部からのSMTP接続を受ける必要はなくなり、後者は自分が受信する以外のメールをすべてエラーにしてしまってもよいのです。
 具体的に考えてみます。ます、防火壁担当のルータにIPフィルタリングの機能があるなら、スプールホストを防火壁内に入れ、外部からスプールホストに向けたTCPコネクション確立要求のパケットを落とすようにしておくと、"スプールホストから外部に向かうSMTP接続は可能だが、逆は不可能" という状態を作りだせます。
 部単位で防火壁を設けているような場合、ハブホストは防火壁外に置くことになるでしょうから、ハブホストからのSMTPコネクション確立要求はすべて落としてしまう設定にします。
 このようにすると、スプールホストが "送信時の中継専用ホスト" として機能し、ハブホストが "外部からのメールを受信するためのMXホスト" として機能します。
 防火壁内部のホスト(ハブホストを除く)は外界から遮断されますから、sendmail 側でメールの不正リレー対策を行わなくても十分に安全性が確保されます。これは、MTAとして sendmail 以外のツールを使う場合にも有効な手法だと思われます。
 また、複数台のハブホストを用意し、同一の優先度のMXレコードを各ハブホストに向けるようにしておけば、メール処理の不可分散ができます。同一の優先度のMXレコードがある場合は、送信側が接続の失敗を検出して他のMXレコードを利用してくれますから、障害にも強くなります。
 これは、user@kaisya.co.jp 宛のメールがどのハブホストに届いたとしても "ローカル宛" として処理するような sendamil.cf を作り、それぞれのハブホストに同一の aliases データベースを持たせることで実現できます。

端末型ダイヤルアップ環境

 個人で複数のPCを所有し、家庭内にLANを構築している方も多いでしょう(実は私もその1人ですが)。その場合、外部との接続は個人用の端末型ダイヤルアップの契約で、NATやIPmasquerade などを利用することが多いのではないでしょうか。
 この場合、外部との電子メールのやりとりに関しては、ISP(Internet Service Provider) のSMTPサーバやPOPサーバにMUAから直接接続して利用するのが簡単です。しかし、外部と接続していない状態でメールをゆっくり書きたいこともあるでしょう。これは、MUAが「送信トレイ」のような機能をサポートしていれば簡単ですが、UNIX系のOSで動くMUAでは、sendmail のキュー処理機構に頼っている(つまり、メールを書き終わった時点で、すぐにMUAからMTAへの送信をおこなう)ものが多いようです。こういったMUAを使う場合、SMTPサーバとしてISP上のホストを用いる設定では、メールを書き終わって送信する際にはISPと接続されている必要があります。
 そこで、次のような設定例を紹介します。

●LAN内にスプールホストを1台準備し、LAN内のMUAはメール送信時にはそのホストに対して送信するように設定する。
●LAN内のホストに仮のドメイン名を付けて運用している場合、LAN内から発信されたメールにそのドメイン名が付いてしまっても大丈夫なように、LANから外部に発信する際に正規のメールアドレスに合わせて From: などを書き換える。
●スプールホスト以外のホストでは、スプールホストに転送するように設定(null-v8.def を利用) し、送信時に /usr/lib/sendmail を起動するMUAに対応する。
●これらのホストは外部からのSMTP接続を受ける必要はないので、LAN内からの接続のみを受け付けるようにしておく。ここでは、LAN内のホストのIPアドレスは 192.168.0.x の範囲で付けているとする。
●念のため、Message-ID はISPのメールサーバに付けさせることにする。

 この場合の def ファイルの設定例を下に示します。


スプールホストのdefファイル(ダイヤルアップ環境)

 CF_TYPE=R8V8
 OS_TYPE=bsd4.4
 FROM_ADDRESS='$m'
 RECIPIENT_GENERIC=yes
 REWRITE_GENERIC_FROM=lower
 REWRITE_GENERIC_TO=lower
 ACCEPT_ADDRESS='$m'
 ACCEPT_LOWER=yes
 LOWER_MATCH_STYLE=any
 ALWAYS_APPEND_DOMAIN=yes
 SMTP_MAILER_FLAG_SUB='M'
 ESMTP_MAILER_FLAG_SUB='M'
 SMTP8_MAILER_FLAG_SUB='M'
 BITNET=auto
 DIRECT_DELIVER_DOMAINS='$m'
 DEFAUT_RELAY='smtp:smtpserver.provider.ne.jp'
 USERTABLE_MAPS='local=hash:/etc/ut.local'
 USERTABLE_LOCAL_REWRITE=yes
 CHECK_HOST_ALLOW=192.168
 CHECK_RELAY_DEFAULT=deny
 LOCAL_HOST_IPADDR=192.168
 


その他のホストのdefファイル(ダイヤルアップ環境)

 CF_TYPE=R8V8-null
 OS_TYPE=bsd4.4
 SPOOL_HOST=spoolhost.private-network.jp
 SMTP_MAILER_FLAG_SUB='M'
 ESMTP_MAILER_FLAG_SUB='M'
 SMTP8_MAILER_FLAG_SUB='M'
 RELAY_MAILER_FLAG_SUB='M'
 CHECK_HOST_ALLOW=192.168
 CHECK_RELAY_DEFAULT=deny
 LOCAL_HOST_IPADDR=192.168
 

 LAN内では private-network.jp といった仮のドメイン名を付けていたとすると、スプールホストの名前は spoolhost.private-network.jp のようになります。これを SPOOL_HOST として設定します。
 スプールホストの設定では、契約したISPのSMTPサーバ名に従って、DEFAULT_RELAY を指定します。そして、LAN内で用いているユーザ名から ISP でのメールアドレスへの書換えを、CFの usertable の機能を用いて実現しています。この対応表は /etc/ut.local というファイルに記述したのち(下参照)、適切な形式のデータベース・ファイルに変換します。


/etc/ut.local の例

 yoshimoto:mailname     kikuchi@provider.ne.jp
  

 この例では、USERTABLE_MAPS に hash 形式のデータベースを利用する設定をおこなっているので、次のように makemap コマンドを用いて hash形式で /etc/ut.local/db というファイルを作ります。

 % /bin/su
 # cd /etc
 # makemap hash ut.local.db <ut.local
 # chown root ut.local.db
 # chmod og-w ut.local.db
 

 makemap コマンドは、sendmail の配布パッケージに含まれる makemap ディレクトリ以下にあるので、OSに添付されていなければこれを利用してください。

fetchmailの利用
 このようにLAN内でメールシステムを作った場合、LAN内のホストどうしでメールのやりとりができます。それらのメールはLAN内のスプールホストに蓄えられます。これに対し、外部からのメールはISP上のPOPサーバから拾う必要があります。
 このような状況で、POPサーバから取ってきたメールをローカルのメールスプールに交ぜてしまえば、MUAからはローカルスプールのみを参照すればいいので、設定が簡単になります。このような動作をしてくれるツールとして、fetchmail があります。
 このソフトウェアは、http://www.tuxedo.org/~esr/fetchmail/で公開されています。ftp://ftp.win.or.jp/pub/network/mail/fetchmail/でもアーカイブのみのミラーをおこなっているようです。
 現在も頻繁にバージョンアップされているので、詳細の解説は省いて簡単に説明します。ユーザのホーム・ディレクトリに .fetchmailrc という名前で下のようなファイルを準備しておき、そのユーザがメールを拾いたいと思ったときにコマンドラインから fetchmail を起動すると、POPサーバから取ってきたメールをローカルにスプールしてくれます。poll で POPサーバ名を指定し、user と pass には、ISPのPOPサーバでのユーザ名とパスワードを指定します。

.fetchmailrc の例

 defaults protocol pop3
  no mimedecode
 # isp isp rules
 poll popserver.provider.ne.jp
  user kikuchi pass syoucyan


 動作原理としては、fetchmail は指定されたPOPサーバからメールを取ってきたあと、エンベロープの受信人として fetchmail を実行したユーザ名(@以下がないもの)を設定したうえでローカルのSMTPサーバに接続して引き渡すだけです。実際にスプールをおこなう作業は sendmail などに任されるので、sendmail.cf などは適切に設定する必要があります。
 この際、エンベロープの受信人に設定されるユーザ名としては、環境変数 USER があればその内容を利用し、なければ環境変数 LOGNAME を、それもなければ実効 UID からパスワード・ファイルを利用して決定する仕組みになっているようです。
 毎回 fetchmail コマンドを実行するのが面倒ならば、次のような行を .fetchmailrc に追加すると、デーモンモードとして動作し、300秒ごとにPOPサーバをチェックしてくれるようになります。

 set daemon 300


一つ前へ