CGI プログラムからのメール送信 (1)

前へ << 全文検索 CGI プログラムからのメール送信 (2) >> 次へ

sendmail

メール送信を行う CGI プログラムを作成します。 メールを送るにしても色々な方法があるのですが、ここでは sendmail を例に上げます。

sendmail は、UNIX 界隈では有名なメール配送ソフトです。 メール受信機能と (SMTP サーバ)、メール送信機能の両方を持っています。 sendmail のメール送信機能を使う方法を説明します。

sendmail の簡単な使い方

まず、UNIX マシンにログインできる方は、 コマンドラインから実行してみましょう。 まず、sendmail のパスを捜します。
% which sendmail
/usr/sbin/sendmail
のように表示されたら OK です。OS によっては /usr/lib/sendmail の場合もありますし、もしかしたら sendmail が インストールされていない可能性もあります。 また、/usr/sbin や /usr/lib にパスが通っていないこともありますので、 頑張って探して下さい。
% sendmail to@hoge.fuga.com ← ここに宛先を書く
From: from@foo.bar.com (あなたのメールアドレス)
To: to@hoge.fuga.com (宛先のメールアドレス)
Subject: test
← 何も入力せず、すぐに ENTER キーを押す (空行)
Hello
This is test
.← . を入力して ENTER で終了
これで foo@bar.com 宛にメールが送られたはずです。 ただし、最初は自分自身に送るようにしましょう。

注意点は

エンベロープとヘッダ

「どうしてコマンドラインで宛先を指定たのに、さらにヘッダにも To: を書かなければいけないの?」と思ったあなた、するどい。 コマンドラインで指定したものは「エンベロープ」、つまり「本当の宛先」です。 一方、To: で指定したものは「見かけ上の宛先」です。
% sendmail to@hoge.fuga.com ← ここは to@hoge.fuga.com
From: from@foo.bar.com
To: usouso@uso.com ← ここは usouso@uso.com
Subject: test

Hello
This is test
.
とすると、このメールは誰宛に届くのでしょうか。 もちろん「本当の宛先」である「to@hoge.fuga.com」です。 ただし、そこに届いたメールの To: は「To: usouso@uso.com」と なっています。

要は、ヘッダの To: なんてのはメール配送に全く関係ないわけです。 メールはエンベロープの宛先に届けられるわけで、To: ヘッダ は 一切関係ありません。

「では、From: ヘッダもメール配送には関係ないの?」と思ったあなた、するどい。 その通りです。全く関係ありません。 仮に宛先のユーザが見付からず、エラーメールとなって返ってきた場合、 エラーメールは From: ヘッダ宛には返されません。 どこに届くかというと、上では指定しませんでしたが、 「エンベロープの From」宛に返されます。 sendmail は自分のいるホスト名を知っています (仮に from.com とします)。 さらに、sendmail を実行したユーザも知っています (仮に user1 とします)。 つまり、「エンベロープの From」は user1@from.com です。 エラーメールは user1@from.com 宛に返されます。

なぜこういうことができるかと言うと、メーリングリストを考えてみるといいでしょう。 FreeBSD のメーリングリストは、

To: FreeBSD-users-jp@jp.FreeBSD.org
From: 68user@X68000.startshop.co.jp
というヘッダで各メンバに配送されます。 ことがわかりますか? このメールは 68user@X68000.startshop.co.jp が FreeBSD-users-jp@jp.FreeBSD.org 宛に送り、さらに jp.FreeBSD.org の sendmail が各メンバに配送しているのです。 つまり、 なわけです。

ただ、ML のようにエンベロープとヘッダが違う場合もありますが、 普通はエンベロープとヘッダは同じになっているはずです。

ただし、他の部分に本当の送り主 (エンベロープの From) が記録されいてるので、 From ヘッダを偽称していたずらメールを送ろうなどと考えないように。

-t オプション

先に述べたように、本当の宛先はエンベロープで指定しますが、 普通はエンベロープとヘッダは同じにしているでしょう。 また、デフォルトでは To: ヘッダはもちろん、Cc: ヘッダや Bcc: ヘッダも 無視されます。 これではちょっと不便なので、ヘッダの部分を見て 勝手にエンベロープを設定してくれる -t オプションを使いましょう。 -t オプションを指定すると、コマンドラインで宛先を指定する必要はなくなります。
% sendmail -t ← 宛先を書かなくてよい
From: from@foo.bar.com
To: to@hoge.fuga.com ← ここがエンベロープとして扱われる
Cc: aa@bb.cc,dd@ee.ff ← Cc: や Bcc: も勝手に送ってくれる
Bcc: gg@hh.ii
Subject: test

Hello
This is test
.

-i オプション

上の例だと、`.' のみの行を送ることはできません。 sendmail がメールの終わりとみなして、終了してしまうからです。 -i オプションを使うと、`.' のみの行を送っても sendmail は終了しません。 では、メールの終わりをどうやって sendmail に伝えるかというと、 EOF (End Of File) です。ターミナル上からは Ctrl-D を押すと EOF が送られます。
% sendmail -i to@hoge.fuga.com
From: ...
To: ...
Subject: ...

hello.
. ←`.' のみの行を送っても終了しない
This is test.
(Ctrl-D) ← Ctrl-D で終了
あるいは、あらかじめファイルにヘッダとメッセージを書き込んでおいて、
% cat mail.txt ← mail.txt というファイルをあらかじめ作っておく
From: ...
(略)
.
This is test.
% sendmail -i to@hoge.fuga.com < mail.txt ← mail.txt の内容を sendmail に渡す
としてもよいでしょう。

perl スクリプトから sendmail を使う

というわけで、perl スクリプトからメールを送るには、

mail-1.pl

    1: #!/usr/local/bin/perl
    2: 
    3: $sendmail = '/usr/sbin/sendmail';
    4: 
    5: open(SENDMAIL,"| $sendmail -t -i");
    6: 
    7: print SENDMAIL <<'END';
    8: From: from@foo.bar.com
    9: To: to@hoge.fuga.com
   10: Cc: aa@bb.cc,dd@ee.ff
   11: Subject: test
   12: 
   13: Hello
   14: This is test
   15: END
   16: 
   17: close(SENDMAIL);
ということになります。 非常にありがちなミスとして、
print <<END;
としてしまうと、perl は @foo の部分を配列と見なしてしまい、
In string, @foo now must be written as \@foo at sample/perl/mail-1.cgi line 6, near "From: from@foo"
というエラーになります。
print <<'END';
と '〜' で囲むか、あるいは
From: from\@foo.bar.com
と、\ でエスケープしましょう。

なお、これは CGI プログラムではありません。 Content-type ヘッダを出力していないからです。 コマンドラインから実行して下さい。

ただし、まだまだたくさん問題点があります。 続きは次節で。

前へ << 全文検索 CGI プログラムからのメール送信 (2) >> 次へ

$Id: mail-1.html,v 1.4 2004/12/04 15:34:52 68user Exp $