Email::Sender を使う上での罠

Email::Send で使われている Return::Value の最新版が読み込むだけで死ぬようになっていて、Moose から Moo に変わったしいよいよ Email::Sender に移行しなきゃと思い作業したのだけどその際にちょっとはまったのでメモ。

bcc が送信できない

理由と対応策が POD に載っている。ぼくは一つ目の例に倣って bcc が指定されていたら to にセットして送るようにしました。

RFC に違反するアドレスに送信できない

オプションで宛先を明示しないと $email のヘッダの中から to をパースしてくれるのだけど、その時に使われる Email::AddressRFC 違反のメールアドレスが取り除かれてしまう。これは2引数目(envelope)で以下のように宛先を明示すると回避できる。

sendmail(
    $email,
    +{ to => 'really-bad-address.....@example.com' },
);

to だけ指定すると cc が送信されない

to をパースする時に cc も同時にパースしているので、to を指定していると cc のパースも行なわれないので cc には送信されない。上でも示した部分の近く。これも Email::Address によるパースを回避したいならちゃんと指定する。

sendmail(
    $email,
    +{
        to => 'really-bad-address.....@example.com',
        cc => 'ccccccc@example.com',
    },
);

で、こうしてみるわけですがこれだと送信されない。envelope を指定していない場合に to をパースする時に同時に cc をパースして to に含めているのと同様に cc も envelope の to に入れなきゃだめ。

sendmail(
    $email,
    +{
        to => ['really-bad-address.....@example.com', 'ccccccc@example.com'],
    },
);

これでいけた。

Log::Minimal::COLOR の色を変更する

debugf が白地に赤でちょっと見辛かったので。

$Log::Minimal::DEFAULT_COLOR->{debug} = {
    text       => 'blue',
    background => 'black',
};

色名は Term::ANSIColor で使えるやつ。

    The recognized normal foreground color attributes (colors 0 to 7) are:

      black  red  green  yellow  blue  magenta  cyan  white

    The corresponding bright foreground color attributes (colors 8 to 15)
    are:

      bright_black  bright_red      bright_green  bright_yellow
      bright_blue   bright_magenta  bright_cyan   bright_white

Furl::S3 を使ってオブジェクトのコピー

Amazon S3 をごにょるモジュールといえば Net::Amazon::S3 とか Amazon::S3 とかがあるのだけれど、LWP::UserAgent 使ってたり Net:: の方は Moose だったりするので、最近は Furl::S3 を使ってる。Furl::S3 には put とか get の基本的なメソッドとバケットの操作ぐらいしか無いんだけど、認証用のヘッダをよしなにしてくれる request メソッドがあるので追加のヘッダを指定してあげれば大抵の S3 の操作はできる。と思う。で、バケットのオブジェクトを別のバケットにまるっとコピーする必要があったので Furl::S3 でやってみた(同一のバケットでもやり方は同じ)。$header は2つめの参考文献に載ってるやつを必要に応じて指定するといいです。

実際には Coro::Semaphore とか Coro::Select あたりと組み合わせて並列にやってます。

use Furl::S3;

my $furl = Furl::S3->new(%conf);

my $source_bucket = 'from';
my $source_key    = 'path/to/photo.jpg';

my $copy_source = "/$source_bucket/$source_key";

my $header = {
    'x-amz-copy-source' => $copy_source,
    'x-amz-acl'         => 'public-read',
    'content_type'      => 'image/jpeg',
};

my $dest_bucket = 'to';
my $dest_key    = 'path/to/dir/image.jpg';

my $res = $furl->request('PUT', $dest_bucket, $dest_key, undef, $header);

Test::WWW::Mechanize のテストがこける

入れようとしたのは Test::WWW::Mechanize 1.30。Test::LongString が 0.15 だと t/content_lacks.t がこける。0.14 にするとテストが通ってインストールできる。perl のバージョンは 5.12.2 と 5.12.3 で再現した。

$ cpanm http://search.cpan.org/CPAN/authors/id/R/RG/RGARCIA/Test-LongString-0.14.tar.gz
$ cpanm Test::WWW::Mechanize

OAuth::Lite::Consumer で access_token 取得時に token とか以外のパラメータを取得

access_token を取ってくるだけなら get_access_token を使えば良い。

my $access_token = $consumer->get_access_token(
    token    => $request_token,
    verifier => $verifier,
);

$access_token は OAuth::Lite::Token オブジェクトになっていて oauth_token, oauth_token_secret, oauth_callback_confirmed 以外のパラメータは捨てられてしまう。

Twitter の OAuth とかだと access_token 取得時に screen_name とかもパラメータに含まれるのでそっちも取りたい(cf. Authenticating Requests with OAuth | dev.twitter.com)。そんな場合は obtain_access_token を使う。

my $res = $consumer->obtain_access_token(
    token  => $request_token,
    params => +{
        oauth_verifier => $verifier,
    },
);
my $access_token = $res->token; # OAuth::Lite::Token
my $screen_name  = $res->param('screen_name');

$res は OAuth::Lite::Response オブジェクトになっていて、token で OAuth::Lite::Token が、param で他のパラメータが取れる。