第4回

Text：情報技研

CGIからのメール送信を簡単に実現する
Mail::Senderモジュール
CPAN（Comprehensive Perl Archive Network）
は、Perlプログラムとドキュメントの膨大なコレクションである。プログラミングに便利な機能を寄せ集めたもので、さしずめ知恵の宝庫といえよう。
本連載では、CPANで4,000個以上提供されているPerlモジュールから便利なものを厳選し、その機能

http://www.cpan.org/を自分のPerlプログラムから使い、効率よくプログラミングする方法を解説する。

CGIからのメール送信

コード1

メール送信のサンプルコード（mail-sender.pl）#!/usr/bin/perl

今回は、ウェブの次によく使うメールの送信を行う機能を実現

use Mail::Sender;

しよう。メールの送信を行うモジュールはいくつかあるが、簡単にいろいろなメールを送信できるMail::Senderモジュールを使って$send = new Mail::Sender;

メールを送信するプログラミング例を解説していく。
$send->MailFile({Mail::SenderモジュールはPerl標準で利用できるモジュールではないため、まず 最 初 にインストール が 必 要 である。また、

smtp=> 'localhost',

to=> 'yourname@yourdomain',

Mail::Senderモジュールが内部で利用するMIME::Base64モジュsubject => 'Test Mail (with File)',ールもインストールしておく必要がある。

from=> 'myname@mydomain',msg=> "This is the test mail with file.\n".

file=> 'filename.zip',"It's send by Mail::Sender Perl module.\n",Mail::Senderを使った単純なメール送信サンプル});

まずはMail::Senderの機能を理解するために、添付ファイル付
if ($Mail::Sender::Error){

きメールを送信するサンプルプログラムを見てみよう（コード1）。

print $Mail::Sender::Error,"\n";実際にこのサンプルコードを実行する際には、宛て先（toの部}分）と送信元（fromの部分）のメールアドレスを変更し、smtpの部分でSendmailなどのSMTPサーバーのアドレスを指定する必要がある。このサンプルコードを実行するホストでSMTPサーバーが動作している場合はsmtpは「localhost」のままでよい。fileには添付して送信するファイルを指定しておく。
また、サンプルコードの「$Mail::Sender::Error」変数チェックをしているif文の部分では、メールの送信時にエラーがある場合にエラーの内容を表示するためのものである。うまくメールが送信されないときはエラーが表示されるので、それをチェックしよう。
実際にサンプルコードmail-sender.plで送信されたメッセージの内容をヘッダー部分も含めて見てみる（図1）。見づらくなるた
め「Received:」ヘッダーは省略してある。メールのへッダー部分を確認すると「X-Mailer」というヘッダーオプションにMail::Senderで送信された旨が書かれていることがわかる。
Mail::Senderモジュールを使わなければ、これらのへッダーをいちいち自分で生成しなければならない。添付ファイルがなければこれよりも簡単な内容にはなるが、それでも処理するコードの分量はそれなりになるだろう。へッダーの生成からファイルのエンコー ディン グ まで、これ だけ の 処 理 を 手 軽 に 行 えてしまう
Mail::Senderモジュールがいかに便利かがわかるだろう。

190 +++ iNTERNET magazine 2003.06 +++図1

mail-sender.plで送信されたメールの内容

インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D

実用的なサンプル：メール送信フォームの表示
次に、もう少し具体的なサンプルプログラムを実行してみよう。
ここでは、CGIフォームからメールを送信するということを行ってみる。もちろんメールにファイルを添付して送ることも可能で、添付するファイルもCGIでアップロードできるようにしてあるので、ブラウザーだけでメールを送信できる。
このサンプルプログラムは、これまでのようにメールの内容を入力するフォーム画面をCGIモジュールを利用して表示するスク
リプトと、フォームに入力されたデータを処理して実際にメールを送信するスクリプトの2つに分かれる。
まず、メールの内容を入力するページ用のサンプルコード（コー図2ド2）とその実行例（図2）を示す。

index.cgiの実行結果

これについてはこれまでと同様にCGIモジュールを利用してフォームを表示しているだけなので特に説明の必要もないだろう。
新しいこととしては、添付ファイルの指定のためにCGIアップロー

