hnwの日記

モダンにGmailからメール送信


補足:Email::MIMEについては「モダンPerlの世界へようこそ:第20回 Email::Sender:メールを送信する|gihyo.jp … 技術評論社」の内容とかぶってました…。この記事によればEmail::Senderも既に安定してるみたいなので、Email::Sendを使っている本記事の内容はあまり意味がない気がします。


久々にPerlの話題です。「メールの送信 - モダンなPerl入門」にある通り、最近はEmail::MIME+Email::Sendでメールを送るのが流儀なんだそうです。*1


しかし、まだまだPerl使いの中でもモダンすぎるせいか、ネットを探しても利用例が少ない気がしました。特に、Gmailからメール送信したい場合にはEmail::Send::SMTPSSLまたはTLS認証を利用することになるんですが、その実例となると皆無に近い気がしましたので、そのあたりをまとめてみました。

まずはサンプルコード

#!/usr/local/bin/perl -w
#
# 必須モジュール
#   Email::MIME;
#   Email::Send;
#   Net::SMTP
#   Net::SMTP::SSL
#   MIME::Base64;
#   Authen::SASL;
use strict;
use warnings;
use utf8;
use Encode;
use Email::MIME;
use Email::MIME::Creator;
use Email::Send;

my $mailer = Email::Send->new(
    {
        mailer => 'SMTP',
        mailer_args => [
            Host => 'smtp.gmail.com',
            Port => 465,
            username => 'foo@example.com',
            password => 'bar',
            ssl => 1,
#            Debug => 1, # SMTPの通信内容が見えるので、デバッグに便利。
            ],
        });

my $mail = Email::MIME->create(
    header => [
        To      => 'baz@example.com',
        From    => encode('MIME-Header-ISO_2022_JP',
                          'Email::Sendのテスト <foo@example.com>'),
        Subject => encode('MIME-Header-ISO_2022_JP', 'テストですよ'),
    ],
    attributes => {
        content_type => 'text/plain',
        charset      => 'iso-2022-jp',
        encoding     => '7bit',
        # 下記設定で、UTF-8+Base64で送信できる。
        # charset      => 'utf-8',
        # encoding     => 'base64',
    },
    # bodyでなくbody_strを使うと、
    # attributesのcharset,encodingに応じて勝手にencodeしてくれる。
    body_str => 'テストなんです',
    );
$mailer->send($mail);


以下、「モダンなPerl入門」と異なる点を順に紹介します。

Email::Sendのmailerについて

「モダンなPerl入門」では、mailerとして'Sendmail'を指定して、Email::Send::Sendmailを利用していました。通常はこれが無難だと思います。


一方、自分でSMTP通信を行いたい場合は、mailerとして'SMTP'を指定すればEmail::Send::SMTPが使われます。mailerを変更すると受け取るmailer_argsも変わってきます。Email::Send::SMTPでは、ssl=>1を指定することで、SMTP over SSLを利用できます。また、Debug=>1も便利です。


他にEmail::Send::Qmailなんてのもありますね。

Email::MIME->create()について

「モダンなPerl入門」では触れられていませんが、Email::MIME->create()でattributesを定義した方がよさそうです。charset=>'iso-2022-jp'が無いとContent-Typeにcharsetが付かないので、環境によっては本文が読めないかもしれません。


また、シングルパートのメールを送る場合、partsを使うよりbodyまたはbody_strを使った方がシンプルかと思います。特に、body_strはattributesのcharset/encodingを見てエンコーディングの変換をよしなにやってくれるので、文字エンコーディングを変えて何度も実験するような場合は便利かもしれません。

Gmailについての補足

送信に利用するGmailアカウントと異なるFromを使うと、Gmailのアカウントもヘッダに記述されてしまったり、もしかしたら送信できなかったりすると思います。上記のサンプルコードは、example.comGoogle Appsアカウントが存在したときのコードだと思ってください。

おまけ:Email::Send::SMTPtlsについて

Email::Send::SMTPソースコードを見るとtls=>1というのが指定できそうなんですが、僕が実験した限りではうまく動きませんでした。たぶん書くとしたら下記のようになると思うんですが…。

my $mailer = Email::Send->new(
    {
        mailer => 'SMTP',
        mailer_args => [
            Host => 'smtp.gmail.com',
            Port => 587,
            User => 'foo@example.com',
            Password => 'bar',
            tls => 1,
            ],
        });

*1:Email::SendじゃなくてEmail::Senderを使えと言われても - soffritto::journal」によれば、Email::Sendもoldtypeになりつつあるようですが…