|
||||
|
|
Perlからメールを送信する
|
|
|
SMTPとは
SMTPとは ( Simple Mail Transfer Protocol ) の略でもともとはサーバ間でメールをやり取りするためのプロトコルですが、メールクライアント ( Outlook Expressなど ) がサーバに対してメールを送信する際にも利用されています。 信頼性があり、効率的にメールを転送することの出来るプロトコルです。 通常は TCPポート番号の 25番を使用します。
また SMTPの規定では7ビットコードとなりますので、正常にメールを送信するには7ビットのJISコードを用いなくてはいけません。 動作手順
次に示す手順のやり取りが、メールクライアントとメールサーバの間で行われます。
QUITコマンドが送信されると実際にメールが送信されます。私たちは意識する必要はありませんが、受信したサーバは他のユーザー宛であった場合、他のシステムとまた同様の手順で相手システムにメールを転送することになります。 ※サーバから送られるレスポンスは全て正常時のレスポンスになります。各コマンド、レスポンスはそれぞれ [ SMTPコマンド一覧 ] [ SMTP応答コード一覧 ] を参照してください。 SMTPのコマンド
応答コード
SMTPサーバからの応答は次のようなフォーマットになります。
コード3桁目 1 : コマンドは正常に受け付けられ、現在実行中です。 2 : コマンドは正常終了しました。 3 : コマンドは正常に受け付けられましたが、パラメータなどの指定が必要です。 4 : コマンドは正常に受け付けられませんでした。 5 : コマンドはこのシステムでは実行できません。 コード2桁目 0 : 3桁目がエラーを示す時に、文法的なエラーがある事を示します。 1 : この応答は情報を伝えるものです。 2 : TCPコネクションに関連した情報。 5 : メールシステムの状態を示します。 コード1桁目 : 2、3桁によってより詳しい内容を表わします。
メールのフォーマット
これまではサーバとのやり取りについて説明してきましたが、今回はメール本文のフォーマットについてです。(DATAコマンドの後に送信するデータ) 電子メールはヘッダ部と本文の二つから構成され、それぞれは空白行を境界線とします。本文についてはピリオド一つだけの行を含むことは出来ません。 これはSMTPのコマンドでDATAコマンドの後送信されるデータはピリオド一つだけの行を含むとそこでサーバ側ではメールの本文が終了したと勘違いしてしまうためです。
ヘッダ部は次の表にあるようなフィールドの集合で構成します。各フィールドは下記のようなフォーマットで最終フィールドが終了したら空白行を挿入しそこからメールの本文を開始します。 ヘッダ部のフォーマット
(フィールド名) :(フィールド内容)
socketとは
socketとはTCP ( SMTPで使用します ) で通信をする場合は、まず先立って socketを使ってコネクションを確立しなくてはいけません。 確立後は通常のファイルハンドル同様に入出力用の print/<>などを使って通信する事が可能になります。
Perlでのsocket作成法
1. Socketモジュールの輸入。このサンプルはSocketモジュールを使用してあるのでPerl5以上の対応ですPerl4では動きません。
use Socket;
2. getservbyname関数 を呼び出してそのサービスが使用するポート番号を取得しています。ここで'tcp'という文字を引数で渡していますがこれは異なるレイヤで使用されるプロトコルです。この [ tcp ] と呼ばれるプロトコルによって信頼性のある通信が実現できます。
$port = getservbyname('smtp','tcp');
3. ホスト名 ( inet_aton関数でパックされたIPアドレス ) とポート番号を構造体にパックして作成する。
$struct = sockaddr_in($port,inet_aton($server));
4. Socketの作成
socket(SH, PF_INET, SOCK_STREAM, 0);
5. 構造体の情報を元にサーバへ接続する。
nect(SH, $struct );
Perlでの記述
実際にPerlでの記述は次に記述しておきます、上で説明したSMTPサーバとのやり取りをする為に先ずSOCKETを作成しそれから [ 動作手順 ] で示したやり取りが始まります。 [ ソケット ] と [ 動作手順 ] の情報を元に下のコードを眺めて見てください。これがソケットの作成からSMTPを使った perlでのメール送信の手順になります。
[ smtp.pl ]
# ------------------------------------------------------- # # # SMTPメール送信サンプル # # ------------------------------------------------------- # # 【 Program name 】 # smtp.pl # ------------------------------------------------------- # # 【 更新履歴 】 # 2001/5/7 - 作成 # ------------------------------------------------------- # # # ソケットモジュ−ルの輸入 # use Socket; # ------------------------------------------------------- # # 接続情報の設定 # ------------------------------------------------------- # # # SMTPサーバ名、又はIPアドレス # $server = 'xxxxx.co.jp' ; # # 宛先 # $to = 'knave@excite.co.jp' ; # # 送信元 # $from = 'xxxxxxx@xxxxxxxxxx' ; # # 題名 # $subject = 'サンプルメール' ; # # 送信データ # $data = 'テストメール' ; # # 文字コード変換ライブラリの使用 # require './jcode.pl'; # ------------------------------------------------------- # # ヘッダ、データ部の作成 # ------------------------------------------------------- # $send_data = 'X-Mailer: SMTP Samle' . "\n"; $send_data .= 'MIME-Version: 1.0' . "\n"; $send_data .= 'Content-Type: text/plain; charset=iso-2022-jp' . "\n"; $send_data .= 'From: '. $from . '<'. $from .'>' . "\n"; $send_data .= 'To: '. $to . "\n"; $send_data .= 'Subject: ' . $subject . "\n"; $send_data .= "\n"; $send_data .= $data; # ------------------------------------------------------- # # SOCKETの作成 # ------------------------------------------------------- # # PORT番号を取得します $port = getservbyname('smtp','tcp'); # PORT、IPで構造体を作成する $struct = sockaddr_in($port,inet_aton($server)); # ソケットの生成 socket(SH, PF_INET, SOCK_STREAM, 0) || die("ソケットの生成失敗 $!") ; # 接続 connect(SH, $struct ) || die("接続失敗 $!") ; # ソケットのバッファリングは行わない select(SH); $| = 1; select(STDOUT); $respons = <SH> ; unless($respons =~ /^220/) { close(SH); die("接続失敗 $!") ; } # ------------------------------------------------------- # # コマンドの送信 # ------------------------------------------------------- # # -------- HELOコマンドの送信とレスポンスの確認 --------- # # コマンドの作成、送信 $command = "HELO $server\n"; print SH $command ; # レスポンスの受信、確認 $respons = <SH> ; &decode(\$respons) ; # レスポンスの確認 unless($respons =~ /^250/){ close(SH); die("HELOコマンド失敗 $!") ; } # -------- MAILコマンドの送信とレスポンスの確認 --------- # # コマンドの作成、送信 $command = "MAIL FROM:$from\n"; print SH $command ; # レスポンスの受信、確認 $respons = <SH> ; &decode(\$respons) ; unless($respons =~ /^250/){ print SH "RSET\n"; close(SH); die("MAILコマンド失敗 $!") ; } # -------- RCPTコマンドの送信とレスポンスの確認 --------- # # コマンドの作成、送信 $command = "RCPT TO:$to\n"; print SH $command ; # レスポンスの受信、確認 $respons = <SH> ; &decode(\$respons) ; unless($respons =~ /^25[0|1]/){ print SH "RSET\n"; close(SH); die("RCPTコマンド失敗 $!") ; } # -------- DATAコマンドの送信とレスポンスの確認 --------- # # コマンドの作成、送信 $command = "DATA\n"; print SH $command ; # レスポンスの受信、確認 $respons = <SH> ; &decode(\$respons) ; unless($respons =~ /^354/){ print SH "RSET\n"; close(SH); die("DATAコマンド失敗 $!") ; } # -------- ヘッダ、本文の送信とレスポンスの確認 --------- # # 文字コードの変換 &jcode'convert(*send_data,'jis'); # コマンドの作成、送信 $command = "$send_data\n.\n"; print SH $command ; # レスポンスの受信、確認 $respons = <SH> ; &decode(\$respons) ; unless($respons =~ /^250/){ print SH "RSET\n"; close(SH); die("本文、ヘッダ部送信失敗 $!") ; } # --------QUITコマンドの送信 -------- # # コマンドの作成、送信 $command = "QUIT\n"; print SH $command ; # --------切断 -------- # close(SH); select(STDOUT); print "MAILは正常に送信されました。\n"; # -------------------- # 改行コード変換 # -------------------- sub decode{ my $inf = $_[0]; $$inf =~ s/\x0D\x0A|\x0D|\x0A/\n/g; } オレンジで記述してある箇所は変更箇所になります。それぞれを設定してから実行してみてください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||