実用的なサンプル：メールの送信処理

ド機能を利用している点があるくらいである。
次に、フォームのデータを受け取り、実際にメールを送信するサ
コード2 メール入力フォーム表示のサンプルコード（index.cgi）

ンプルコードを示す（コード3）。最初に示したコード1で扱ったメールでは、メールの内容にアルファベットのascii文字しか使って#!/usr/bin/perlいなかったので単純な処理でよかったが、ここではより実用的な

use CGI qw(:standard);

ものとするために日本語の処理を行っているため、コードが若干

use CGI::Pretty;複雑になっている。
図2で示した入力でこのサンプルコードを実行させると図3の## 入力フォームの表示ような内容のメールが送信される。

print

メソッドの詳しい解説は後でするが、大まかな処理の流れを説

header(-charset=>'x-euc-jp'), start_html,h2('フォームからメールを送ってみよう'),明すると、次のようになる。

start_multipart_form(-action=>'mail-sender.cgi'),

・添付ファイルがない場合

table({border=>0},MailMsgメソッドでメールを送信する。

Tr([・添付ファイルがある場合td(['To:', textfield('to', '', 50),'←宛て先のアドレス（「,」で区切り複数可）']),td(['Cc:', textfield('cc', '', 50),'←同報送信のアドレス（「,」で区切り複数可）']),
td(['Subject:', textfield('subject', '', 50),

OpenMultipart→Body→Send→Attach→Closeの一連のメソッドを組み合わせて使ってメールを送信する。
添付ファイルがある場合でもMailFileメソッドを使わずに複数のメソッドを組み合わせる方法をとっているのは、本文に日本語を'←件名（日本語可）']),td(['From:', textfield('from', '', 50),使えるようにするためである。

'←送信者のアドレス']),td(['自分の名前:', textfield('name', '', 50),'←送信者の名前（日本語可）']),td(['添付ファイル:', filefield('file', '', 40)]),]),

メールで日本語を扱うための処理
それでは、もう少し詳しく説明していく。メールで日本語を使う
場合には、送信する際に日本語を7bitの文字列の形式に変換す),br('メールの本文:'), textarea('Message', '', 12, 70), p,ることが望まれる。そのため、ヘッダー部分である件名（Subject）

submit('メール送信'), reset('入力項目リセット'),

やアドレス（From、To、CC、BCCなど）に含まれる日本語はMIME

end_form, end_html;

エンコードし、本文は7bitのJISコードに変換する作業が必要となる。これを行うためにJcodeモジュールが活躍している。

インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D+++ iNTERNET magazine 2003.06 +++191

コード3 メール送信CGIのサンプルコード（mail-sender.cgi）

また、各パートごとに「Content-type:」を指定して文字コードを指定するために、OpenMultipartをはじめとする一連のメソッドを#!/usr/bin/perl

利用し、最初パートの本文では日本語を送れるように「ISO-2022-

use CGI qw(:standard);

JP」（7bitのJISコード）を指定し、次のパートの添付ファイルでは

use CGI::Pretty;

MIMEのBase64でエンコードされた「application/octet-stream」

use Mail::Sender;を指定している。MailFileを使わなかったのは、このようにパート

use Jcode;

ごとに「Content-type:」を指定したかったからだ。

use File::Path;
use File::Copy;

ファイルを添付するための処理## フォーム変数の処理$to= param('to');$cc= param('cc');

CGIでアップロードされた添付ファイルは、フォーム変数にファイルハンドルが渡される。そこで、ローカルのファイルを一時的に$subject = jcode(param('subject'))->mime_encode();オープンして、File::Copyモジュールを使ってファイルハンドルを$fromAddr = param('from');

指定して内容をローカルファイルにコピーする。コピーしたファイ$fromName = jcode(param('name'))->mime_encode();ルを送信してから一時ファイルを削除している。サンプルコードを$from

簡単にするために、ローカルの一時ファイルはmail-sender.cgiと= "$fromName <$fromAddr>";$message = jcode(param('Message'))->jis;$file= param('file');## ファイルの処理同じ場所に作成される。
エラー処理

