sendmailについて



sendmail起動時の注意事項

 Red Hat Linuxの場合デフォルトで提供されているsendmail.cfを利用した場合、sendmailを起動してもリモートから受け付けない設定になっているので、sendmail.cfの以下の行を
  O DaemonPortOptions=Port=smtp,Addr=127.0.0.1, Name=MTA
という行を
  O DaemonPortOptions=Port=smtp,Addr=0.0.0.0, Name=MTA
に変更して下さい。または、sendmail.mcファイルの
  DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')
という行を
  DAEMON_OPTIONS(`Port=smtp,Addr=0.0.0.0, Name=MTA')
に変更して、
  # m4 sendmail.mc > sencmail.cf
  # mv sendmail.cf ../
として、sendmail.cfを再構築してもかまいません。

設定ファイル

 ここで、sendmailの設定ファイルの種類やロケーション、設定ツールについて見ておきます。

設定ファイルのロケーション

 sendmailはさまざまな環境で開発が行われたため、同様の機能の設定ファイルでも、その名前が環境によって異なっていました。これは、複数システム上で動くsendmailをメンテナンスする際などには混乱の元となっていました。そのため、sendmail 8.10で統一したディレクトリ構成が定められ、デフォルトではすべての設定ファイルが/etc/mail以下に置かれるようになりました。
 sendmail関連する設定ファイルを作成する際には、必ず/etc/mailに置くようにしましょう。

代表的な設定ファイル

sendmail.cf
 sendmailの動作を決める設定ファイルです。非常に複雑な構造で一種のプログラミング言語のようなもので記述されています。sendmailが起動すると、まずこのファイルが読み込まれます。sendmail.cfには、それぞれの設定ファイルの名前や場所が記述されています。通常は、このファイルは直接編集せず、cfやWIDE CFなどの設定ツールを使って設定します。

aliases
 メールアドレスの別名を指定します。aliasesではドメイン名を解釈しません。メールアドレスのアカウント名の部分のみで配送先を決定します。
 .dbファイルを作成するには、以下のようにして下さい。
  # /usr/sbin/makemap hash /etc/mail/aliases < /etc/mail/aliases
relay-domains
 リレーを許可するドメイン名を指定します。

access
 リレーを許可するドメイン名を指定します。relay-domainsよりも、より柔軟な指定が可能です。ドメイン名以外にもメールアドレスでの制限も可能です。
 .dbファイルを作成するには、以下のようにして下さい。
  # /usr/sbin/makemap hash /etc/mail/access < /etc/mail/access
mailertable
 特定ドメインの経路を上書きする指定を行います。この機能により、特定のドメインやユーザだけ、デフォルトのメーラ(メール配信エージェント)から別の有効な内部のメーラに変更するように指定できます。
 設定は、1行に1つ、左にホスト名やドメイン名の一部を、右にメーラに続けて「:(コロン)」、IPアドレスやホスト名を記述する場合もあります。
  1:  hoge.com     smtp:[222.111.100.101]
  2:  .hoge.co.jp  smtp:mail.hoge.ne.jp
 メーラには、sendmail.mcで記載している
  MAILER(smtp)dnl
の括弧内のメール転送エージェントを指定します。
 上記例の1行目は、ドメインhoge.com宛のメールをsmtpメール転送エージェントで、IPアドレス222.111.100.101へ転送する設定です。
 2行目は、.hoge.co.jpのホスト、例えば、sale@kobe.hoge.co.jp宛のメールなどをsmtpメール転送エージェントで、ホストmail.hoge.ne.jpへ転送する設定です。
 1行目のように、IPアドレスやホストを「[」と「]」で囲むと、そのホストやアドレスに対してはDNSサーバーのMXレコード(メールサーバーに対する設定)を参照しないでAレコードのアドレスに向けて転送されます。このようにする理由は、設定が不完全な場合にMXループ(MXレコード参照を限りなく繰り返してしまうような現象)を引き起こしてしまうからです。
 設定行の左に来るホスト名やドメイン名で、部分的に一致する設定を記述した場合、例えば、
  *1:  .hoge.co.jp      smtp:[222.111.100.101]
  *2:  kobe.hoge.co.jp  smtp:mail.hoge.ne.jp
のような場合は、より一致する部分が多い方が優先されます。ですので、上記の設定では、sale@kobe.hoge.co.jp宛のメールは*2行目が適用されます。
 .dbファイルを作成するには、以下のようにして下さい。
  # /usr/sbin/makemap hash /etc/mail/mailertable < /etc/mail/mailertable
domaintable
 ドメイン名のマッピングを提供します。この機能により、ドメイン名が変更になった際、自動的にドメイン名を変更することができます。

virtusertable
 ドメインごとに同じアカウント名のメールアドレスを発行するときに使います。そうすることで、1台のマシンを複数のバーチャルドメインのホストとして機能させることができます。
 .dbファイルを作成するには、以下のようにして下さい。
  # /usr/sbin/makemap hash /etc/mail/virtusertable < /etc/mail/virtusertable
local-host-names
 ホスト名のすべてのエイリアス(別名)を格納しています。このファイルに記述してあるホスト名のメールアドレス宛のメールを受け取ります。user@hoge.comというメールアドレス宛のメールを受け取りたい場合は、hoge.comと指定します。

 これらの設定ファイルの中で最も重要なsendmail.cf、そしてaliasesファイルについて、もう少し詳細を見ておきます。

sendmail.cf

 sendmailの動作を決めるもっとも大切な設定ファイルです。sendmailが起動すると、まず、このファイルが読み込まれます。sendmail.cfには、それぞれの設定ファイルの名前や場所が記述されています。
 sendmail.cfでどのような設定ファイルが指定されているかを調べるには、以下のようにします。grepの-nオプションは行数を出力するオプションです。
  # grep -n / /etc/mail/sendmail.cf
  20:##### in /usr/src/build/308253-i386/BUILD/sendmail-8.12.8/cf/cf
  21:##### using ../ as configuration include directory
  30:#####  $Id: cfhead.m4,v 8.108.2.1 2002/08/27 20:19:08 gshapiro Exp $  #####
  31:#####  $Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp $  #####
  33:#####  $Id: linux.m4,v 8.13 2000/09/17 17:30:00 gshapiro Exp $  #####
  37:#####  $Id: local_procmail.m4,v 8.21.42.1 2002/11/17 04:25:07 ca Exp $  #####
  40:#####  $Id: no_default_msa.m4,v 8.2 2001/02/14 05:03:22 gshapiro Exp $  #####
  42:#####  $Id: smrsh.m4,v 8.14 1999/11/18 05:06:23 ca Exp $  #####
  44:#####  $Id: mailertable.m4,v 8.23 2001/03/16 00:51:26 gshapiro Exp $  #####
  46:#####  $Id: virtusertable.m4,v 8.21 2001/03/16 00:51:26 gshapiro Exp $  #####
  48:#####  $Id: redirect.m4,v 8.15 1999/08/06 01:47:36 gshapiro Exp $  #####
  50:#####  $Id: always_add_domain.m4,v 8.11 2000/09/12 22:00:53 ca Exp $  #####
  52:#####  $Id: use_cw_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp $  #####
  55:#####  $Id: use_ct_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp $  #####
  58:#####  $Id: local_procmail.m4,v 8.21.42.1 2002/11/17 04:25:07 ca Exp $  #####
  60:#####  $Id: access_db.m4,v 8.24 2002/03/06 21:50:25 ca Exp $  #####
  62:#####  $Id: blacklist_recipients.m4,v 8.13 1999/04/02 02:25:13 gshapiro Exp $  #####
  64:#####  $Id: accept_unresolvable_domains.m4,v 8.10 1999/02/07 07:26:07 gshapiro Exp $  #####
  67:#####  $Id: proto.m4,v 8.649.2.14 2002/12/30 15:46:02 ca Exp $  #####
  70:V10/Berkeley
  91:Fw/etc/mail/local-host-names
  120:FR-o /etc/mail/relay-domains
  151:Kmailertable hash -o /etc/mail/mailertable.db
  154:Kvirtuser hash -o /etc/mail/virtusertable.db
  159:Kaccess hash -T -o /etc/mail/access.db
  179:O AliasFile=/etc/aliases
  199:# error message header/file
  200:#O ErrorHeader=/etc/mail/error-header
  221:O HelpFile=/etc/mail/helpfile
  233:O ForwardPath=$z/.forward.$w:$z/.forward
  272:# Use as mail submission program? See sendmail/SECURITY
  306:O QueueDirectory=/var/spool/mqueue
  360:O StatusFile=/etc/mail/statistics
  372:O UserDatabaseSpec=/etc/mail/userdb.db
  410:# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others)
  411:#O ServiceSwitchFile=/etc/mail/service.switch
  413:# hosts file (normally /etc/hosts)
  414:#O HostsFile=/etc/hosts
  423:#O SafeFileEnvironment=/arch
  432:O SmtpGreetingMessage=$j Sendmail $v/$Z; $b
  447:O OperatorChars=.:%@!^/[]+
  461:#O DeadLetterDrop=/var/tmp/dead.letter
  486:#O ControlSocketName=/var/spool/mqueue/.control
  489:#O MaxMimeHeaderLength=0/0
  498:#O PidFile=/var/run/sendmail.pid
  516:#O DefaultAuthInfo=/etc/mail/default-auth-info
  543:# DHParameters (only required if DSA/DH is used)
  545:# Random data source (required for systems without /dev/urandom under OpenSSL)
  568:Ft/etc/mail/trusted-users
  580:	$.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}
  675:# check for IPv4/IPv6 domain literal
  1073:###  check_relay -- check hostname/address on SMTP startup
  1243:R$* $| $# $+		$# $2			error/ok?
  1271:### Relay_ok: is the relay/sender ok?
  1393:###	<+ TAG>	lookup with and w/o tag
  1641:#####  $Id: smtp.m4,v 8.64 2001/04/03 01:52:54 gshapiro Exp $  #####
  1677:R$+			$: $>PseudoToReal $1
                                sender/recipient common
  1688:R$+			$: $>PseudoToReal $1
                                sender/recipient common
  1696:R$+			$: $>PseudoToReal $1
                                sender/recipient common
  1713:Msmtp,		P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP,
                        R=EnvToSMTP, E=\r\n, L=990,
  1714:		T=DNS/RFC822/SMTP,
  1716:Mesmtp,		P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP,
                        R=EnvToSMTP, E=\r\n, L=990,
  1717:		T=DNS/RFC822/SMTP,
  1719:Msmtp8,		P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP,
                        R=EnvToSMTP, E=\r\n, L=990,
  1720:		T=DNS/RFC822/SMTP,
  1722:Mdsmtp,		P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP,
                        R=EnvToSMTP, E=\r\n, L=990,
  1723:		T=DNS/RFC822/SMTP,
  1725:Mrelay,		P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP,
                        R=MasqSMTP, E=\r\n, L=2040,
  1726:		T=DNS/RFC822/SMTP,
  1734:#####  $Id: procmail.m4,v 8.22 2001/11/12 23:11:34 ca Exp $  #####
  1736:Mprocmail,	P=/usr/bin/procmail, F=DFMSPhnu9, S=EnvFromSMTP/HdrFromSMTP,
                        R=EnvToSMTP/HdrFromSMTP,
  1737:		T=DNS/RFC822/X-Unix,
  1745:#####  $Id: local.m4,v 8.58 2000/10/26 01:58:29 ca Exp $  #####
  1786:Mlocal,		P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL,
                        R=EnvToL/HdrToL,
  1787:		T=DNS/RFC822/X-Unix,
  1789:Mprog,		P=/usr/sbin/smrsh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL,
                        R=EnvToL/HdrToL, D=$z:/,
  1790:		T=X-Unix/X-Unix/X-Unix,
 また、これを見ると、設定ファイルが単なるテキストファイルなのか、ハッシュになっているのかも分かります。
 例えば、
  Kaccess hash -T -o /etc/mail/access.db
のように、“hash”と指定されている場合は、ハッシュ形式のデータベースを利用しています。hasuを利用するにはBakerleyDB が必要です。“dbm”と指定されている場合は、DBM形式のデータベースを利用しています。dbmを利用するには、NDBMがインストールされている必要があります。
 逆に、
  Fw/etc/mail/local-host-names
のように、“hash”と指定されていなければ、テキストファイルで指定されています。
 テキストファイルで指定されている設定ファイルは、sendmailの起動時に一度だけ読み込まれます。そのため、テキストファイル形式の設定ファイルを変更した場合は、必ずsendmailを再起動する必要があります。設定ファイルがデータベースファイルの形式である場合は、sendmailを再起動する必要はありません。

aliasesファイル
 aliasesファイル(エイリアスファイル)は、もっとも古典的なアカウント名のマッピングを提供するファイルです。転送メールアドレスなどを定義することもできます。転送メールアドレス以外にも、いくつかの方式をサポートしています。詳細は転送設定を参照して下さい。
  # 必須なエイリアス
  postmaster:	root
  MAILER-DAEMON:	postmaster
  # 一般的なエイリアス
  kanami:		tatu,nozomi
  nozomi:		outside@foobar.jp
  sakura:		outside@foobar.jp
  m1:		|/usr/local/fml/fml.plxxx
  ml2:		:include:/home/neko/members.txt
 aliasesファイルには、必ずpostmasterとMAILER-DAEMONの定義が必要です。postmasterには、メール関連プログラムからのメールが送られてきます。また、メール配信ができなかった(バウンス)際は、常に、MAILER-DAEMONからのメールとして、送信元に送り返します。
 MAILER-DAEMONの定義がされていないと、もし、送信元に送り返したエラーメッセージがバウンスメールになった場合、また戻ってくる宛先がないため、デッドレター(配信できないメール)となってしまいます。

キューディレクトリ

 sendmailはメールの送信を直列で送信します。そのため、メールが順番待ちのため、すぐに配送できない場合があります。配信できない理由は、順番待ちの他にも配送先サーバのダウン、一時的なディスク容量の問題などがあります。そのような場合は、いったんキューディレクトリにメールを保存して、配信されるのを待ちます。
 キューディレクトリがどこにあるかわからない場合は、以下のようにして調べます。
  #grep -n QueueDirectory /etc/mail/sendmail.cf
  263:O QueueDirectory=/var/spool/mqueue
 パスはOSごとに異なりますが、このようにsendmail.cfのQueueDirectoryを探すと見つけることができます。なお、このディレクトリは必ず絶対パスで指定されている必要があります。
 キューに保存されたメールは指定された時間ごとに再度処理され、再送できないか試みます。メールキューにキューがたまっているかどうかをチェックするにはmailqコマンドを使います。
  # mailq
  /var/spool/mqueue (2 requests)
  ----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------
  fBVKnEH31246      795 Tue Jan  1 05:49 <kanammi@othehost.or.jp>
                                         <sakura@hoge1.co.jp>
  fBSC0JH28447      536 Fri Dec 28 21:00 <xxxx@mobilesite.co.jp>
キューディレクトリのパーミッション
 キューディレクトリは、所有者を「root」、パーミッションを「700」にするべきです。そうしないと、第三者にキューファイルを読まれてしまったり、あるいはキューファイルを削除されたりする恐れがあります。また、キューファイルを不正に生成することにより、スパムメールの送信なども可能になってしまいます。そのため、キューディレクトリのパーミッションには十分気をつけなければなりません。キューディレクトリのパス上のディレクトリは、すべて所有者をrootとし、root以外が書き込みパーミッションを持たないように設定しておくべきです。

sendmailの設定ツール

 sendmailの設定ツールには、日本でよく使われてきた「WIDE CF」とsendmailに標準で付いてくる「cf」の2つがあります。WIDE CFでは、WIDEプロジェクトで開発された日本製のsendmail設定ツールです。日本国内では、長らくWIDE CFが利用されてきましたが、WIDE CFが1998年より更新が停止しており、今後、sendmailがバージョンアップしていくにしたがって利用できなくなる可能性も出てきました。実際、WIDE CFの更新が停止されたあと追加されたSMTP認証などの機能は、WIDE CFを使って設定することはできません。今後のことを考え、sendmail標準装備のcfを利用した設定について解説していきます。

cf

 cfは、sendmailに標準でついている設定ツールです。WIDE CFに比べて比較的短い設定ファイルで設定が可能なのが特徴です。世界中で使われているので、ドキュメントが非常に充実しています。/usr/share/sendmail-cf/ディレクトリにあるREADMEファイルも大変詳しく解説されています。
 また、/usr/share/sendmail-cf/READMEの日本語訳のプロジェクトも進んでいます。現在では、その大部分の訳が完成しています。
   cf プロジェクト(仮称)
   ・・・cf/READMEの日本語化を進めているプロジェクトです

   cf/README
   cf/READMEの日本語化プロジェクトの成果物をより見やすい形で提供してくれています。

WIDE CF

 WIDEプロジェクトの成果であるWIDE CFは、日本では標準的なsendmailの設定ツールとして多くの人に慣れ親しまれてきました。以下のサイトより、まだダウンロードが可能です。最新バージョンは、CF-3.7Wpl2(sendmail 8.9対応)です。sendmail 8.12でも、一部を書き換えれば使えるようです。なお、WIDE CFに関しては、日本語の書籍やMANUAL.jpnなと詳しい解説書もあるので、今回は取り上げません。
   ftp://ftp.st.ryukoku.ac.jp/pub/network/mail/CF/

設定のポイント

 sendmialを設定する上でポイントとなるのは、以下のような点でしょう。
   不正リレーに関する対策
   複数ドメイン対応
 不正リレー対策としては、accessデータベースやPOP before SMTP、SMTP認証(SMTP AUTH)などが存在します。複数ドメイン対応としては、まず、受信するドメインを設定できるようにすること、infoというアドレスを複数ドメインで発行できるようにすることなどが主なポイントとなります。

メール配信エージェント

 sendmailの仕事は、メールを送信先に送り届けることです。送り届けるためには、そのためのプログラムが必要です。それをメール配信エージェント(MDA:Mail Delivery Agent)を呼びます。sendmailでは、メーラ(MAILER)と呼ばれることがありますが、クライアントのメールソフトとは意味が違うことに注意して下さい。インターネットメールサーバでは、大きく分けて2つのメール配信エージェントが定義されています。
 sendmail.cfのMで始まる行を調べてみます。
  # grep ^M /etc/mail/sendmail.cf
  Msmtp,          P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP,
                  E=\r\n, L=990,
  Mesmtp,         P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP,
                  E=\r\n, L=990,
  Msmtp8,         P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, 
                  E=\r\n, L=990,
  Mdsmtp,         P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP,
                  E=\r\n, L=990,
  Mrelay,         P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP,
                  E=\r\n, L=2040,
  Mprocmail,      P=/usr/bin/procmail, F=DFMSPhnu9, S=EnvFromSMTP/HdrFromSMTP,
                  R=EnvToSMTP/HdrFromSMTP,
  Mlocal,         P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL,
                  R=EnvToL/HdrToL,
  Mprog,          P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL,
                  R=EnvToL/HdrToL, D=$z:/,
 ここで出てきたのが、登録されている配信プログラムです。ここでは折り返されていますが、先頭に“M”があるのが行頭です。“M”のあとにあるのがメール配信エージェント名となります。
 “M”で始める行(M行)には、sendmailで利用するメール配信エージェント(メーラ)が定義されています。
 Msmtp行からMrelay行までは、sendmailに直接組み込まれています。これら、TCP/IPを使用したネットワークでメールを配信する機能です。
 その下のprocmail、local、progは、ローカルメールを配信するための機能です。ここでは、procmailメーラとlocalメーラには/usr/bin/procmailが指定されています。procmailは、非常に多機能なメールフィルター用プログラムです。localメーラは、メールをユーザのメールボックスに追加する際に使用するプログラムを指定します。progメーラには、配信を処理するほかのプログラムを起動する際に使用するプログラムを指定します。ここでprogメーラに指定しているsmrshは、不用意に任意のプログラムを起動できないように制限することができる、sendmailと同時に配布されているプログラムです。
 この他にも、UUCP接続で利用する配信プログラムやFAX接続などの配信プログラムも存在します。

ホスト内でメールを配信する仕組み

 外部のホストから自ホストのユーザ宛にメールを受け取ったら、そのメールを該当するユーザのメールボックスに保存しなければなりません。この、sendmailから実際のメールボックスまでの配送を受け持つのが「ローカル配信エージェント(Local MDA:Local Mail Delivery Agent)」です。
 ローカル配信エージェントとして有名なのはprocmailです。procmailは、多くのサイトで動作しています。
   procmail.org
 ローカル配信エージェントは、設定によっては外部のホストへメールを転送することも可能です。感覚的に理解しにくいと思いますので、ローカル配信エージェントとその他のプログラムとの関係を次の図に示します。
  ┌──────────┐            ┌──────────────────────┐
  │┌────────┐│            │┌────────────────────┐│
  ││                ││    SMTP    ││                  MTA                   ││
  ││              <┼┼──────┼┼>            (sendmail)              ││
  ││                ││            │└────────────────────┘│
  ││                ││            │                       ∧  │         ∧    │
  ││                ││            │                       │  │         │    │
  ││                ││            │                       │  ∨         │    │
  ││      MUA       ││            │┌───────┐┌──────┐    │    │
  ││(メールソフト)││            ││   POPサーバ  ││ローカル配信│    │    │
  ││              <┼┼──────┼┼>(Qpopper) ││エージェント│    │    │
  ││                ││            │└───────┘└──────┘    │    │
  ││                ││            │          ∧        │                │    │
  ││                ││            │          │        │                │    │
  ││                ││            │          ∨        ∨                ∨    │
  ││                ││            │┌──────────┐          ┌───┐│
  │└────────┘│            ││   メールボックス   │          │キュー││
  │   クライアント     │            │└──────────┘          └───┘│
  │   コンピュータ     │            │                メールサーバ                │
  └──────────┘            └──────────────────────┘
sendmailの実行

 sendmailを実行するには、次のようにします。本文を書き、最後に[Ctl]+[D]キーを押します。すると、ローカルユーザのkanamiとsakuraにメールが配送されます。もちろんメールアドレスを指定することができます。
  #sendmail kanami,sakura
  (ここに本文を書く)
  [Ctl]+[D]
起動オプション

 sendmailは、起動時に“-”(ハイフン)で始まる引数を起動オプション(コマンドラインスイッチ)として認識します。代表的なコマンドラインスイッチを表にまとめました。なお、“-”で始まらない引数は、メールメッセージの送信先アドレスとみなされます。

スイッチ 説明
-b 動作モードを設定
-v 冗長メッセージ出力モードで実行
-d デバックモードで実行
-f $from メール送信時にエンベロープFromを指定する
-t メール送信時にメール本体に記述してあるFromやToをエンベロープ情報として採用する
-i メッセージの終了を表す“.”(ドット)を無効にする


 sendmailというと、デーモンとして常時起動していてメールを受け付けているという印象があるかもしれませんが、このように、その他にもいろいろな動作モードがあります。代表的なコマンドラインスイッチのうち、後半の3つのオプションは、プラグラムなどから起動する際によく利用されます。

-bによる動作モードの指定

 sendmailを起動する際に指定する-bオプションで動作モードを指定します。例えば、“-bd”として起動すれば、sendmailはデーモンモードとして起動し、SMTP接続を待ち受けます。また、“-bi”として起動すると、/etc/mail/aliasesを再構築して終了します。

スイッチ 説明
-ba ARPAnetプロトコルを使用する
-bD デーモンとして実行するが、制御端末を切り離さない
-bd デーモンとして実行する
-bH 配信先ホストごとの配信成否記録をクリアする(purgestat)
-bh 配信先ホストごとの配信成否記録を表示する(hoststat)
-bi エイリアスデータベースを再構築する(newaliases)
-bm メールの発信者になる
-bp キューを表示する(mailq)
-bs 標準入出力に対してSMTPを実行する
-bt テキストモード:メールアドレスの書き換えルールのテスト
-bv ベリファイモード:選択されている配信エージェントの確認


 これらのオプションのうちのいくつかは、別名のコマンド名を持っています(下記の表を参照)。“newalises”や“mailq”などはよく使うため、こちらの別名を使った方が便利です。

別名コマンド スイッチ 説明
purgestat -bH 配信先ホストごとの配信成否記録をクリアする
hoststat -bh 配信先ホストごとの配信成否記録を表示する
newaliases -bi エイリアスデータベースを再構築する
mailq -bp キューを表示する


デーモンモード(-bd)

 sendmailをデーモンモードで起動するには、-bdオプションを指定します。こうすることで、常時起動して送られてくるメールを受信したり、逆に、他のホストのメールを配送する機能を提供します。
 sendmailのデーモンモードによる起動は、
  sendmail -bd -q1h
とします。
 “-bd”で、デーモンモードで起動することを指定しています。“-q1h”はキューの処理方法についての指定です。キューに保存されたメールを1時間おきに処理するように指定しています。キューについては、キューの項目を参照して下さい。

起動しているsendmailの動作モードの確認
 現在起動しているモードが分からない場合は、sendmail.pidを参照してみましょう。2行目(最終行)に、現在の起動コマンドが記述されています。
  # tail -l /var/run/sendmail.pid
  1320
  /usr/sbin/sendmail -bd -q1h
 もし、sendmail.pidファイルの場所が分からない場合は、次のように調べます。
  # grep sendmail.pid /etc/mail/sendmail.cf
  #O PidFile=/var/run/sendmail.pid
 上の例では、コメントアウトされていますが、デフォルトの/var/run/senmail.pidが指定されています。

sendmailの起動/終了/再起動
 sendmailは、起動時に1度だけsendmail.cfファイルを読み込みます。もし起動後に、sendmail.cfを再構築した場合は、必ずsendmailを再起動する必要があります。sendmail.pidを使って、sendmailの再起動を次のように行うことができます。
  # kill -HUP `head -1 /var/run/sendmail.pid`
 sendmail.pidファイルの1行目にはデーモンモードで起動しているsendmailのプロセスIDが記述されています。それをheadコマンドで読み出し、killコマンドに渡しています。そして、killコマンドにHUPシグナルを渡して再起動させています。
 sendmailを終了させるには、HUPシグナルを送らずに以下のようにします。
  # kill `head -1 /var/run/sendmail.pid`
 sendmail終了後、起動したい場合は、tailコマンドでsendmail.pidの最後の1行を実行します。
  # `tail -1 /var/run/sendmail.pid`
メールキューの表示(-bp)
 メールキューに現在どれだけのメールが蓄積されているかを表示することもできます。メールキューを表示するためには、sendmailに-bpオプションをつけて実行します。mailqコマンドでも同様の結果を得ることができます。
 mailq(あるいは、sendmail -bp)を実行し、メールキューが空であれば以下のような結果を返します。
  # mailq
  /var/spool/mqueue is empty
 メールキューに保存されたメールであれば、以下のように表示されます。
  # mailq
  /var/spool/mqueue (2 requests)
  ----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------
  fBVKnEH31246      795 Tue Jan  1 05:49 <kanammi@othehost.or.jp>
                                         <sakura@hoge1.co.jp>
  fBSC0JH28447      536 Fri Dec 28 21:00 <kanammi@othehost.or.jp>
                   (Deferred: Connection reset by mfsmax.mobilesite.ne.jp.)
                                         <xxxx@mobilesite.co.jp>
 この例では、キューに2通のメールが保存されています。出力される内容は次のようになります。

Q-ID
 キューに入っているメールを一意(ユニーク)に決定することができるIDです。実際に/var/spool/mqueueに保存されているファイル名も、このQ-IDを元にしています。

Size
 メール本文の大きさを表示します。

Q-Time
 メールがはじめてキューに入った日時を示します。

Sender/Recipient
 送信者と受信者を示しています。1行目が送信者で、2行目が受信者になります。もし、配信されなかった理由がある場合は、2つ目のメールのように、送信者と受信者の間の行に配信できなかった理由が表示されます。
 なお、冗長メッセージモード(あとで解説します)と併用すると、より詳しいキューの一覧を出力することができます。
  # mailq -v
  /var/spool/mqueue (2 requests)
  ----Q-ID---- --Size-- -Priority- -----Q-Time----- ------------Sender/Recipient------------
  fBVKnEH31246      795      31168 Tue Jan  1 05:49 <kanammi@othehost.or.jp>
                                                    <sakura@hoge1.co.jp>
  fBSC0JH28447      536     121071 Fri Dec 28 21:00 <kanammi@othehost.or.jp>
                       (Deferred: Connection reset by mfsmax.mobilesite.ne.jp.)
                                                    <xxxx@mobilesite.co.jp>
 通常の出力と比べる、Priorityフィールドが追加されています。Priorityはメッセージの再送信の優先度を示しています。また、通常の出力では、あまり長いエラーメッセージは省略されてしまいますが、冗長メッセージモードであれば、省略されずに出力されます。

エイリアスの再構築(-bi、newaliases)

 aliasesはアドレスの別名を定義します。ときに膨大な数になる場合もあるのでm、データベースファイルで管理されています。そのため、aliasesを編集したら、必ずnewaliasesを実行する必要があります。newaliasesは“sendmail -bi”の別名として定義されています。
 aliasesが現在どこにあるか分からない場合は、
  # grep /aliases /etc/mail/sendmail.cf
  O AliasFile=/etc/mail/aliases
として、aliasesファイルの場所を調べます。
 newaliasesが正常に終了すれば、次のように表示されます。表示される結果は、aliasesのファイルパス、定義されているエイリアスの数、“:”の右側の値のうち最も長い長さ、そして、データベースに入力されたバイト総数を示しています。
  # newaliases
  /etc/mail/aliases: 40 aliases, longest 10 bytes, 395 bytes total
 エラーがある場合は、次のように表示されます。以下のエラーは、59行目にdecodeが重複して定義されているというエラーと、61行目に“:”がないというエラーです。エラーが出た場合は、必ずエラーがなくなるように、aliasesを修正する必要があります。
  /etc/mail/aliases: line 59: decode... Warning: duplicate alias name decode
  /etc/mail/aliases: line 61: missing colon
  /etc/mail/aliases: 41 aliases, longest 10 bytes, 405 bytes total
 なお、aliasesではメールのエイリアスがループしていることを検査しません。そのため、ループするような設定にしないように気をつける必要があります。aliasesの設定を確認するには、次に説明するベリファイモード(-bv)を使います。

ベリファイモード(-bv)

 ベリファイモードでは、aliasesデータベースを再帰的に検索して、あるアドレスに送られたメールが最終的にどこに配送されるか確認することができます。
 次の例では、postmasterというアドレスがあるかを確認しています。postmaster宛にメールが来たら、localのrootというユーザに配信されるように設定されています。
  # sendmail -bv postmaster
  root... deliverable: mailer local, user root
 外部のサイトにメールを送るように設定した場合は、次のように表示されます。
  # sendmail -bv user
  user@hoge.com... deliverable: mailer esmtp, host hoge.co.jp
  user	admin@hoge.co.jp
 user宛にメールが届いたら、esmtpでadmin@hoge.co.jp宛にメールが転送されます。もし、user1からuser2に転送するように設定していて、user2が存在しない場合は次のように表示されます。
  # sendmail -bv user1
  user2... User unknown
 newaliasesの段階ではエラーが出ませんので、newaliasesを実行したら、必ずベリファイモードでaliasesデータベースの設定を確認する習慣をつけましょう。

冗長メッセージモード(-v)

 冗長メッセージモードでsendmailを起動すると、メールを配信する際の全手順をコンソール画面に出力します。以下の例は、aya@hodege.comにmail.txtというファイルの内容を送信する例です。
  # sendmail -v aya@hoge.com < mail.txt
  aya@hoge.com... Connection to mail1.hoge.com. via esmtp...
  220 mail1.hoge.com ESMTP Sendmail 8.9.3/3.7W00052615; Sun, 6 Jan 2002 19:00:22 +0900
  >>> EHLO hoge.co.jp
  250-mail1.hoge.com Hello pc1.mylan.net[192.168.0.128], pleased to meet you
  250-8BITMIME
  250-SIZE 5000000
  250-DSN
  250-ONEX
  250-XUSR
  250 HELP
  >>>MAIL From: SIZE=46302
  250 ... Sender ok
  >>>RCPT To:
  250 Recipient ok
  >>> DATA
  354 Enter mail, end with "." on a line by itself
  >>> .
  250 TAA00639 Message acceptd for delivery
  aya@hoge.com... Sent (TAA00639 Message accepted for delivery)
  Closing connection to mail1.hoge.com
  >>> QUIT
  221 mail1hoge.com closing connection
 自ホストから送ったデータには先頭に“>>>”がついています。それ以外の行は、リモートホストから送られてきたデータです。このモードを利用して、自分のホストの設定がうまく動作しているかどうかチェックすることができます。自ホストにsendmailでリモートで接続して、チェックするのも有用です。

デバックモード(-d)

 デバックモードでは、冗長メッセージモードよりもさらに詳しい情報を出力することができます。-dコマンドラインスイッチの書式を示します。
  -d[カテゴリ].[レベル],[カテゴリ].[レベル],...
 カテゴリにはデバックする内容を、レベルには出力する情報を指定します。例えば、次のように実行すると、カテゴリ番号“40”に対応するデバッグメッセージを表示します。カテゴリ番号“40”は、キューの処理に関する情報出力です。ここでは、出力レベルは省略しています。(省略した場合は“1”が指定されます)。
  # sendmail -d40 root < /dev/null
  >>>>> queueing /var/spool/mqueue/qffBNGGqa01405 >>>>>
  queueing 80fa5a0=root:
          mailer 9 (local), host `'
          user `root', ruser `root'
          state=OK, next=0, alias 0,uid 0,gid 0
  flags=8000183
          owner=(none),home="/root", fullname="root"
          orcpt="(none)", statmta=(none), status=(none)
          rstatus="(none)"
  <<<<< done queueing fbNGGqa01405 <<<<<
 デバッグ番号の一覧について詳しく知りたい場合は、書籍等(『sendmail第3版』オライリー・ジャパン刊など)を参照して下さい。
 また、レベルは高く(数を大きく)すればするほど、出力する情報が多くなります。例えば、次のように“d0.1”を指定してみます。カテゴリ番号“0”は、一般的なデバッグ情報の出力です。
  # sendmail -d0.1 root < /dev/null
  Version 8.12.1
   Compiled with: LDAPMAP MAP _REGEX LOG MATCHGEOS MIME7TO8 MIME8TO7
                  NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS QUEUE SASL SCANF
                  SMTP TCPWRAPPERS USERDB
  ============ SYSTEM IDENTITY (after readcf) ============
        (short domain name) $w = localhost
    (canonical domain name) $j = localhost.localdomain
           (subdomain name) $m = localdomain
                (node name) $k = redhat72
  ========================================================
 レベルを高くすると、次のように出力される内容が詳細になります。
  # sendmail -d0.11 root < /dev/null
  Version 8.12.1
   Compiled with: LDAPMAP MAP_REGEX LOG MATCHGECOS MIME7TO8 MIME8TO7
                  NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS QUEUE SASL SCANF
                  SMTP TCPWRAPPERS USERDB
      OS Defines: HASFCHOWN HASFLOCK HASGETDTABLESIZE HASINITGROUPS
                  HASLSTAT HASRANDOM HASSETREUID HASSETRLIMIT HASSETSID
                  HASSETVBUF HASSNPRINTF HASURANDOMDEV HASUNAME HASUNSETENV
                  HASWAITPID IDENTPROTO USE_SIGLONGJMP
   Def Conf file: /etc/sendmail.cf
    Def Pid file: /var/run/sendmail.pid
  canonical name: localhost.localdomain
   UUCP nodename: redhat72
          a.k.a.: localhost.localdomain
          a.k.a.: localhost
          a.k.a.: [127.0.0.1]
  ============ SYSTEM IDENTITY (after readcf) ============
        (short domain name) $w = localhost
    (canonical domain name) $j = localhost.localdomain
           (subdomain name) $m = localdomain
                (node name) $k = redhat72
  ========================================================
 カテゴリ番号は、“0-99”のように範囲で指定することも可能です。また、複数のカテゴリをカンマで区切って指定することもできます。カテゴリ番号、出力レベルの推奨最大値は、両方とも99です。つまり、“d99.99”が最大値になります。

キュー

 すべてのメールはすぐに配信されるとは限りません。さまざまな理由で、すぐに配信できない場合があります。そのような場合、sendmailはいったんメールキューに保存して、配送できる状態になるまで再度配送を試みます。ある一定期間、配送できない状態が続くとエラーになり、配送元へと返されてしまいます。
 sendmailのキューは、メールが再度配信できるようになるまでキューディレクトリで保持されます。キューディレクトリについては、キューディレクトリを参照して下さい。キューの表示については、メールキューの表示を参照して下さい。

キューの処理方法

 キューディレクトリに保存されたキューを処理するには、sendmailの起動時に-qオプションを指定します。-qオプションでは、キューの処理の開始やその間隔を指定することができます。

定期的な処理

 デーモンモードの項でsendmailを起動するには、以下のようにして起動すると解説しました。この起動方法は多くのサイトでは適切な起動方法です。
  # sendmail -bd -q1h
 “-q1h”は、1時間おきにキューに蓄積されているメールを処理するという指定です。サイトによっては、この間隔を15m(15分)としてもかまわないでしょう。では、なぜ「多くの場合、1時間おきに処理する」のが適切なのでしょうか?それは、キューの処理時間と配送の遅延時間に関係してきます。

キューの処理時間と配送の遅延時間
 一度キューに入ってしまうと、再度キューが処理されるまでメールは配送されません。そのたm、キューの処理を“-q1h”と1時間おきと指定すると、メール配送が1時間以上遅れてしまうことがあります。メールの遅れをできるだけ少なくするためには、再送の間隔はできるだけ短くした方がよいわけです。
 しかし、キューの処理間隔を15m(15分)とした場合、例えば、そのホストから大量のメールが発信され、キューディレクトリに数多くのキューが登録されたとします。その場合、キューの間隔が15分しかないと、前回のキューの処理が終わる前にまた新しいキューの処理が始まってしまいます。結果として、CPU負荷の急激な増大、キューディレクトリの不整合などが起こる可能性があります。そのようなことを防ぐために、キューの処理時間は、ある程度安全な間隔をあける必要があるわけです。
 では、その間隔ができるだけ長い方がよいかというと、前述のようにメールの配信の遅延の問題があるため、あまり、長くあけることはできません。このような問題のバランスを取る値として、先人たちのこれまでの経験から、多くのサイトでは“-q1h”がちょうどよいとされています。
 もちろん、メールの配信量がほとんどない場合は、15mなどのように短く設定する方がよいでしょう。逆に、配信の量が多い場合は、その負荷や処理に長い時間がかかる理由を調査し、慎重に間隔を調整する必要があります。

直ちにキューを処理する
 sendmailの起動時に“-q”と時間間隔の指定を省略して指定した場合は、キューを1度だけ処理して終了します。1度に多くのメールがキューにたまり、すぐに処理したいという場合は、次のようにして、直ちにキューの処理を実行することができます。
  # sendmail -q
 また、以下のように冗長メッセージモードで実行すると、より詳細なメッセージを出力しながら、キューを処理することができます。時間がかかる原因などを調査する際には、このモードと併用すると便利です。
  # sendmail -q -v
特別な場合の処理

 キューには、sendmailが初回の配送で配送できなかったものが保存されます。通常に運用する上では問題ないのですが、メールの配送の量がシステムの許容値を大きく超えてしまった場合、キューのメール数は増大の一途をたどります。すると、新しくキューに保存されたメッセージがいつまでたっても送信されないといった自体が発生します。
 このような場合は、一時的にキューの一部を別の場所に保存しておき、後続のメッセージを処理できるようにします。そして、余裕が出た段階で、もしくは別のマシンなどで、別の場所に保存しておいたキューファイルを処理します。
 別のディレクトリに移しておいたキューファイルを処理するには、-QueueDirectory=/var/spool/newqueueスイッチを使います。
  sendmail -QueueDirectory=/var/spool/newqueue -OTimeout.queuereturn10d -q -v
 ここで、1つ注意が必要なのはメッセージの寿命です。キューを別のディレクトリに保存しておく期間が長くなると、メッセージを配送する寿命が尽きてしまう場合があります。メッセージを配送する寿命が尽きてしまえば、配送先ホストが生きていてもタイムアウトでエラーが送信元に帰ってきてしまいます。ここでは、メッセージの寿命を10日に延長しています。


cfによる設定

 sendmailの設定はsendmail.cfに記述します。このファイルを直接編集することができるのであれば、sendmailの特長を生かす柔軟な設定ができます。しかし、sendmail.cfは非常に複雑でかなりの知識を要していなければなりません。
 そこで、簡単に設定できるように「cf」という設定ツールが標準で添付されています。

cfを使う前に

 cfはm4というマクロ言語プロセッサを利用して動作します。そのため、cfを使用するにはm4がインストールされていなければなりません。インストールされていない場合は、以下のサイトからインストールして下さい。
http://www.seindal.dk/rene/gnu/
http://www.gnu.org/software/m4/m4.html
ftp://ftp.seindal.dk/oub/rene/gnu/

m4の使い方

 cfで利用する設定ファイルは、Red Hat Linuxでは/usr/share/sendmail-cf/cfにあります。実際に編集するファイルは、このディレクトリの中にある「.mc」という拡張子で、このファイルを「.mcファイル」と呼ぶことにします。.mcファイルが.cfファイルの元になります。.mcファイルを.m4を使ってsendmailの設定ファイルであるsendmail.cfに変換します。
 .m4ファイルから.cfファイルへ変換するには、cf/ディレクトリで以下のように実行します。
  # ./Build sendmail.cf
 sendmail.cfを編集したい場合は、引数にsendmail.cfを指定します。

cf/ディレクトリ

README
 cfの利用方法が詳細に書かれています。このファイルの日本語化に取り組んでいるサイト(cfプロジェクト(仮称)cf/README)もあります。

cf
 各OSのための基本的な設定ファイル(.mcファイル)が入っています。このディレクトリで、m4を使って.cfファイルを作成します。

domain
 特別なドメインに関する設定が定義されています。これは、DOMAINマクロで読み込まれます。例えば、CS.Berkerry.EDU.m4にはCS.Berkerry.EDUのサブドメインのための設定がされています。通常はgeneric.m4以外は使いません。

feature
 よく利用される専門的な設定が定義されています。.mcファイルからFEATUREマクロで読み込まれます。

hack
 ローカルハックです。HACKマクロで読み込むことができます。.Berkerry.EDUの設定が参考として入っています。

m4
 一般的なサポートルーチンが用意されています。ここにあるファイルはとても重要なので、通常は変更しないで下さい。

mailer
 配信エージェント(メーラ)の種類が定義されています。.mcファイルからMAILERマクロで読み込まれます。

ostype
 各OS用の設定が定義されています。.mcファイルの中で、OSTYPEにOSを指定することで読み込まれます。“linux”、“bsd4.4“、“sunos4.1”・・・などが定義されています。

sh
 .mcファイルから.cfファイルを作成するためのシェルスクリプトが入っています。

siteconfig
 昔のバージョンとの互換性のためだけに残されています。SITECONFIGマクロでUUCPホストの接続情報を読み込むことができます。

.mcファイルを編集する前に

 まず、cf/ディレクトリにある.mcファイルを見てみましょう。
  # cat generic-linux.mc
とすると、以下のように表示されます。
  divert(-1)
  #
  # Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  #       All rights reserved.
  # Copyright (c) 1983 Eric P. Allman.  All rights reserved.
  # Copyright (c) 1988, 1993
  #       The Regents of the University of California.  All rights reserved.
  #
  # By using this file, you agree to the terms and conditions set
  # forth in the LICENSE file which can be found at the top level of
  # the sendmail distribution.
  #
  #
  #
  #  This is a generic configuration file for Linux.
  #  It has support for local and SMTP mail only.  If you want to
  #  customize it, copy it to a name appropriate for your environment
  #  and do the modifications there.
  #
  divert(0)dnl
  VERSIONID(`$Id: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $')
  OSTYPE(linux)dnl
  DOMAIN(generic)dnl
  MAILER(local)dnl
  MAILER(smtp)dnl
 このファイルを見ると、最後の6行が設定だと分かると思います。

m4の文法

 cfで利用する.mcファイルを編集する前に、最低限のm4の文法を解説します。

クォート

 m4では設定値をクォートする場合、バッククォーテーション(`)とシングルクォーテーション(')で囲みます。
  define(`ALIAS_FILE', `/etc/mail/aliases')dnl
 日本語キーボードであれば、[Shift]キーを押しながら[@]キーを押すと、バッククォーテーション(`)、[Shift]キーを押しながら[7]キーを押すと、シングルクォーテーション(')となります。

コメント

 .mcファイルのコメントアウトは“#”で行います。“#”から行末の改行までの文字列はコメントとして、m4の解釈から外されます。
 ただし、独特なのは、m4の場合“#”でコメントアウトしても改行は残るため、空行が残ってしまいます。コメント行が数行にわたるような場合は、不要な空行が何行も残ってしまいます。これを防ぐには、divert関数を使ってコメント行の出力を破棄します。

空行

 m4はマクロ言語であるため、Perlなどのスクリプト言語などとは基本的に異なります。そのため、m4では改行は重要な意味を持ちます。m4でさまざまな定義を行いますが、定義文の改行はそのまま出力されます。
 例えば、
  1st Line
  define(N,100)
  Testing N definition.
のような定義sample.mcをm4で処理すると、以下のようになります。
  # m4 sanple.mc
  1st Line
  Testing 100 definition.
 defineは、文字を置き換えるマクロ定義です。ここでは“N”を“100”に置き換えています。このように、m4で処理するとdefineマクロ定義は実行されますが、改行は残ってしまいます。
 このような無駄な空行は出力結果を読みにくくするため、次のように、dnlをいう命令を使って空行を削除します。
  1st Line
  define(N,100)dnl  There is dedine macro.
  Testing N definition.
 このsanple.mcをm4で処理すると、define行の改行が削除されて
  # m4 sanple.mc
  1st Line
  Testing 100 definition.
 のように出力されます。
 dnlのあとは削除されるので、コメントを入れてもかまいません。このように、dnlは#コメントと同じように利用することができます。人によっては、より便利に感じるかもしれませんが、明らかにコメントを入れることが目的である場合には、“#”を使うことが推奨されています。

m4の組み込み関数

 m4には、後で説明するcfの設定用マクロの他に、組み込み関数がいくつかあります。ここでm4に組み込まれている関数を解説します。

マクロ定義

 書式 define(a,b)
 defineは、“a”という文字列を“b”と定義します。つまり、“a”という文字列があれば、“b”に置き換えます。

 書式 undefine(a)
 “a”が定義されていたら、それを無効にします。定義されていなければ、何もしません。

条件付きマクロ定義

 条件付きマクロ定義は、ある条件を満たしたい場合にだけマクロを定義します。また、複数の条件分岐も可能です。

 書式 ifdef(a,b)
 “a”が定義されていれば、“b”が定義されます。

 書式 ifelse(a,b,c,d)
 “a”と“b”の文字列を比較します。もし、同じであれば、関数の戻り値として文字列“c”を返します。一致しなければ、文字列“d”を返します。実際、ifelseは4つ以上の引数を指定することができます。

 ifelse(a,b,c,d,e,f,g)

 このように指定すると“a”と“b”が同じなら“c”を、同じでなければ“d”と“e”を比較し、マッチすれば“f”を、それ以外なら“g”を返します。

ファイル関数

 ファイル関数は、ファイルの読み込みやファイルの記述などに関する関数です。

 書式 include(filename)
 filenameで指定したファイルを読み込みます。そして、include文を書いた場所で、そのファイルに定義した命令が適用されます。includeは、よく使う定義をまとめておき、再利用する際などに大変便利です。

 書式 divert(n)
 m4はその出力をいくつか一時ファイルに書き出すことができます。divertの引数に数字を渡すことで、その出力先を指定します。m4では、1~9までの一時ファイルを利用することが可能です。
 cfでは一時ファイルは使いませんが、ファイルの出力先を変更する機能を利用して、C言語などにある複数行のコメントアウトと同等の機能を実現することができます。

 divert(0)

 divertに0を設定すると、出力先を標準出力に変更します。通常はこの設定です。ちなみに、

 divert

 と引数を与えずに指定した場合、引数に0を指定した場合と同じ効果があります。

 divert(-1)

 引数に-1を指定すると出力をすべて破棄します。これを使って、不要な空行を破棄することができます。m4では、コメントアウトした際の行も空行として出力されてしまいます。場合によって、この空白は出力された結果を読みにくいものにしてしまうため、不要な空行は削除します。
  divert(-1)
  # ここにコメントを書きます
  # 通常は空行が出力されますが
  # divert(-1)
  # 出力が破棄されます。
  # ちなみに、ここではわかりやすいように
  # 日本語で書いていますが
  # 日本語は入力しないで下さい
  divert(0)
    ・
  (ここ以降に通常の定義を行う)
    ・
 算術関数

 m4には、3つの算術関数があります。

incr 数値を1つあげる
decr 数値を1つ下げる
eval 任意の整数演算を実行する


 演算子

 m4には、以下のような算術演算子、比較演算子、論理演算子があります。

**or^ 乗数演算
+ 足し算
- 引き算
A==B 比較演算子(AはBと等価)
A!=B 比較演算子(AとBは等価でない)
A 比較演算子(AはBより小さい)
A<=B 比較演算子(AはB以下)
A>B 比較演算子(AはBより大きい)
A>=B 比較演算子(AはB以上)
! 否定
&or&& 論理演算子
|or∥ 論理演算子(または)


 文字列関数

 文字列の簡単な処理を行う関数です。

 書式 len(a)
 aの文字列の長さを返します。

 書式 substr(s,m,n)
 sの文字列の一部を返します。mからn文字を返します。

 システム関数

 書式 esyscmd
 この命令は、システムにコマンドを引き渡します。例えば、

 esyscmd(date)

 というようにすると今日の日付を返します。

 この他にも、m4の命令はいくつもありますが、cfを扱う上ではこの程度知っておけば十分です。これ以上詳しいことを知りたい場合は、manなどを参照して下さい。

.mcファイルの編集

 では、さっそく設定を始めましょう。ここでは、.mcファイルとしての最低限の設定を見ていきます。
 先ほどのgeneric-linux.mcをコピーして、設定するためのファイルを作成します。皆さんは、自分のOSに合った.mcファイルをsendmail.mcとしてコピーして下さい。
  # cp /usr/share/sendmail-cf/cf/generic-linux.mc /etc/mail/sendmail.mc
 では、sendmail.mcを見てみましょう。行頭の番号(nn:)は行番号です。分かりやすいように付けていますが、実際のファイルにはありません。
  01:divert(-1)
  02:#
  03:# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  04:#       All rights reserved.
  05:# Copyright (c) 1983 Eric P. Allman.  All rights reserved.
  06:# Copyright (c) 1988, 1993
  07:#       The Regents of the University of California.  All rights reserved.
  08:#
  09:# By using this file, you agree to the terms and conditions set
  10:# forth in the LICENSE file which can be found at the top level of
  11:# the sendmail distribution.
  12:#
  13:#
  14:
  15:#
  16:#  This is a generic configuration file for Linux.
  17:#  It has support for local and SMTP mail only.  If you want to
  18:#  customize it, copy it to a name appropriate for your environment
  19:#  and do the modifications there.
  20:#
  21:
  22:divert(0)dnl
  23:VERSIONID(`$Id: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $')
  24:OSTYPE(linux)dnl
  25:DOMAIN(generic)dnl
  26:MAILER(local)dnl
  27:MAILER(smtp)dnl
 まず、ファイルの先頭にあるdivert(-1)は無視して、2行目から見ていきます。先頭の“#”で始まる行は、コメント行です。しかし、m4ではコメント行でも末尾の改行だけは削除されないため、divert(-1)を利用して出力先を変更しています。divert(-1)にしている間はその出力は破棄されるため、複数行のコメントなどがある場合は、これを利用します。divert(0)にすると、出力を標準出力に戻します。先頭のコメントの部分では、著作権表示やそのファイルの説明などが記述されています。
 22行目で初めて出てくるdnlはDelete to NewLineの略で、dnlから次の行まで改行を含む文字列を破棄します。m4では。命令文のあとの改行もそのまま出力されてしまうため、行末にdnlを指定して、改行が出力されないようにしています。

 VERSIONID
 23行目のVERSIONIDには、出力するsendmail.cfにコメントとして書き込むバージョンIDを指定します。いつ作成したファイルであるか自分でわかりやすいように設定します。
 VERSIONIDの指定は必須ではありません。

 OSTYPE
 24行目のOSTYPE定義は必須です。OSTYPEを指定することで、sendmailの各設定ファイルのパス名やメーラに必要なフラグなどの重要な設定を簡単に設定することができます。
 OSTYPEに設定できる値は、/usr/share/sendmail-cf/ostype/ディレクトリの中にあるファイル名です。どのようなファイルがあるかはOSTYPE定義を参照して下さい。

 DOMAIN
 25行目のDOMAIN定義は、ドメイン固有の設定を指定します。通常は
 DOMAIN(`generic')dnl
と指定すればうまく動作します。必要であれば、利用する環境によってドメイン定義を再定義することができます。設定できる値は/usr/share/sendmail-cf/domain/ディレクトリの中にあるファイル名です。

 MAILER
 26、27行目にあるMAILER定義では、sendmailが利用するメーラを指定します。ここでは“local”と“smtp”が指定されています。
 MAILER(`local')の指定は必須です。そのほか、MAILER(`smtp')やMAILER(`procmail')など、利用する環境によって必要なものを指定します。
 なお、MAILER定義は必ず.mcファイルの最後に置かれていなければなりません。また、MAILER(`smtp')とMAILER(`procmail')、MAILER(`uucp')を使用する場合、MAILER(`smtp')は必ずMAILER(`procmail')とMAILER(`uucp')より先に定義されている必要があります。

 これから、このファイルに必要な設定を追加していくのですが、.mcファイルに記述する設定には順番があります。

.mcファイルにおける定義の順番

 .mcファイルの定義には順番があります。通常は、以下の順で記述します。

 VERSIONID
 OSTYPE
 DOMAIN
 FEATURE
 ローカルマクロの定義(define/undefine/ifedf...)
 MAILER
 LOCAL_RULE_*
 LOCAL_RULESETS

 OSTYPEやDOMAINなどのマクロでよくあるケースに応じたマクロが定義されています。そのため、defineなどのローカルマクロの定義をOSTYPEなどの前に指定すると、OSTYPEの定義で上書きされ、設定が有効にならない場合があります。
 そのため、define、undefine、ifdefなどのローカルマクロの定義をOSTYPEやDOMAINのあとに記述する必要があります。defineでローカルマクロを設定して、undefineでローカルマクロを解除します。undefineで、OSTYPEなどで指定されたローカルマクロを解除することができます。
 ただし、この順所には若干の例外があります。FEATUREに影響を与えるローカルマクロ定義は、FEATURE()の前にマクロ定義がされていなければなりません。例えば、define(`PROMAIL_MAILER_PATH',・・・)はFEATURE(`local_procmail')の前に記述する必要があります。
 FEATUREとは、よく設定される設定についてあらかじめ用意しておき、キーワードを指定することによって、その設定を適用することができるマクロ定義です。

OSTYPE定義

 cfでは、OSTYPEは必須の定義です。OSTYPEには、それぞれのOSに基づいた基本設定がされていますので、自分のホストのOSに合ったOS名を指定する必要があります。
 OSTYPEに値を指定すると、/usr/share/sendmail-cf/ostype/ディレクトリにある、指定された値と同じ名前の.m4ファイルが読み込まれます。OSTYPEに指定できる値は、/usr/share/sendmail-cf/ostype/ディレクトリにある.m4という拡張子のファイルのファイル名になります。

aix2.m4 aix3.m4 aix4.m4 aix5.m4 altos.m4 amdahl-uts.m4
aux.m4 bsd4.3.m4 bsd4.4.m4 bsdi.m4 bsdi1.0.m4 bsdi2.0.m4
darwin.m4 dgux.m4 domainos.m4 dynix3.2.m4 freebsd4.m4 gnu.m4
hpux10.m4 hpux11.m4 hpux9.m4 irix4.m4 irix5.m4 irix6.m4
isc4.1.m4 linux.m4 maxion.m4 mklinux.m4 nextstep.m4 openbsd.m4
osf1.m4 powerux.m4 ptx2.m4 qnx.m4 riscos4.5.m4 sco-uw-2.1.m4
sco3.2.m4 sinix.m4 solaris2.m4 solaris2.ml.m4 solaris2.pre5.m4 solaris8.m4
solaris2.ml.m4 solaris2.pre5.m4 solaris8.m4 sunos3.5.m4 sunos4.1.m4 svr4.m4
ultrix4.m4 unixware7.m4 unknown.m4 uxpds.m4


 この中から自分のOSに合った適切なファイルを選択します。OSがLinuxであれば、以下のように指定します。
  OSTYPE(linux)dnl
 同じようにSolaris2.6の場合は、このように指定します。
  OSTYPE(Solaris2)dnl  for Solaris2.6
 FreeBSD4.4の場合は、
  OSTYPE(bsd4.4)dnl  for FreeBSD4.4
とします。
 もし、この中に自分のOSとあるファイルがない場合は、unknownを指定します。
  OSTYPE(unknown)dnl
MAILER定義

 sendmailでは、いくつかのメーラをサポートしています。通常、MAILER定義は.mcファイルの最後に定義します。
  # MAILERマクロの設定例
  MAILER(local)dnl
  MAILER(smtp)dnl
  MAILER(procmail)dnl
 local

 sendmail.cfのlocalメーラとprogメーラのことを指します。自ホスト宛のメールを受け取り、ローカルのメールボックスに配信する場合などに使われます。全てのメールを別サイトにリレーする場合などを除き、通常、この定義は必須です。このメーラは.mcファイルから記述を削除したとしても、必ず自動的に読み込まれます。

 smtp

 SMTPメーラのことです。このメーラを使用する場合、すべてのホストがDNSで参照可能である必要があります。実際には、以下の5つのメーラが定義されています。

・smtp
 他サーバへの通常のSMTP配送を行います。

・esmtp
 他サーバへ拡張SMTP配送を行います。

・smtp8
 他サーバへ8ビットデータをMIME変換せずにSMTPで配送します。

・dsmtp
 配送要求に応じて配送します。

・relay
 RELAY_HOST、LUSER_RELAY、MAIL_HUBへの配送を行います。

 procmail

 procmailというアプリケーションへの配送インターフェースです。procmailは、sendmailとは関係なく、別途インストールする必要があります。多くのシステムの場合、デフォルトでインストールされています。
 このメーラを使うと、あるドメイン宛のメールをすべて1ユーザ宛に配送するなどといったことが可能になります。実際には、mailertableに次のように指定します。
  host.procmail:/etc/procmailrcs/host.com
 このように指定すると、/etc/procmailrcs/host.comを読みに行きます。/etc/procmailrcs/host.comで、
  :0# forward mail for host.com
  ! -oi -f $1 person@other.host
のように設定されているとすると、host.com宛の全てのメールは、person@other.hostに送信されます。procmailのスクリプトにおいて、$1は発信者の名前、$2は受信者の名前です。
 procmailメーラを利用するには、.mdファイルでMAILER(procmail)定義よりも前に、FEATURE(`local_procmail')定義をしておく必要があります。

 fax

 FAX送信を指します。これは「Sam Letter's HylaFAX sofrware」をベースにした実験的な機能です。詳しくはHyla FAX Home Pageを参照して下さい。

 この他にも、cyrus、uucp、usenet、pop、mail11、qpageなどのメーラが存在します。

新しい設定を反映させる

 sendmail.mcの編集が済んだらsendmail.cfを作成し、新しい設定を反映させます。これより、頻繁にsendmail.mcファイルに関する設定が出てきます。そのたびにsendmail.cfに変換して、sendmailを再起動するわけですが、何回も同じ手順になりますから、ここで、1度だけ新しいsendmail.cfに差し替える手順を示します。必要な場合、こちらの記述を参照して下さい。

sendmail.cfの差し替え

 sendmail.cfの差し替えは以下の手順で行います。

   1 sendmail.mcを編集する
   2 sendmail.cfに変換する
   3 旧ファイルのバックアップ
   4 sendmail.cfのインストール
   5 sendmailを再起動する

 1 sendmail.mcの編集

 viなどでsendmail.mcを開き、設定を行います。編集は/etc/mail/で行うことにします。
  # vi /etc/mail/sendmail.mc
 設定が終わったら、viを終了し、sendmail.mcを保存します。

 2 sendmail.cfへの変換

 sendmail.mcの編集が済んだら、sendmail.cfに変換します。/usr/share/sendmail-cf/cf/ディレクトリで、
  sh Build sendmail.cf
とします。引数にsendmail.cfと指定するとsendmail.mcファイルが読み込まれ、sendmail.cfファイルが作成されます。

 3 旧ファイルのバックアップ

 次に、sendmail.cfやsendmailのバイナリプログラムをバックアップします。sendmail.cfだけを更新する場合にはsendmail.cfのみのバックアップだけでよいでしょう。日付などを付けてコピーします。
  # cp /etc/sendmail.cf /etc/sendmail.cf.YYYYMMDDNN
 4 sendmail.cfのインストール

 バックアップが終わったら、早速sendmail.cfをインストールしてみましょう。
  sh Build install-cf
 5 sendmailの再起動

インストールが終わったら再起動します。
  # kill -HUP `head -1 /var/run/sendmail.pid`
 ここでエラーが出た場合は、エラー内容にしたがって.mcファイルを修正し、sendmail.cfを作成し直します。エラーが出なければ問題ありません。

基本的なsendmailの設定

 ここで、基本的なメールサーバの設定として、そのほか必要なのものをトピックス的にいくつかあげておきます。

UUCPを使わない

 必要のないサービスを停止することは、セキュリティを向上させる上で大変重要です。ここでは、UUCPやBITNET形式のアドレスを扱いませんので、以下のようにして設定を無効にします。
  undefine(`UUCP_RELAY')dnl
  undefine(`BITNET_RELAY')dnl
 また、sendmailで明示的にUUCPアドレスを使わないように宣言することもできます。FEATURE定義でnouucpを指定すると、UUCPアドレスのメールを配送しないようになります。
 また、nouucpの第2引数にrejectを指定すると、ローカルパート(@の左側)に“!”がついたアドレスが転送を許可されたシステムからのものでない場合には拒否します。nospecialを指定すると、“!”に関する特別な処理を一切しません。
  FEATURE(`nouusp',`nospecial')dnl
個人情報の流失を防ぐ

 SMTPには、相手のメールサーバにどのようなユーザがいるかを調べるVRFYコマンドと、指定したメールアドレスのエイリアスなどを展開して誰に転送しているか調べるEXPNコマンドがあります。これらのコマンドを利用すると、特定のメールアドレスの情報が外部に漏れてしまうことがあります。
 コマンドの詳細については、SMTPコマンドリファレンスを参照してください。
 このコマンドを利用できないようにするには、.mcファイルにconfPRAIVACY_FLAGSを定義します。通常はgoawayを指定します。
  define(`confPRIVACY_FLAGS',`goaway')dnl
 goawayは、VRFYコマンドとEXPNコマンドを禁止するほかに、confPRIVACY_FLAGSの設定フラグ一覧にあるような機能を持っています。

フラグ 意味
public 制限なし
needmailhelo MAILコマンドの発行前にHELOを要求する。
needexpnhelo EXPNコマンドの発行前にHELOを要求する。
needvrfyhelo VRFYコマンドの発行前にHELOを要求する。
noexpn EXPNコマンドを禁止する。
novrfy VRFYコマンドを禁止する。
restrictmailq 一般ユーザのmailqコマンドの使用を禁止する。
restrictqrun 一般ユーザのsendmail -qの使用を禁止する。
noreceipts Return-Recipt-To:の解釈を抑制する。
authwarnings 発信者アドレスの偽造の可能性に関する情報をヘッダに付加する。
goaway needmailhelo、needexpnhelo、needvrfyhelo、noexpn、novrfy、authwarnings、noreceiptsすべてを指定したのと同じ。


 複数のフラグを指定したい場合には、“,”(カンマ)で区切って指定します。
  define(`confPRIVACY_FLAGS',`goaway,restrictmailq,restrictqrun')dnl
VRFYコマンドとEXPNコマンドの動作

 VRFYやEXPNが実際どのように動作するかは、telnetでSMTP接続してみるとよく分かります。
  #VRFYコマンドとEXPNコマンドの使用例
  VRFY gonta  <---①
  250 Gonta <gonta@mail.hoge.com>  <---②
 EXPN user1  <---③
  250-User1 <user1@mail.hoge.com>  ┐
  250-Gonta <gonta@mail.hoge.com>  │<---④
  250 <goro@mail.hoge.com>         ┘
  EXPN re-talk
  250 <"|/usr/local/fml/fml.pl /var/spool/ml/re-talk "@mail.hoge.com>  <---⑤
 まず、メールサーバにSMTP接続します。220応答コードが送られてきたら、“EHLO <メールサーバ名>”と入力して[Enter]キーを押します。250応答コードが送られてきたら、VRFYコマンドを入力します。VRFYコマンドの引数には、調べたいアドレスのローカルパート(@の左側)を指定します(①)。接続しているSMTPサーバでVRFYコマンドの使用が許可されていれば、250応答コードとともに、ユーザの本名(/etc/passwdに設定されていれば)と最終的に受け取るメールアドレスが返されます(②)。
 このコマンドは、fingerというコマンドとよく似た効果を持ちます。最近では、fingerは禁止されていることが多いようですが、まだVRFYコマンドは有効である場合が多く見受けられます。個人情報の流失やメールアドレスの調査に利用されてしまうため、このコマンドは利用できないようにしておきましょう。
 次に、EXPNコマンドを実行します。EXPNコマンドも引数にメールアドレスのローカルパートを指定します(③)。EXPNコマンドをが通れば、そのメールアドレスに設定されている転送先のアドレスが全て分かります(④)。リモートホストのメールアドレスの場合は、ユーザ名が表示されませんが、グループアドレスなどを設定している(エイリアスで、複数アドレスに転送している)場合は、メールアドレスが流失してしまう場合もあります。
 また、実際に使っているメーリングリストなどの場合は、⑤のように実行プログラムのパスが表示されてしまいます。このようは出力でセキュリティホールを見つけられてしまう場合もありますので、EXPNコマンドについても必ず禁止しておきましょう。
 VERYコマンドとEXPNコマンドの実行が失敗した例をそれぞれ示しておきます。このような応答があれば、問題ありません。
  #VRFYコマンドの実行失敗例
  VRFY user1
  252 Cannot VRFY user; try RCPT to attempt delivery (or try finger)
  #EXPNコマンドの実行失敗例
  EXPN user1
  502 Sorry, we do not allow this operation
信用できるユーザを設定する

 sendmailには、-fオプションでエンベロープFromを指定する機能があります。しかし、エンベロープFromを明示的に変更した場合、メールのヘッダにメッセージのヘッダが偽造された可能性を示すX-Authentication-Warningヘッダが追加されてしまいます。このヘッダを追加せずに-fオプションを使用したい場合、そのユーザを「信頼できるユーザ」として設定します。
 FEATURE(use_ct_file)を指定すると、/etc/mail/trusted-usersから信頼するユーザを読み込みます。
  FEATURE(use_ct_file)dnl
 設定ファイルを/etc/mail/trasut-usersから変更したい場合は、confCT_FILEで設定を変更することができます。
  define(`confCT_FILE',`/etc/mail/sendmail.ct')dnl
  FEATURE(use_ct_file)dnl
また、confTRUSTED_USERSを使ってユーザを直接指定することができます。複数指定する場合には、半角空白で区切って指定します。明示的に指定しなくても、root、uucp、daemonは常に指定されます。
  define(`confTRUSTED_USERS',`majordom fml')dnl
  FEATURE(use_ct_file)dnl
 confTRUSTED_USERSに似た、confTRUSTED_USERというマクロもあるので混乱しないようにして下さい。confTRUSTED_USERでは、設定ファイルの所有者やdaemonの起動ユーザとして信用するユーザを指定します。これは、初期設定では未設定です。

常にドメイン名を追加する

 ローカルのユーザからローカルのユーザ宛のメールの場合、通常は@以降のドメイン部分は必要ありません。しかし、ユーザの名前空間が統一されていないような場合(複数ドメイン名を管理している場合など)は、常にドメイン名を付加するようにした方がよいでしょう。その場合、以下のようにdefineで定義します。
  define(`always_add_domain')dnl
メールの最大サイズを制限する

 メールの最大サイズの制限方法は、RFC1870(SMTP Service Extenxion for Message Size Declaration)で定義されています。しかし、最新のSMTPを定義しているRFC2811では、最近のマルチメディアデータの大容量化に伴い、メッセージの最大サイズの制限はするべきではないとされています。
 とはいっても、送信先のメールボックスのサイズなどの問題や、自分のサーバには制限が無くても、リレー先のサーバで容量オーバーでリレーされないなどの問題を避けるため、実用上は、ある程度の制限を設けるべきかもしれません。制限をかけても、メールソフトのメール分割機能を使えば問題ありません。
 メールの最大サイズの制限するには、confMAX_MESSAGE_SIZEで指定しています。値の設定は、バイト単位で行います。以下の例では、1MBで制限しています。
  define(`confMAX_MESSAGE_SIZE',`1048576')dnl
 初期設定は無制限(infinite)です。infiniteを指定すれば、設定されているサイズ制限は解除されます。
  define(`confMAX_MESSAGE_SIZE',`infinite')dnl
転送設定

 送られてきたメールは、まず、sendmail.cfによって処理され、自ホスト宛のメールであるかどうかがチェックされます。そして、ローカルユーザ宛のメールである場合は、以下のような流れで処理されます。

  1.システムのaliasesファイルで処理される
  2.ユーザディレクトリにある~/.forwardファイルで処理される
  3.sendmail.cfのローカル配信エージェントに従い、メールスプールファイルに書き込む

 メールを転送する場合は、/etc/aliases(または、/etc/mail/aliases:設定による)や~/.forwardファイルなどで設定します。

aliases

 /etc/aliasesで、メールアドレスのローカルパート(@の左側)の別名(エイリアス)を定義することができます。
 基本的な書式は、大変簡単で
  postmaster:	root
 このように値を“:”(コロン)で区切る形で定義します。この例では、“postmaster@ドメイン名”というメールアドレス宛のメールをrootユーザに配送することを意味します。配送先のユーザを複数指定した場合は、“,”(カンマ)で区切って指定することができます。
  postmaster:	root,user
 また、配送先にはメールアドレスを指定することもできます。
 次のように、“,”(カンマ)で区切って複数アドレスを設定することで、簡易的なメーリングリスト(転送メールアドレス)を作成することもできます。なお。このような設定を行うときは、必ず
  define(`confPRIVACY_FLAGS',`goaway')
を指定して、EXPNコマンドを無効にします。

newaliases

 注意しなければならないのは、aliasesファイルはデータベースファイルとして管理されていると言うことです。/etc/aliasesはテキストファイルなので、編集したら必ずnewaliasesコマンドを実行して、データベースファイルを再構築する必要があります。
 データベースファイルは、/etc/aliases.dbという名前で保存されています。
  newaliases
 newaliasesコマンドを実行する場合、エラーメッセージが出た場合はエラーメッセージにしたがって処理します。よくある間違いが、“:”の右側(キー)に重複したレコードをしてしまうことや、“:”を忘れるなど単純な文法の間違いです。
 なお、このnewaliasesコマンドは、root以外では実行することができません。

:include:

 メンバーが変わる可能性があるメーリングリストなどのために、もう少し使いやすくすることができます。aliasesには、:include:という機能があります。:include:は、指定したファイルからメールアドレスのリストを読み込みます。
  ml1:		:include:/home/user1/null/ml1/users
 このようにすると、/home/user1/null/ml1/usersというテキストファイルから配送先(メールアドレス)のリストを読み込みます。
 :include:で指定されたファイルには、1行に1アドレスを記述します。記述の仕方は、基本的にaliasesファイルにおける“:”の右側の記述と同じです。
 また、:include:で指定されたファイルで定義することによって、プログラムを起動することもできます。

必須のエイリアス定義

 aliasesには、必ず設定すべき必須のエイリアス定義が存在します。それがpostmasterとMAILER-DAEMONです。
  # 必須なエイリアス
  postmaster:		root
  MAILER-DAEMON:	postmaster
 メール関連のプログラムのいくつかは問題が起こると、postmaster宛にメッセージを送ることがあります。そのため、postmasterは必ず必要です。
 また、メール配送時に何らかの問題が起こった際のエラーメールは、MAILER-DAEMONというアドレスから配送されますが、そのエラーメールが何らかの問題で配送できなかった場合にMAILER-DAEMON宛にメールが来たり、エラーメールに対して問い合わせがくる場合があります。そのため、このようなメールを受け取れるように、必ず、MAILER-DAEMONを設定する必要があります。
 この2つのエイリアスは、デフォルトで/etc/aliasesファイルにすでに記述されています。絶対に削除してはいけません。また、virtusertableなどで複数ドメインを運用するような場合は、各ドメイン毎にpostmasterやMAILER-DAEMONを適切なユーザが受け取れるように設定する必要があります。
 なお、aliasesは大文字小文字を区別しません。つまり、“MAILER-DAEMON”と“mailer-daemon”というアドレスは同じアドレスを指すことになります。UNIXシステムでは多くの場合、大文字と小文字を区別しますので、混乱しないようにしてください。

その他のエイリアス定義

 必須のエイリアス定義以外は、自由に設定してかまわないのですが、歴史的な背景から、さまざまなエイリアスが最初から定義されています。
 参考までに、redhat9.0のエイリアスファイルを以下に示します。
  #
  #       @(#)aliases     8.2 (Berkeley) 3/5/94
  #
  #  Aliases in this file will NOT be expanded in the header from
  #  Mail, but WILL be visible over networks or from /bin/mail.
  #
  #       >>>>>>>>>>      The program "newaliases" must be run after
  #       >> NOTE >>      this file is updated for any changes to
  #       >>>>>>>>>>      show through to sendmail.
  #
  # Basic system aliases -- these MUST be present.
  mailer-daemon:  postmaster
  postmaster:     root
  # General redirections for pseudo accounts.
  bin:            root
  daemon:         root
  adm:            root
  lp:             root
  sync:           root
  shutdown:       root
  halt:           root
  mail:           root
  news:           root
  uucp:           root
  operator:       root
  games:          root
  gopher:         root
  ftp:            root
  nobody:         root
  apache:         root
  named:          root
  xfs:            root
  gdm:            root
  mailnull:       root
  postgres:       root
  squid:          root
  rpcuser:        root
  rpc:            root
  ingres:         root
  system:         root
  toor:           root
  manager:        root
  dumper:         root
  abuse:          root
  newsadm:        news
  newsadmin:      news
  usenet:         news
  ftpadm:         ftp
  ftpadmin:       ftp
  ftp-adm:        ftp
  ftp-admin:      ftp
  # trap decode to catch security attacks
  decode:         root
  # Person who should get root's mail
  root:           \user1
 “General redirections for pseudo accounts.”として、たくさんのエイリアスが登録されています。必要がなければこれらのアドレスは削除してもかまいませんが、特定のプログラムが利用している場合もあるので、削除する際には注意して下さい。
 また、重要なのはroot宛のメールを読む一般ユーザの指定です。この例では、最終行にroot宛のメールをuser1に配送するように指定しています。ここでは確実にuser1に配送するため、再帰的な処理を停止しています。
 通常、rootアカウントはリモートからログインできませんので、root宛に届いたメールは一般ユーザでログインし、suコマンドでrootになったあと、シェル上から読むしかありません。重要な連絡が来る場合もあるため、一般ユーにメールを転送し、POPで読めるようにしておくと便利でしょう。

再帰的な処理

 aliasesは再帰的に処理されます。例えば、user1宛のメールが届いたとして、その配送先が決定できるまで、何度もaliasesを解釈します。
 例えば、
  user1:	user2
  user2:	user3
  user3:	user4
  user4:	user5
 のような定義があったとすると、1回目の解釈でuser1宛のメールがuser2に配送され、次に、今度はuser2宛のメールとしてaliasesを解釈し、user3宛に配送されます。そして、最終的にはuser5に配送されて処理が完了します。
 このように再帰的に処理される場合、次のような定義はメールをループさせてしまうことになります。
  user1:	user2
  user2:	user1
 通常は必要ないと思いますが、どうしてもuser1に来たメールをuser2に配送し、user2に来たメールuser1に配送したいという場合は、メールをループさせないために次のように定義します。
  user1:	\user2
  user2:	\user1
 アドレスの前に“\”をつけることで、それ以後のaliasesの再帰的解釈を行わなくなります。user1宛に送られたメールはuser2に配送され、user2にエイリアスでどのような定義がされていても無視されます。
 ただし、この設定を行う上で注意したいのは、ユーザのホームディレクトリにある.forwardファイルの解釈も行わなくなると言うことです。

転送しつつメールボックスに保存

 aliasesの機能は、一般的な言い方をすると、転送アドレスを作成することです。これまでは転送専用の書き方をしてきました。つまり、user1@hoge.comというアドレスに来たメールを違うアドレスにそのまま転送するやり方です。
  user1:	user2
 という指定は、次のようなイメージになります。
  ┌────────┐   ┌────┐   ┌───┐
  │user1@hoge.com  │-->│aliases │-->│user2 │
 └────────┘   └────┘   └───┘
 しかし、user1でも受け取りつつ、user2にも転送したいということはよくあると思います。そういう場合は、次のように指定します。
  user1:	\user1,user2
 このように、user1の前に“\”をつけて定義します。“\”をつけて定義するとaliasesの再帰的な解釈を行わなくなります。こうすることで、次のように、1通のメールを2つのメールボックスに保存することができます。
  ┌────────┐   ┌────┐   ┌───┐
  │user1@hoge.com  │-->│aliases │-->│user1 │
 └────────┘   └────┘ │ └───┘
                     │ ┌───┐
                     └>│user2 │
                       └───┘
プログラムを起動する

 aliasesファイルでは、メールを受け取ったときにそのメールをプログラムに渡すことができます。つまり、メールを受け取ったタイミングで特定のプログラムを起動することができるです。この仕組みは、メーリングリストシステムや自動応答メールなどのシステムで利用されます。
 定義方法は、次のようになります。
  |/usr/local/fml/fml.pl
 プログラムのパスの前にパイプ記号(|)をつけて指定します。もし、プログラムに引数がある場合は、次のどちらかのように、ダブルクォーテーションで全体をクォートする必要があります。
  |"/usr/local/fml/fml.pl arg"
  "|/usr/local/fml/fml.pl arg"
 この機能は大変便利なのですが、ちょっとしたミスで重大なセキュリティホールを生む可能性がありますので、使用には十分注意が必要です。まちがっても、任意のプログラムが実行できるようなプログラム(例えば、shやPerl、Rubyなど)を指定してはいけません。
 aliasesファイルだけでなく、ユーザが個別に持つ.forwardや:include:で読み込まれるファイルでも、このようにプログラムを起動することができます。しかし、この機能は大変危険です。ユーザが個別に持つ.forwardファイルからの実行も可能なため、ユーザの思わぬミスがセキュリティホールにつながりかねません。そこで、管理者が許可した安全なプログラム以外は実行できないように制限することができます。プログラムの実行権限は、smrshによって提供されています。

リダイレクト

 aliasesの特別な機能として、リダイレクトというものがあります。あるアドレスがなくなり、別のアドレスに変更された際に、変更後のアドレスを通知する機能です。aliasesファイルに
  user: user@new.address.REDIRECT
と書いておくと、”551 User has moved; please try <user@new.address>”というメッセージが送り返されます。
 この機能を利用するには、.mcファイルに以下を追加します。デフォルトはOFFになっています。
  FEATURE(`redirect')
データベースの自動再構築

 aliasesファイルを変更した際に、データベースを自動的に再構築してくれる機能があります。この機能を有効にするには、以下を.mcファイルに追加します。
  define(`confAUTO_REBUILD')dnl
 しかし、このオプションはDoS攻撃の標的になる可能性があるため、将来のバージョンでは削除されることが決まっています。初期設定はもちろんOFFです。
 また、以下の定義を追加すると、newaliasesを実行する際にaliasesに登録されている全メールアドレスのドメイン部がDNSで引けるかどうかチェックを行います。しかし、この定義はnewaliasesの実行を非常に遅くするため、あまりお勧めしません。
  define(`confAUTO_ALIASES')
aliasesファイルのパスを変更する

 aliasesファイルのパスを変更するには、ALIAS_FILEで定義します。
  define(`ALIAS_FILE',`/etc/mail/aliases')dnl
 実は、aliasesファイルはカンマで区切ることで複数のファイルを指定することができます(ただし、これはあまり使われない機能です)。必要な場合のみ利用するようにしましょう。複数指定する場合には、次のように指定します。
  define(`ALIAS_FILE',`/etc/mail/aliases,/etc/mail/nextaliases')dnl
.forwardファイル

 メールが各ユーザに配送される際、メールボックスに格納する前に.forwardファイルを解釈します。例えば、user1にメールが配送されるとき、user1のホームディレクトリにある.forwardファイルを解釈します。.forwardファイルは、aliasesの:include:と同じように処理されます。
 ただし、aliasesでアドレスの前に“\”をつけた場合は、その後、.forwardファイルを含むエイリアスファイルの解釈の対象から外されます。ユーザ名の前に“\”をつけたユーザの.forwardファイルは解釈されず、そのユーザ宛のメールはメールボックスへ直接格納されてしまいます。
 .forwardファイルで、メールを自分のメールボックスに配送しながら、別のメールアドレスに転送するように設定するには、次のようにします。
  \user1,user1@otherdomain.com
 1行に1つずつ定義することもできます。
  \user1
  user1@hoge.com
 もちろん、:include:やプログラムを実行することもできます。
 また、“#”で始まる行はコメント行として無視されます。
  \user1
  user1@otherdomain.com
  # ML
  |"/usr/local/fml/fml.pl /home/user1/ml/mlusers"
  :include:/home/user1/forward_address_file
 .forwardファイルから、メールを通常のメールスプールとは別のファイルに直接追加することもできます。次のリストの1行目の指定はローカルのメールスプールに保存する設定です。2行目の指定は、メールのコピーを/home/user1/mail.backupというファイルに保存する設定です。V8以降のsendmailでは、ファイルロック機構を備えているため、安全にファイルに追加することができます。
  \user1
  /home/user1/mail.backup
 また、procmailというプログラムを利用すれば、メールを個別のフォルダに振り分けたり、条件に従ってメールを転送したりすることができます。
 しかし、procmailはユーザ名をコマンドラインの引数として指定しないので、sendmailにとってアドレスが一意となるようにダミーのシェルコメントが必要になります。なぜ、このようなことをしなければならないかについては、重複メールを取り除くを参照して下さい。
  "|exec /usr/bin/procmail #user1"
 ただし、sendmail V8からは、.forwardファイルからプログラムを実行するためには、有効なログインシェルが必要になりました。有効なログインシェルを持たない(/bin/nologinや/bin/false等)ユーザは、forwardファイルからプログラムを実行することはできません。

.forwardファイルの種類

 あまり知られていませんが、.forwardファイルにはいくつかの種類があります。あるユーザにメールを配送する際には、そのユーザの名前のそれぞれの.forwardファイルの中から一番最初に見つかったものを処理します。
 どのような順番でどのようなファイルが定義されているかは、sendmail.cfのO ForwardPath行で確認することができます。
  # cat /etc/sendmail.cf | grep Forward
  # Forward file search path
  O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward
 O ForwardPath行の書式は、値を“:”で区切ります。$uはローカルユーザ、$hは処理中の受信者アドレスのホスト部、$wはドメイン名を省略したホスト名、$zはローカルユーザのホームディレクトリを示しています。
  O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward
 この例では、user1@hoge.comの場合、以下の順番でファイルを探します。
  /home/user1/.forward.mail.hoge.com
  /home/user1/.forward.hoge.com
  /home/user1/.forward.mail
  /home/user1/.forward
.forwardファイルが見つかってすぐに解釈をはじめるわけではありません。まずは、そのファイルが安全であるかどうかを判定します。そのファイルが所有者以外からの書き込みが可能になっていたりすると、不正に書き換えられ、攻撃に利用されている可能性もあるとして、解釈を中止します。

.forwardで利用するファイルの種類の指定

 .mcファイルで、.forwardの機能で利用するファイルの種類と順番を指定することができます。
  difine(`confFORWARD_PATH',$z/.forward.$w:$z/.forward')dnl
 デフォルトは、上記のとおりです。以下のマクロ変数を利用して変更することも可能です。.forwardの名称を変更して、ユーザに使用させないといった使い方もできます。
 なお、設定値で使えるマクロ変数は以下のとおりです。

設定値で使えるマクロ変数一覧
$u ローカルユーザ名
$h 処理中の受信者アドレスのホスト部
$w ドメインを省略したホスト名
$z ローカルユーザのホームディレクトリ


メールのループを防止する

 ユーザディレクトリの.forwardを許可していると、ときおりユーザの設定ミスで転送ループが発生してしまう場合があります。
 例えば、user1@hoge.comとuser1@otherdomain.comというメールアドレスがあったとして、user1@hoge.comが
  \user1, user1@otherdomain.com
 user1@otherdomain.comが
  \user1, user1@hoge.com
のような.forwardファイルを作成したとすると、転送ループが発生してしまいます。
 このような場合に、一時的にループを断ち切りたいときは、/etc/aliasesファイルに以下のように“\”をつけて定義します。
  user1:	\user1
 すると、ユーザディレクトリの.forwardファイルの解釈を行わないようになるため、そのホストのローカルのメールスプールにのみ配信されるようになります。

自動応答メール

 .forwardファイルでは、プログラムを指定して、プログラムにメールを渡すことができます。プログラムを指定するには、プログラムのパスの前にパイプ記号(|)をつけて指定します。.forwardで指定されるよくあるプログラムとして、vacationというものがあります。vacationはsendmailに同梱されて配布されているソフトウェアです。
 vacationは、メールを受け取るとメールの送信者宛に指定されたメッセージを返します。この仕組みを利用すると、長期不在時に不在の旨のメッセージを返したり、メールを受信した旨のメッセージを自動的に返したりすることができます。
  \user1
  "|/usr/bin/vacation user1"
 1行目は、ローカルのメールスプールにメールを保存します。2行目で、vacationを実行しています。引数にはユーザ名をしてします。

vacation

 vacationは、ホームディレクトリにある.vacation.msgというテキストファイルを送信者へメールで返信します。ただし、引数で指定したユーザ名が、届いたメールの“To:”、もしくは“Cc:”ヘッダにない場合は、自動応答を返しません。また、“postmaster”や“MAILER-DAEMON”などの特別なメールアドレスからのメールにも自動応答を返しません。これは、メールのループを防ぐためです。この他にも、送られてきたメールの“Precedence:”ヘッダが“bulk”や“junk”であるメールにも自動応答は返しません(Precedence:ヘッダは、メールの重要度をユーザが指定するヘッダです)。
 受け取ったメールの送信者のアドレスや自動返信日時などは、ユーザのホームディレクトリにある.vacation.dbファイルで保存されています。このファイルは、データベースファイルですので、以下のようにして初期化する必要があります。
  $ /usr/bin/vacation -i
 初期化の作業は、vacationの設定を.forwardファイルに追加する前に、必ず1回は行っておく必要があります。
 また、vacation.dbファイルの中身を確認するには、次のようにします。
  $ /usr/bin/vacation -l
 自動応答に使われる.vacation.msgファイルは、(ヘッダと含む)完全なメッセージである必要があります。以下に例を示します。
  # .vacation.msgの例
  From: user1@hoge.com
  Subject: Thank you for your mail
  Cntent-Type: text/plain; charset=iso-2002-jp
  X-Mialer: vacation
  ご連絡ありがとうございます。
 24時間以内にお返事させていただきます。お急ぎの場合は、
  ....@otherdomain.ne.jpまで連絡願います。
  --user1
 メッセージは、必ずJISコード(ISO-2022-JP)で保存します。EUCなどで保存してしまうとメールが文字化けしてしまいます。また、サブジェクトに日本語を指定したい場合は、MIMEでエンコードしておく必要があります。
 サブジェクトをMIMEエンコードする最も簡単な作成方法は、一度メールソフトでメールを送り、それを受信したものからヘッダを抜き出して利用することです。しかし、メールソフトによっては、受信時にサブジェクトをデコードしてしまいます(ただし、メールソフト上の表示はデコードされていても、メールボックスファイルを直接テキストエディタで開くと、デコードされていないこともあります。)その場合は、デコードしないメールソフトを探すか、英語のサブジェクトを使うなどの工夫が必要です。

起動できるプログラムを制御する(smrsh)

 sendmailでは、/etc/aliasesファイルや.forwardファイルなどからメールを受け取るときにプログラムを起動することが可能であることは説明しました。そして、そのプログラムにメールを渡すことができます。この機能を利用することで、メールを処理する様々なプログラムを利用できるようになります。しかし、このことは、簡単なことでセキュリティホールを生んでしまう危険性を持っています。
 ユーザの.forwardファイルなどを書き換えて、不正なプログラムを実行する攻撃は昔から行われてきました。メールが届くたびにそのコマンドを実行するように、.forwardを不正に書き換えることもできてしまいます。賢い攻撃者(クラッカー)なら、ユーザに気づかれないようにメールをメールボックスに配送しながら不正なプログラムを実行するような設定をするでしょう。その結果、攻撃を非常に見つけにくいものとすることができます。定期的な実行であれば管理者も不審に思うかもしれませんが、メールが届くタイミングというランダムな時間で行われるものだと、ログを見ても気づかない可能性があります。
 こういった攻撃を防ぐために。、sendmailではsmrsh(sendmail restricted shell)というプログラムが用意されています。smrshはシェルプログラムで、smrshを利用すると管理者が許可した特定のコマンドやプログラム以外は実行できなくなります。その結果、ユーザやクラックが作成した危険なプログラムの実行を禁止することができます。また、smrshで実行できるプログラムを制限しておけば、今後、セキュリティホールが見つかった場合などの対応がやりやすくなります。
 なお、smashはsendmailに同梱されており、Red Hat Linuxの場合は自動的にインストールされます。

smrshの使い方

 smrshを有効にすると、sendmailからプログラムを実行する際のシェルがすべてsmrshに変更されます。例えば.forwardファイルに
  |"/home/user1/bin/ml.pl arg"
というような記述があったとします。
 すると、smrshは/home/user1/bin/ml.plを探さずに、/etc/smrsh(Red Hat Linuxの場合)ディレクトリからそのプログラムを探します。つまり、この場合は、/etc/smrsh/ml.plを探すわけです。この/etc/smrshディレクトリに指定したプログラムがなければ、smrshはプログラムを起動しません。
 起動できなかった場合は、次のようなエラーを出力します。
  smrsh: ml.pl not available for sendmail programs
 smrshからプログラムを起動できるようにするには、/etc/smrshにsmrshから起動させたいプログラムのシンボリックリンクを作成します(またはコピーします)。
  ln -s /home/user1/bin/ml.pl /etc/smrsh/
 なお、smrshからの起動を許可するプログラムは、必ずセキュリティホールや不具合がないかを確認する必要があります。また、PerlやRuby、bashなど、任意のプログラムを実行できるようなプログラムをsmrshに登録してはいけません。そのようなプログラムを登録してしまうと、smrshで制限している意味がありません。
 自作のプログラムを登録する際も同様に、必ず任意のプログラムが起動できないことを確認する必要があります。このほかsmrshは、ls;ls -la;のように、“;”で区切って複数のプログラムを起動するような設定も拒否します。

smrshを使う

 smrshを利用するには、.mcファイルで
  FEATURE(`smrsh')dnl
とします。
 これをsendmail.cfに変換すると、次のように定義されます。
  Mprog, P=/usr/sbin/smash, ....
“M”で始まる行はメーラの指定です。“M”の次に“prog”と書いてあることから、この行がprogメーラを定義していることが分かります。このように、smrshはprogメーラに指定されます。
 また、confEBINDIRsmrshのディレクトリを変更することができます。
  define(`confEBINDIR',`/usr/sbin')dnl
 この場合、/usr/sbinディレクトリに定義されます。デフォルトのディレクトリ(confEBINDIRでディレクトリを指定しない場合)では、/usr/libexecです。
 smrshがプログラムを探すディレクトリが分からない場合は、
  # man smrsh
のFILESセクションを参照して下さい。
 また、smrshがプログラムを探すディレクトリを変更した場合には、smrshのソースファイルsmrdh.cを編集する必要があります。smrsh.cの
  # define CMDIR	"/usr/smrch"
 という行を
  # define CMDIR	"/usr/asm/sm.bin"
に変更して、コンパイルを行います。すると、プログラムを置くディレクトリを変更することができます。ただし、この場合は、manのFILESセクションは変更されませんので、忘れないようにしましょう。
 smrshは、大変有益なプログラムです。すべての場合において設定するように心がけておきましょう。

バーチャルドメインの設定

 最近は、個人で複数のドメインを所有していることも珍しくなくなってきました。汎用JPドメインや新g-TLDである.infoや.bizも始まり、1台で複数のドメインを運用したい状況が多くなってきています。
 また、企業などでは“企業名.co.jp”と“企業名.jp”、“ブランド名.com”などを利用しているかもしれませんし、事業所毎にドメイン名を変えている場合もあるかもしれません。そうした場合に、ドメイン名毎に1台のサーバを用意するというのは、現実的ではないでしょう。ネットワークの規模や状況にもよりますが、可能であれば、1台のサーバで複数のドメインを運用したいものです。
 sendmailでは、こうしたニーズに応えるために、1台のサーバで複数のドメインを運用する機能を提供しています。その機能を「バーチャルドメイン」を呼びます。

.mcファイルの基本的な定義

 sendmailでバーチャルドメインの機能を利用するには、.mcファイルに次の5行を指定するのが基本になります。
  # .mcファイルでのバーチャルドメインの定義
  01:define(`confCR_FILE',`/etc/mail/relay-domains')dnl
  02:define(`confCW_FILE',`/etc/mail/local-host-names')
  03:FEATURE(use_cw_file)dnl
  04:FEATURE(virtusertable, `hash -o /etc/mail/virtusertable')dnl
  05:FEATURE(`access_db', `hash -o /etc/mail/access_db')dnl
 この中で、最も重要なのが3行目と4行目です。
 3行目で、自ホストがメールを受け取るドメイン名を登録したファイルを利用することを宣言しています。通常は、DOMAIN(`generic')の中で宣言されるため、宣言し直す必要は特にありませんが、ここでは、分かりやすいように宣言しています。
 4行目で、virtusertableを有効にしています。virtusertableを使うと、バーチャルドメインのメールアドレスと、実際のローカルユーザとの対応を定義することができるようになります。つまり、あるメールアドレス宛のメールを、どのユーザが受け取るかを指定することができるのです。詳しくはドメインごとにアドレスを発行するを参照して下さい。
 その他の行は、バーチャルドメインを利用する上で、必要な付帯的な機能や設定を定義しています。それぞれ、解説していきます。
 1行目で、リレーするリモートホストのドメイン名やIPアドレスを指定するファイル(relay-domains)のパスを定義しています。relay-domainsの利用方法については、あとの項で詳しく説明します。
 2行目は、3行目で設定した、自ホストで受け取るメールアドレスのドメイン名を指定するファイルを指定しています。ここで指定しているファイルはデフォルトのもの(local-host-names)ですが、変更することもできます。デフォルトの値は、/usr/share/sendmail-cf/m4/cfhead.m4で設定されています。なお、local-host-namesはV8.9以前はsendmail.cwというファイル名でした。
 5行目は、アクセスデータベースという、メールをリレーするかどうか、メールを受け取るかどうか、などのアクセス制限を行うデータベースファイルを指定しています。このファイルの利用方法についてはアクセスデータベースでのアクセス制限で詳しく説明します。
 なお、4行目と5行目は、設定ファイルにデータベースファイルが指定されています。ここではハッシュ形式です。-oという引数がついていますが、これは、すでに存在するファイルを引数として指定する際に指定します。

メールを受け取るドメイン名を指定する(local-host-names)

 自ホストで、メールを受け取るようにするには、まず、DNSのMXレコードが自ホストに向いている必要があります。しかし、MXレコードが向いているだけではメールを受け取ることはできません。何も設定しないと、メールの受け取りは拒否されます。
 メールをうまく受け取れるようにするには、local-host-namesファイルに受け取りたいドメイン名を追加します。
  hoge.com
  hoge.co.jp
 このファイルは、テキストファイルなのでデータベースに変換する必要はありません。しかし、設定が終わったら、sendmailを再起動する必要があります。

ドメインごとにアドレスを発行する(virtusertable)

 実は、local-host-namesに受け取るべきドメイン名を設定するだけで、複数のドメインでメールを受け取れるようになります。では、virtusertableはどうして設定する必要があるのでしょうか?
 例えば、“info@ドメイン名”というアドレスを作りたいとします。そのためには、まずinfoというユーザを作成します。すると、local-host-namesで“hoge.com”、“hoge.co.jp”が登録されていれば、info@hoge.comというメールアドレス宛のメールをinfoというユーザのメールボックスで受け取ることができます。しかし、同時にinfo@hoge.co.jpというめーるあどれすのメールも受け取れるようになってしまいます。どういうことかわかるでしょうか?
 hoge.comを使っているユーザと、hoge.co.jpを使っているユーザは異なる場合があります。infoのように、汎用性の高いメールアドレスはどちらのユーザも使いたいと主張するでしょう。しかし、現実には“info”というアカウント名を取得したユーザしか利用することはできません。
 この問題を解決するのが、virtusertableという機能です。virtusrtableは、メールアドレスと受け取るユーザ名の対応表です。virtusertableを使えば、info@hoge.comを受け取るユーザとinfo@hoge.co.jpを受け取るユーザを、別々に指定することができるようになります。

virtusertableの設定

 virtusertableを設定するには、/etd/mail/virtusertableというテキストファイルを編集します。virtusertableはテキストファイルとして指定されているので、設定が終わったら、データベースファイルに変換する必要があります。
  # virtusertableの変換
  makemap hash /etd/mail/virtusertable < /etd/mail/virtusertable
 変換後は、virtusertable.dbというファイル名になります。
 では、virtusertableに設定を行ってみましょう。以下の設定例をもとに解説をしていきます
  # virtusertableの設定例
  01:info@hoge.com		hogeuser1
  02:info@hoge.co.jp	hogecouser2
  03:aya@hoge.co.jp	error:nouser No such user here
  04:sakura@hoge.co.jp	error:D.S.N:unavailable Address invalid
  05:@hoge.com		hogeuser1
  06:@hoge.co.jp		admin@otherhost.jp
 このように設定を行うと、次のような動作をします。

  info@hoge.com宛のメールはhogeuser1というローカルユーザに配送する。
  info@hoge.co.jp宛のメールはhogecouser2というローカルユーザに配送する。
  aya@hoge.co.jp宛のメールは指定のエラーメッセージとともにエラーを返す。
  sakura@hoge.co.jp宛のメールはDSNのエラーメッセージ付きでエラーを返す。

 右側の値には、ローカルユーザ名、エラー内容の他にも、メールアドレスを指定することができます。
 5行目の設定は特徴的で、@hoge.comに所属するメールアドレスのうち、virtusertableのほかの場所で指定されていないアドレスは、すべてhogeuser1というローカルユーザに配送されると言うことです。この機能は、プロバイダなどでは、よく「キャッチオール機能」や「デフォルト転送アドレス」などと呼ばれます。この機能をうまく利用すると、support@hoge.comとorder@hoge.comなどのメールアドレスを1つ1つ設定しなくても、この行を書くだけで、どのようなアドレスも受け取れるようになります。
 6行目で、@hoge.co.jp宛のメールを別のアドレスに転送しています。
 また、例えば
  @hoge2.co.jp	%1@hoge3.co.jp
と設定すると、sakura@hoge2.co.jp宛のメールはsakura@hoge3.co.jpへというように、あるドメイン宛のメールをそのまま同じユーザ名でドメインに転送すると言うことも可能です。
 さらに、例えば以下のような設定をしていて、user-detail@hoge2.co.jp宛のメールが届いたとします。
  user+*@hoge2.co.jp	newuser+%2@hoge3.co.jp
  gen+*@hoge2.co.jp	%2@hoge3.co.jp
  ;*@hoge2.co.jp		%1+%2@hoge3.co.jp
 user-detailはuser+*にマッチします。“*”にマッチした場合は、値で%2で参照することができます。そのため、このメールはnewuser+detail@hoge3.co.jp宛にメールが送られることになります。

実際にバーチャルドメインを設定する

 新しいドメインを追加する際の典型的な手順を解説します。ここでは、hoge.comとhoge1.co.jpが既に設定されており、そこにhoge3.co.jpを追加していくという設定で話を進めていきます。

1.local-host-namesにドメイン名を追加する
 まず、バーチャルドメインを追加するにはlocal-host-namesにドメイン名を追加します。local-host-namesはテキストファイルです。この最終行に、新しいドメインを追加します。
  hoge.com
  hoge.co.jp
  hoge3.co.jp
2.relay-domainsにリレー許可するドメインを追加する

 ドメイン名を追加したら、relay-domainsにリレー許可するドメインとして登録します。このファイルもテキストファイルです。最終行に、hoge3.co.jpを追加します。
  # 自分が使うプロバイダなども指定できます
  hoge.com
  hoge.co.jp
  hoge3.co.jp
3.アドレスを受け取るユーザを作成する。

 次に、新しいドメイン名のアドレスでメールを受け取るユーザを作成します。ここでは、dom1comというユーザを作成したとします(忘れずにパスワードも設定します)。
 ユーザを作成したら、新しく追加したドメインでメールを受け取れるように、virtusertableを使って設定します。virtusertableは、次のようになっています。
  # virtusertableの設定例
  info@hoge.com		hogeuser1
  info@hoge.co.jp		hogecouser2
  @hoge.com		hogeuser1
  @hoge.co.jp		admin@otherhost.jp
  @hoge3.co.jp		dom1com
 ここでは、xxxx@hoge3.co.jp宛に来たメールを、すべてdom1comというユーザが受け取れるようにしました。特定のメールアドレス宛のメールを別のユーザが受け取れるようにするには、別の定義を追加します。
 新しいドメインを追加したら、あとメールアドレスを追加する際には、local-host-namesなどにはさわらずに、virtusertableを編集するだけです。なお、virtusertableはデータベースファイルなので、makemapでデータベースに変換します。
  # makemap hash /etc/mail/virtusertable < /etc/mail/virtusertable
 設定が終わったら、sendmailを起動します。これで、新しいバーチャルドメインが利用できるようになりました。
  kill -HUP `head -1 /var/run/sendmail.pid`
 エラーなく再起動できればメールサーバの受け入れ準備が整いました。

 次に、DNSサーバのMXレコードをこのホストのIPアドレスになるように指定します。設定が変更できたら、DNSサーバを再起動します。ゾーンの設定を変更したら、徐々にDNS情報が浸透していき、メールサーバにメールが届くようになります。メールサーバの移転の場合は、このあと1週間程度は新旧両方のメールサーバに届くメールをチェックします。

不正リレーの防止

 古き良き時代は、メールサーバは互いにリレーをして、メールの目的のホストに届けていました。これは、オープンリレーと呼ばれるメールの配送方式です。
 しかし現在では、メールシステムも商業利用されており、一部の心ない人による広告メールや迷惑メールなどのスパムメールが問題となっています。オープンリレーとなっているメールサーバは、スパム送信者にとって格好の踏み台です。そのようなメールサーバでは、管理者が不在であったり、ログの管理がきちんとされていなかったりと、万が一メールの送信先から苦情が来たとしてもスパムの送信者まで苦情が届かないようにすることが容易だからです。
 このように、不正に利用されると本当に送りたいメールが送れなかったり、苦情やエラーメールが山ほど届くことになります。。最近ではメールサーバをオープンリレーとはせず、正当なユーザのみリレーを許可する、メールの不正リレーを制限するというのが一般的となっています。
 この節では、主に第3者リレーを防ぐための技術について、その概要を解説していきます。メールサーバを権限ない第3者に利用されないよう設定することは、管理者の重要な仕事の1つです。どのような技術があるか簡単に見てみましょう。

relay-domainsでアクセス制限

 /etc/mail/relay-domainsファイルは、リレーを許可するかどうかを指定するもっとも基本的な設定ファイルです。このファイルには、無条件にリレーを行ってもよいドメイン名やIPアドレスを指定します。逆に、このファイルに記述がないドメインからのリレーはすべて拒否することになります。
 relay-domainsファイルを利用することを明示的に宣言するため、.mcファイルに以下の行を追加します。必要であれば、ファイル名を変更することもできます。デフォルトの設定ファイルは、/usr/share/sendmail-cf/m4/cfhead.m4で設定されています。
  define(`confCR_FILE',`/etc/mail/relay-domains')dnl
relay-domainsの設定

 relay-domainsはテキストファイルです。このファイルには、リレーを許可するリモートホストのドメイン名を1行に1つずつ指定します。
  hoge.com
  hoge1.co.jp
  otherhost.ne.jp
 このように、relay-domainsに自分の利用しているプロバイダのドメイン名を指定することで、リモートホストから、メールクライアントソフトを使ってメールを送信することができます。
 しかし、上記のような指定だと、そのプロバイダ(ドメイン)に所属するすべてのユーザに送信を許可することになってしまうため、リモートホストからのメールの送信を許可する場合、通常はこの方法を用いません。リモートホストからのメールを送信できるようにするためには、必ずSMTP認証などを利用する必要があります。これについてはSMTP認証(SMTP AUTH)を参照して下さい。
 なお、relay-domainsの設定を変更したら、必ずsendmailを再起動します。

自ホストのリレーを許可する

 デフォルトの設定では、自ホストからのリレーもすべて拒否されてしまいます。プログラムからSMTP接続する場合や、メールクライアントをホスト上で動かした際にリレーができるように、自ホストのすべてのIPアドレスをrelay-domainsに定義しておきます。
  # relay-domainsの設定例
  192.168.0.1
  192.168.0.2
  192.168.0.3
  hoge.com
  hoge.co.jp
  otherhost.ne.jp
アクセスデータベースでのでアクセス制限

 Sendmail 8.9以降からはrelay-domainsに加え、accessデータベースで柔軟なアクセス制限が可能になりました。
 リレー元のリモートホストやFromアドレスでの制限が一般的ですが、そのほかにも、メールアドレスやIPアドレスごとにリレーの許可や破棄、エラーなどを細かく設定することができます。
 accessデータベースを有効にするには、.mdファイルに、以下の定義を追加します。
  define(`access_db',`hash -o /etc/mail/access')dnl
accessファイルの設定

 では、accessファイルの実際の設定を見ていきましょう。
  # accessファイルの設定例
  01: badspammer.com		550 Go away and don't spam us anymore
  02: tux.badspammer.com		OK
  03: spam@badspammer2.com		REJECT
  04: 192.168.0			RELAY
 この例では、まず1行目でbadspammer.comからのメールはすべて、“550”RFC821準拠のエラーコードを返し、メールを拒否しています。badspammer.comと指定すると、badspammer.com以下の、サブドメインのホストからの接続もすべて拒否します。
 ただし、2行目でtux.badspammer.comからのメールだけは、例外で受け取るように設定しています。OKという指定は、拒否している中から一部だけ許可したいといった場合に利用します。
 3行目で、spam@badspammer2.comからのメールはすべて受け取りを拒否しています。
 4行目で、192.168.0.0/24(つまり、192.168.0.0~192.168.0.255のすべてのIPアドレス)からのメールはすべてリレーするとしています。IPアドレスで後ろを省略すると、そのIPアドレス、すべてを対象にすることができます。

/etc/mail/accessに指定できる値
OK ドメインネームが解決できない場合や他のルールセットが拒絶していても受け付けるようにする
RELAY SMTPのリレーを許可する(OKと同じ機能も含む)
REJECT メールの受け取りを拒否する
DISCARD メッセージを破棄する
###"any text" ###にはRFC821に準拠したエラーコードを指定。"any text"には、エラーメッセージを指定する。


 /etc/mail/accessはデータベースファイルなので、編集が終わったら、テキストファイルからデータベースファイルに変換します。
  # makemap hash /etc/mail/access < /etc/mail/access
 設定が完了したら、sendmailを再起動します。

SMTP認証(SMTP AUTH)

 relay-domainsやaccessの設定だけでは、リレーを不特定多数に適切に許可することはできません。プロバイダやドメインごとにリレー許可するしかありません。しかし、そうすると、かなり多くの人にリレーを許可することになります。そこで、不特定多数の人たちに適切に許可を与えるために考え出されたのが、SMTPに認証の仕組みを組み込むSMTP認証です。SMTP認証には、その認証方式として、

LOGIN
PLAIN
CRAM-MD5
DIGEST-MD5

などの種類があります。
 なお、サーバとクライアントソフト(メールソフト)の両方がSMTP認証に対応していても、サーバとクライアントソフトで同じ認証方式をサポートしていなければ、認証が成功しないため注意が必要です。

SMTP認証の仕組み

 SMTP認証は、下図のような仕組みになります。
   この方式で認証したいんだけど   対応している認証方式はこれだよ!
  ┌──────┐                            ┌──────┐
  │            │  ───────────>  │            │
  │クライアント│                            │   サーバ   │
  │            │  <───────────  │            │
  └──────┘     SMTP認証のユーザID、   └──────┘
                       パスワードの送信     OK
            SMTPの認証方式が成功
              │
              ∨
            SMTPセッションの開始
 SMTP認証にはいくつもの認証方式があるため、最初にクライアントとサーバの両方でサポートされている認証方式を探します。
 まず、サーバは自分がサポートしている認証方式のリストをクライアントに提示します。クライアントとはその中から、自分がサポートしている認証方式の中でもっとも強力な認証方式を選んでサーバに通知します。サーバよりその認証方式でを受け入れることができるという回答を得られてから、クライアントはその認証方式で個人認証を行います。
 同じ方式が見つからなければ、通常のリレー制限の対象となります。配送先がローカルであればほとんど無条件で受け入れます。配送先がリモートである場合は、relay-domainsやaccessファイルなどでリレーが許可されているかを判断します。つまり、認証がうまくいかなくても、配送先がローカルである場合とaccessファイルなどでリレーが許可されている場合はメールの送信を受け入れます。なお、認証には、通常のUNIXログインパスワードではなく、SMTP認証専用のユーザIDおよびパスワードを使用します。








重複メールを取り除く

 例えば、次のようにエイリアスが定義されているとします。
  info:		kanami
  supporot:	kanami,sakura
 ここに、次のようなメールが送ることを考えます。
  To: info@hoge.com
  Cc: supporot@hoge.com
  From: user@domain.jp
  Subject: Mail Send
  Dear Staff,
  Thank you.
  .
 To:にinfoを指定し、Ccにsupportを指定します。このようなメールは。お客様などからよく来ることがあるかと思います。
 単純にエイリアスを解釈すると、infoはkanamiというユーザにメールを配送します。また、supportはkanamiというユーザとsakuraをいうユーザにメールを配送します。すると、kanamiには2通のメールが配送されてしまいます。
  ┌──────────────┐
  │  info     -->  kanami   │
  │                            │
  │  support  -┬>  kanami   │
  │             └>  sakura   │
  └──────────────┘
 同じ内容のメールを2通受け取っても1通は削除するだけです。メールソフトのメールボックスに邪魔なメールが溜まりますし、良いことではありません。sendmailはこのことをよく考えてくれています。sendmailは、最終的に配送先が決まるまでエイリアスを再帰的に解釈します。配送先が決まると、その配送先の中に重複がないかをチェックします。
 その結果、例えば、infoから転送されたkanamiとsupportから転送されたkanamiという配送先が重複していることが分かると、sendmailは、この重複を取り除いてくれます。イメージとしては、下図のような感じです。
  ┌─────────────────────────────┐
  │  info     -->  kanami                                 │
  │                     ∥     -->  kanami(1通だけ届く) │
  │  support  -┬>  kanami                                 │
  │             └>  sakura   -->  sakura                │
  └─────────────────────────────┘
 この機能は大変便利なのですが、1つ大きな副作用があります。それは、sendmailが配送先がプログラムでもアドレスとして解釈してしまうことが原因です。次のように、複数ユーザが同じプログラムを利用していたとします。
  user1:	|/usr/bin/MDA
  user2:	|/usr/bin/MDA
 この状態で、user1とuser2にCcde同じメールが届いたとします。すると、sendmailは配送先が同じものだとしてメール1通を削除してしまいます。
 そのため、多くのメール配信エージェント(MDA)では、引数にユーザ名を付加するようにしてあります。つまり、次のように定義される場合が多くなります。
  user1:	|"/usr/bin/MDA user1"
  user2:	|"/usr/bin/MDA user2"
 sendmailで認識するアドレスは、ユーザ名など引数も含んだパスがアドレスとなるため、この配信先アドレスは重複したものとはなりません。
 しかし問題は、引数などを取らないMDAなどがあることです。引数を取らないMDAとして代表的なものにprocmailがあります。引数と取らないと、全て同じ配送先アドレスとして解釈されてしまいます。その結果、思ったとおりの動作をしてくれません。それを防ぐためには、ダミーのコメントを利用します。
  user1:	|"/usr/local/bin/procmail #user1"
  user2:	|"/usr/local/bin/procmail #user2"
 このようにすることで、sendmail側から見ると配送先アドレスが重複せず、実際にプログラムを実行するシェルからも、コメント以降は無視するため、影響はありません。