モダンPerlの世界へようこそ
第20回 Email::Sender:メールを送信する
メール送信のあれこれ
たとえばウェブアプリケーションでなにかの注文を受け取ったとき,あるいはシステム管理ツールでなにか異常を発見したとき,ユーザや管理者にメールを送れるようにしたい,というのはよくある要件です。昔はヒアドキュメントやテンプレートエンジンなどを使って送信したいメールを用意したあと,sendmailへのパイプを開いてメールを流し込んでいたものですが,いまはメールの作成から送信まで,すべてモジュールを使って実現できるようになっています。
とはいえ,需要が大きいだけにメール関係のモジュールは山のようにあります。ディストリビューション(パッケージ)の数だけで500を数えますし,メール関係の名前がついたモジュールは現在CPANにアップロードされている7万以上ものモジュールのほぼ1割を占めるほどです。これではどれを使えばよいのかわからないという声があがるのも当然でしょう。
そこで今回はPerl Email Projectというコミュニティがおすすめするモジュールを中心に,モダンなメールの送信法をまとめてみます。
Perl Email Projectとは?
PEPことPerl Email Projectは,当時よく使われていた「Mail::」ないし「MIME::」で始まるモジュール群の不具合や複雑さに業を煮やしたサイモン・カズンズ(Simon Cozens)氏やリチャード・クランプ(Richard Clamp)氏,サイモン・ウィストウ(Simon Wistow)氏らが2003年頃に始めたプロジェクトです。いまでは新しいツールの作成にとどまらず,バグが放置されている古い関連モジュールのメンテナンスや,既知の問題とその解決策をまとめたりする作業も行われていますが,当初の目的は,Email::SimpleのPODにあるように「使うのもメンテも簡単な,無駄のない,高速で外部依存も最小限にとどめた,正しい」メール関係モジュールをつくることでした。PEPのモジュールは既存のモジュールとの混乱を避けるために「Email::」以下の名前空間にまとめられています。だから,モダンな実装が欲しければ基本的にはその名前空間にあるモジュール群を使っていけばよい,ということになります(逆にいうと,このプロジェクトに関係のないメール関連モジュールにはEmail::という名前をつけないほうがよいでしょう)。
Perl Email Projectが管理しているモジュールは,Task::Email::PEP::All,あるいはClass::DBIに依存しているEmail::Storeを外したTask::Email::PEP::NoStoreを使うとまとめてインストールできます。
> cpan Task::Email::PEP::NoStore
また,同プロジェクトのWikiにはおすすめモジュールの一覧などもまとまっています。
Email::MIMEを使ってメールを作成する
さて,今日の本題ですが,メールを送信するにはまずメールそのものを作成する必要があります。そのためのツール自体いくつもありますが,日常的な用途ではEmail::Simpleや,そのラッパであるEmail::MIMEを使うのがおすすめです(Email::Simpleでは添付ファイルなどの処理ができないので,ふつうはEmail::MIMEを使うことになるでしょう)。
Email::MIMEを使ってISO-2022-JPベースのごく一般的なメールを作成する場合はこのようになります。
use strict;
use warnings;
use utf8;
use Email::MIME;
use Email::MIME::Creator;
use Encode;
# use Encode::compat::MIME::Header::ISO_2022_JP; # perl < 5.8.8
my $email = Email::MIME->create(
header => [
From => encode('MIME-Header-ISO_2022_JP' => '"F.U." <foo@example.com>'),
To => encode('MIME-Header-ISO_2022_JP' => '"B.A." <bar@example.jp>'),
Subject => encode('MIME-Header-ISO_2022_JP' => 'タイトル'),
],
attributes => {
content_type => 'text/plain',
charset => 'ISO-2022-JP',
encoding => '7bit',
},
body => encode('iso-2022-jp' => '本文'),
);
# print $email->as_string;
headerには追加したいヘッダのフィールド名とその内容の組を列挙します。このフィールド名はそのままメールヘッダに流用されます(省略表記などはありません)。必須ヘッダのひとつであるDateヘッダについては,指定がなければEmail::MIME(や,Email::Simple)のほうで自動的に用意してくれます。特定の時間を指定したい場合はEmail::Date::Formatを使うのが簡単です。
use Email::Date::Format 'email_date'
my $email = Email::MIME->create(
header => [
Date => email_date( time - 60 * 60 ),
...,
],
body => '...',
);
また,Encodeのバージョンが2.11より古い場合はMIMEヘッダのISO-2022-JPエンコードに対応していません。Perl 5.8.8以降であればコアに入っていますが,それ以前のPerlを使っている方でEncodeをアップグレードできない場合は,Encode::compat::MIME::Header::ISO_2022_JPというモジュールをご利用ください。
単純な用途では特に指定する必要はありませんが,attributesを利用すると一部のヘッダを簡単に表記できます(attributesを使わずheaderのなかで直接指定してしまってもかまいません)。本稿執筆時点で対応しているキーはcontent_type,charset,encoding,disposition,name,filename,format,boundaryです。
bodyにはメール本文をスカラー,または配列リファレンスの形で渡せます。
なお,先日公開されたEmail::MIME 1.900以降,headerやbodyのかわりにheader_str,body_strというキーを使うと,attributesで指定したcharsetやencodingの値をもとに内部でエンコードしてくれるようになりました。これは,UTF-8のメールを送る際には非常に便利です。
use utf8;
my $email = Email::MIME->create(
header_str => [
From => '"F.U." <foo@example.com>',
To => '"B.A." <bar@example.jp>',
Subject => 'タイトル',
],
attributes => {
content_type => 'text/plain',
charset => 'UTF-8',
encoding => 'base64',
},
body_str => '本文',
);
ただし,body_strの方はこれでよいのですが,header_strについてはEncode::MIME::HeaderのエンコードがUTF-8にしか対応していないため,charsetの指定によらずUTF-8でエンコードされてしまいます。ISO-2022-JP,あるいは携帯電話向けにShift-JISなどのヘッダが必要な場合は,strのつかないheaderを使って自分でエンコードしたほうがよいでしょう(※1)。
- ※1
ISO-2022-JPについてはEmail::MIME::Creator::ISO_2022_JPというモジュールを用意しておきました。
モダンPerlの世界へようこそ
- 第27回 Test::Most:Test::Moreでは物足りなくなってきたら
- 第26回 ShipIt:モジュールのリリースをもっと手軽に
- 第25回 Module::Starter:モジュールを書くためのテンプレート
- 第24回 CPAN:Perl界の水先案内人
- 第23回 Module::Build:MakeMakerの後継者を目指して
- 第22回 Mojolicious::Lite:本当に簡単なウェブアプリがあればいいときは
- 第21回 KiokuDB:マッピングが複雑すぎると感じたら
- 第20回 Email::Sender:メールを送信する
- 第19回 Who's Who on IRC:Perl界の紳士録(IRC編)
- 第18回 local::lib:ふだんと違う環境でPerlを使う