open (FILE, ">$file");最後に、メールが正しく送信された場合はその旨を表示し、正copy ($file, \*FILE);

しく送信できなかった場合にはエラーであることを表示するとともに「$Mail::Sender::Error」の内容を表示する。

## メールの送信$send = new Mail::Sender;

なお、サンプルコードは短く簡単にするために、メールの送信

if ($file){

可／不可以外のエラー処理は特に行っていないことを最後にお$send->OpenMultipart({smtp => 'localhost', to => $to, cc => $cc,断りしておく。実際には、もっとしっかりとしたエラー処理が必要

from => $from, subject => $subject});になるだろう。

$send->Body('ISO-2022-jp','7bit','text/plain');$send->Send($message);$send->Attach({file => $file});$send->Close;## 一時ファイルの削除
rmtree($file);}else{$send->MailMsg({smtp => 'localhost', to => $to, cc => $cc,from => $from, charset => 'ISO-2022-jp',
subject => $subject, msg => $message})}## 結果の表示
print header(-charset=>'x-euc-jp'), start_html;
if ($Mail::Sender::Error){printh3('メールの送信は次のエラーにより失敗しました。'),$Mail::Sender::Error,"\n";}else{
print h3('メールを送信しました。');}
print end_html;
図3192 +++ iNTERNET magazine 2003.06 +++mail-sender.cgiで送信されるメールの内容例

インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D

Mail::Sender.pmモジュール
Eメールの送信

Mail::Sender.pmのココがスゴイ！

【カテゴリー】メールとニュース【バージョン】0.8.06【作者】Jan Krynicky氏【URL】http://search.cpan.org/author/JENDA/Mail-Sender0.8.06/

【引数】
・from

Mail::Sender.pmは、メールの送信を行うモジュールである。通
常のメールだけでなく、1つまたは複数の添付ファイルを添付したマルチパートのメールを送信することもできる。

送信元のEメールアドレス。
・replyto
返信先のEメールアドレス。

実 際 の SMTP（ Simple Mail Transfer Protocol）の 仕 様 や・to

SMTPサーバーの動作を意識することなく、普通のメーラーを使送信先のEメールアドレス。

うかのように（場合によってはある意味でメーラーよりも使いやす「,」で区切って複数指定可能。

い！）必要な情報を指定するだけで、簡単にメールを送信できる非・smtp常に便利なモジュールだといえる。

送信に利用するSMTPメールのFQDN名（ドメイン名を含む完全なホスト名）
も実際にMail::Senderが行っている動作を全部Perlで自分で書しくはIPアドレス。

こうとすると、図 1 や図 3 にあるようなメールヘッダーの生成、・subject

SMTPサーバープログラムへのデータの引き渡しなど、SMTPに件名。

関する正しい知識が必要になるだけでなく、非常に煩雑な作業が・headers必要になり、コードは長くなってしまう。さらに添付ファイルメールの送信となると、ファイルのエンコードから、マルチパートヘッダーの生成などまで処理する必要があり、さらに複雑になる。それらのオプションのヘッダー指定。
・message
メール本文（テキスト）。

処理をまったく意識しなくてもPerlから簡単にメールを送信できるというのは非常にありがたい。

【 名 前 付 き パ ラメー タ ー 】

Mail::Sender.pmのメソッド（1）い。また下記のパラメーターも名前付きパラメーターとして指定で上記の各パラメーターは「from =>」のように直接指定してもよきる。
Mail::Senderモジュールには多くのメソッドがあるが、最初のサンプルプログラム（コード1）
で示した添付ファイルがある場合に使うMailFileメソッドと、添付ファイルがない場合に使うMailMsg
メソッド（実際はこちらを使うことの方が多いだろう）を知っておけばたいていは困らないだろう。

・fake_from

受信側のメーラーに表示される送信元Eメールアドレス。
・fake_to

受信側のメーラーに表示される送信先Eメールアドレス。
・cc

MailMsgメソッドとMailFileメソッドはパラメーターを指定して呼カーボンコピーを送信するEメールアドレス。

び出すことでメール送信まですべて行ってくれる。ここで紹介する「,」で区切って複数指定可能。

