Perlで日本語(ISO-2022-JP)メールを送信(まとめ)
UTF-8で作成されたメール本文をMIME::Lite及びEncodeを使用してメールを送信をする。
そこで問題となってくるのが下記の3点。
1.チルダ(全角)等の文字化け("〜 ‖ − ¢ £ ¬ ")
2.機種依存文字が含まれていた場合の対応
3.MIME::Lite で smtp送信する場合、Return-Pathが有効にならない
1.チルダ(全角)等の文字化け("〜 ‖ − ¢ £ ¬ ")に関する解決方法:
これは有名らしいのですが、Encode::JPが採用している UnicodeConsortium の写像表 に問題があるとかで、
一部の文字が化けます。チルダとか。
しようがないので こんな風に対応しておきました。
my %map = (
"\x{ff5e}" => "\x{301c}", # 〜 (1-33, WAVE DASH)
"\x{2225}" => "\x{2016}", # ‖ (1-34, DOUBLE VERTICAL LINE)
"\x{ff0d}" => "\x{2212}", # − (1-61, MINUS SIGN)
"\x{ffe0}" => "\x{00a2}", # ¢ (1-81, CENT SIGN)
"\x{ffe1}" => "\x{00a3}", # £ (1-82, POUND SIGN)
"\x{ffe2}" => "\x{00ac}", # ¬ (2-44, NOT SIGN)
);
foreach (keys %map){
$val =~ s/$_/$map{$_}/g;
}
return $val;
もっとスマート?に置換を行なう場合はこの方法で、こっちのほうが恐らく早いです。
$val =~ tr/[\x{ff5e}\x{2225}\x{ff0d}\x{ffe0}\x{ffe1}\x{ffe2}]/[\x{301c}\x{2016}\x{2212}\x{00a2}\x{00a3}\x{00ac}]/;
2.機種依存文字が含まれていた場合の解決方法:
Unicodeの正規化を利用しました。
Unicode正規化に関しては下記ページを参考。
http://homepage1.nifty.com/nomenclator/unicode/normalization.htm
正規化形式に関しては今回 NFKCを利用しております。
以下が Perlのサンプルコード
use strict; use Encode; use Unicode::Normalize; my $val = "UTF-8の文字列"; # * MIME ヘッダー my $subject = Encode::encode( 'MIME-Header-ISO_2022_JP', NFKC( $val ) ); # * ISO-2022-JP $body = Encode::encode('iso-2022-jp', NFKC($val) ); 1;
3.MIME::Lite で smtp送信する場合、Return-Pathを有効にする方法:
smtpで送信する場合、Return-Pathヘッダー使えないらしい。
10分くらいソースを眺めていたんだけど、
どうも From の値を MAIL FROM で使ってると思われる。
sub send_by_smtp { my ($self, @args) = @_; ;# * 中略 my $from = $self->get('From'); ;# * 中略 ### Create SMTP client: require Net::SMTP; my $smtp = MIME::Lite::SMTP->new(@args) or Carp::croak("Failed to connect to mail server: $!\n"); ;# * ↓ココで $from をいれちゃってる $smtp->mail($from) or Carp::croak("SMTP MAIL command failed: $!\n".$smtp->message."\n"); ;# * 中略 1;
仕方が無いので、上のメソッドをオーバーライドして、
my $from = $self->get('Return-Path') || $self->get('From');
とかしてしまえばOKかな?