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かな?