もの以外にもMail::Senderにはさらに高度な機能があるが、それ・fake_cc

らについてはドキュメントを参照してほしい。

受信側のメーラーに表示されるカーボンコピー先Eメールアドレス。
・bcc

MailMsgメソッド

ブラインドカーボンコピーを送信するEメールアドレス。

Eメールを送信する。

「,」で区切って複数指定可能。

【構文】

・boundary

MailMsg([from [, replyto [, to [, smtp [, subject [,マルチパートメールの区切り文字列。

headers]]]]]], message)

指定しない場合は自動的に生成される。

インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D+++ iNTERNET magazine 2003.06 +++193

OpenMultipartメソッド

・multipart

マルチパートメールの送信を開始する。

マルチパート部分のMIMEタイプ。

【構文】

・type

マルチパートメールのMIMEタイプ。

OpenMultipart([from [, replyto [, to [, smtp [, subject[, headers [, boundary]]]]]]])

・ctype【引数】

通常のメールのMIMEタイプ。
通常は「text/plain」を使う。

引数はMailMsgメソッドの場合と同じ。
また、MailMsgメソッドの場合と同じ名前付きパラメーターも使用できる。

・encoding

メールのコンコード形式。

Bodyメソッド・charset

マルチパートメールの本文のヘッダーを送信する。

メールの文字コード。

【構文】

通常は7ビットJISコードのISO-2022-JPを使う。

Body([charset [, encoding [, content-type]]])・client【引数】

送信元のホスト名。

引数はMailMsgメソッドの場合と同じ。

・priority

また、MailMsgメソッドの場合と同じ名前付きパラメーターも使用できる。

優先度の指定。

MailFileメソッド

Sendメソッド

ファイルを添付してEメールを送信する。

メールの内容を送信する。

【構文】

【構文】

MailFile([from [, replyto [, to [, smtp [, subject [,Send(@strings)

headers]]]]]], message, files)

【引数】

【引数】

・@strings
送信する内容。

・files添付するファイル名。
「,」で区切って複数指定可能。

Attachメソッド
MIMEマルチパートメールの中の1つのパートとしてファイルを

files以外の引数はMailMsgメソッドの場合と同じ。
また、MailMsgメソッドの場合と同じ名前付きパラメーターも使用できる。

エンコードして送信する。
【構文】

Mail::Sender.pmのメソッド（2）Attach(description, ctype, encoding, disposition, file)【引数】

MailMsgとMailFileは、1つのメソッドでメール全体を送信できるが、マルチパートのメールの各パートのヘッダーを細かく指定したいときなどは、複数のメソッドを組み合わせてメールを送信でき

・description
このパートのタイトル。
・disposition

る。実用的なサンプル（コード3）のように、細かく文字コードなどこのパートのdisposition。

を指定する場合には、こちらの方法を使うことになるだろう。

指定しなければ「attachment; filename=ファイル名」となる。

次に説明するメソッドは、それぞれ単体で使うものではなく、組み・ctypeÅencodingÅfile合わせて順番に使うものだ。次に示すようなメソッドを組み合わせ

MailMsg、MailFileメソッドの場合と同じ。て使うことで、メール送信の各段階を細かくコントロールできる。

また、MailMsgメソッドの場合と同じ名前付きパラメーターも使用できる。

1.OpenMultipartメソッドで送信を開く。

Closeメソッド

2.Bodyメソッドで本文用ヘッダーを出力する。

メールを終了して送信する。

3.Sendメソッドで本文を出力する。

【構文】

4.Attachメソッドで添付ファイルを出力する。

Close

5.Closeメソッドで実際にメールを送信する。

194 +++ iNTERNET magazine 2003.06 +++インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D

MIME::Base64.pmモジュール
MIME Base64形式のエンコード・デコード

MIME::Base64.pmのココがスゴイ！！

【カテゴリー】メールとニュース【バージョン】2.18【作者】Gisle Aas氏
【URL】http://search.cpan.org/author/GAAS/MIME-Base642.18/

ファイルハンドルを指定すると、ファイルの内容をエンコードして返す。

