モダンPerlの世界へようこそ

第20回 Email::Sender:メールを送信する

この記事を読むのに必要な時間:およそ 5.5 分

Email::Sendの問題点

ところが,業務で大量にメールを処理する企業などで使われていくうちに,Email::Sendにはさまざまな問題があることがわかってきました。

たとえば,Email::Sendは内部でModule::Pluggableを使っているため,Email::Sendの名前空間のなかに独自の拡張モジュールが入っているとそれもすべて読み込んでしまうのですが,そのせいで一時期Jiftyがインストールされていると,Jifty用のテストモジュールを読み込んでしまうためにEmail::Sendのインストールが失敗するという問題が起こっていました。また,先ほど紹介したall_mailersを使う例のように,ひとつの方法で失敗したら次の方法を試す,というアプローチを取る場合,うっかりしているとEmail::Send::Testで大事なメールをすぐに消えてしまうテスト環境に送信してしまうようなことにもなりかねません。実際の送信を行うプラグインの設定は裏で使われているモジュールにそのまま渡すような形になっていたため,複数のプラグインを利用する際には設定の互換性も問題になりました。送信の途中でメールオブジェクトに手を入れて,特定の条件では特殊なヘッダを追加する,といったこともできるのですが,その変更はあとあとまで残ってしまうため,修正を元に戻す処理を書く必要もあります。値を返すのに使われているReturn::Valueというモジュールにはあまりに落とし穴が多かったため,2010年6月をもって廃止の警告を出すようにする,というアナウンスも行われています。

そのような実装面の問題だけでなく,たとえばメールニュースの送信のようにメールに書かれている送受信者と実際の送受信者が異なる場合の対処など,さまざまな実務上の要望に応えようと思ったとき,現在のEmail::Sendの設計では後方互換性を捨てない限り十分に対応しきれないといった設計上の問題もありました。

そのため,以前から新しいメール送信用モジュール作成の必要性は認識されていましたし,2007年のYAPC::NAでは現在50以上の関連モジュールを管理しているリカルド・シグネスRicardo Signes氏がPEPについての発表のなかで新しいプロジェクトの計画を公表していました。その実装はMIME::Liteを含むほかのさまざまなメール関連ツールのメンテナンスなどもあって遅れに遅れていたのですが,2008年末にはついに氏が勤務先のPobox社でさまざまな改造をほどこしていた私家版Email::Sendをもとにした新しいモジュールが登場しました。それが,現在Email::Sendにかわって推奨されているEmail::Senderです。

Email::Senderの使い方

Email::Senderを使うと,先ほどの例はこのように書き換えられます。

use strict;
use warnings;
use Email::Sender::Simple 'sendmail';
use Email::MIME;

my $email = Email::MIME->create(...);

sendmail($email);

これで,sendmailがあればsendmailで,なければローカルのSMTPサーバを使った送信が行われます。

外部のSMTPサーバを利用したい場合などは,トランスポート層を担当するモジュールのインスタンスを明示的に渡したり,環境変数で設定を切り替えることもできるようになっています。

use Email::Sender::Transport::SMTP;

my $transport = Email::Sender::Transport::SMTP->new(
  host => 'smtp.example.com',
  port => 587,
);

sendmail($email, { transport => $transport });

具体的に送信先を指定したい場合はこのようにします(指定がなければメールヘッダから取得されます)⁠

sendmail($email, { to => [qw( other@example.com )] });

エラーが発生した場合,例外が発生します。evalや,Try::Tinyのようなモジュールでトラップすると,$@(Try::Tinyの場合は$_)でエラー情報が格納されたオブジェクトを受け取れます。

use Try::Tiny;

try   { sendmail($email) }
catch { my $error = $_; warn $error->message };

特にエラーの内容を気にしない場合は,sendmail()のかわりにtry_to_sendmail()を使うと,例外のかわりに単に偽値を返すだけになります。

try_to_sendmail($email) or die "sendmail error!";

その他の使い方についてはEmail::Sender::Manual::QuickStartをご覧ください。

移行状況

Email::Senderの登場以降,Email::Sendの更新履歴などにはEmail::Senderへの移行をうながすメッセージが記されています。Email::SenderはMooseベースということもあり,CPANモジュールレベルではまだそれほど移行は進んでいないようですが,今後本格的なメール送信ツールをつくるのであれば,公式におすすめから外されたEmail::SendやMIME::Liteなどより,Email::Senderを使うほうが無難です。

著者プロフィール

石垣憲一(いしがきけんいち)

あるときは翻訳家。あるときはPerlプログラマ。先日『カクテルホントのうんちく話』(柴田書店)を上梓。最新刊は『ガリア戦記』(平凡社ライブラリー)。

URLhttp://d.hatena.ne.jp/charsbar/

コメント

コメントの記入