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

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

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

メール送信のあれこれ

たとえばウェブアプリケーションでなにかの注文を受け取ったとき,あるいはシステム管理ツールでなにか異常を発見したとき,ユーザや管理者にメールを送れるようにしたい,というのはよくある要件です。昔はヒアドキュメントやテンプレートエンジンなどを使って送信したいメールを用意したあと,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プログラマ。先日『カクテルホントのうんちく話』(柴田書店)を上梓。最新刊は『ガリア戦記』(平凡社ライブラリー)。

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

コメント

コメントの記入