データ列をMIME Base64形式の 7ビットのテキストコードにデコード／エンコードするためのモジュールだ。マルチパート形式【構文】
encode_base64(変換元文字列)のメールを処理するためには必須のモジュールといえる。Perl 5.8では標準で利用できるようになっている。

decode̲base64メソッド
指定した文字列をBase64でデコードした結果を返す。

MIME::Base64.pmのメソッド

ファイルハンドルを指定すると、ファイルの内容をデコードして返す。

encode̲base64メソッド【構文】

指定した文字列をBase64でエンコートした結果を返す。

decode_base64(変換元文字列)

Mail::CheckUser.pmモジュール
Eメールアドレスのチェック

Mail::CheckUser.pmのココがスゴイ！！

【カテゴリー】メールとニュース【バージョン】1.19【作者】Ilya Martynov氏【URL】http://search.cpan.org/author/ILYAM/MailCheckUser-1.19/【戻り値】
trueが返されるとそのメールアドレスは正しい。

最後に、メール関係のモジュールでちょっとしたものを追加で説明しておく。このMail::CheckUserモジュールは、指定したメール

last̲checkメソッド

アドレスが正しいかどうかを調べる。メールアドレスの記述形式のチェックといった簡単なことから、実際に送信しようとしているメ

check̲emailメソッドで確認した結果の詳しい情報を得る。

ールサーバーが存在するか、そのサーバーがメールを受け付けて【構文】

いるかといったチェックを行うことができる。今回のサンプルコー

last_check

ドでは行っていないが、現実には必要となるエラーチェックを行う【戻り値】

ために使うと便利だ。

{ ok => OK, code => CODE, reason => REASON }Mail::CheckUser.pmのメソッド

・CODE

check̲emailメソッド

・OKという形のハッシュ参照が返される。

確認の結果を示すコードの定数。

メールアドレスが正しいかどうかを確認する。
【構文】
check_email($email)trueならばメールアドレスは正しい。
・REASON
確認の結果を示すテキスト。

【引数】
・$email
チェックするメールアドレス。

CODEで返される定数や、Mail::CheckUserモジュールが利用する環境変数などについてはドキュメントを参照してほしい。

インターネットマガジン／株式会社インプレスR&D©1994-2007 Impress R&D+++ iNTERNET magazine 2003.06 +++195

［インターネットマガジン バックナンバーアーカイブ］ ご利用上の注意
この PDF ファイルは、株式会社インプレス R&D（株式会社インプレスから分割）が 1994 年～2006 年まで発行した月刊誌『インターネットマガジン』の誌面を PDF 化し、「インターネットマガジン バックナンバーアーカイブ」として以下のウェブサイト「All-in-One INTERNET magazine 2.0」で公開しているものです。

http://i.impressRD.jp/bn
このファイルをご利用いただくにあたり、下記の注意事項を必ずお読みください。
z 記載されている内容（技術解説、URL、団体・企業名、商品名、価格、プレゼント募集、アンケートなど）は発行当時のものです。
z 収録されている内容は著作権法上の保護を受けています。著作権はそれぞれの記事の著作者（執筆者、写真の撮影者、イラストの作成者、編集部など）が保持しています。
z 著作者から許諾が得られなかった著作物は収録されていない場合があります。
z このファイルやその内容を改変したり、商用を目的として再利用することはできません。あくまで個人や企業の非商用利用での閲覧、複製、送信に限られます。
z 収録されている内容を何らかの媒体に引用としてご利用する際は、出典として媒体名および月号、該当ページ番号、発行元（株式会社インプレス R&D）、コピーライトなどの情報をご明記ください。
z オリジナルの雑誌の発行時点では、株式会社インプレス R&D（当時は株式会社インプレス）と著作権者は内容が正確なものであるように最大限に努めましたが、すべての情報が完全に正確であることは保証できません。このファイルの内容に起因する直接的および間接的な損害に対して、一切の責任を負いません。お客様個人の責任においてご利用ください。

このファイルに関するお問い合わせ先
All-in-One INTERNET magazine 編集部
im-info@impress.co.jp
Copyright © 1994-2007 Impress R&D, an Impress Group company. All rights reserved.