tomi-ruのモバイル日記

profile
記事とカテゴリ一覧はこちら

2008-08-01

メールの受信における本文のdecode

| 00:03 | はてなブックマーク - メールの受信における本文のdecode - tomi-ruのモバイル日記

http://mobilehacker.g.hatena.ne.jp/tokuhirom/20080729/1217321096

のように楽できると思って、メールから投稿できるものを作りかけてみたのだけど、問題がありました。メールは、送信時と受信時で使うエンコーディングが違う問題です。

Email::Address::JP::Mobile でたとえば au だと mail_encoding は x-sjis-kddi-auto を返しします。これは送信する時(encode)には良いのですが、受信の時(decode)はこれじゃなくて x-iso-2022-jp-kddi-auto あたりを使いたいところですよね。。

  • 送信も受信と同じエンコーディングを使えばいいじゃないか。つまり、auの場合送信で x-iso-2022-jp-kddi-auto を使えばいい? →なんか理由があってこれはおすすめとは言えなかった気がします。たしかauの絵文字しか使えないからとかだったような。
  • encodeはiso-2022-jpで、decodeはsjisでやるというエンコーディングをつくるのは明らかにきもいよな
  • mime_encoding も送信用として MIME-Header-JP-Mobile-SJIS-Ezweb を返します。ただ受信(decode)の場合、もともとMIMEが Subject: =?iso-2022-jp?B?xxxx=?= ?shift_jis?B?xxxx=?= と一つのヘッダに複数のエンコーディグが混じることもあるためオールマイティになっているのでたまたま問題ない。

send_encoding() とかを新設するのがいいのか。

  • mime_encoding() - 送信・受信用MIMEエンコーディング
  • mail_encoding() - 受信用エンコーディング
  • send_encoding() - 送信用エンコーディング

だんだんきもくなってくる。しかたないか。しかもこれだけがんばっても絵文字が取れるのはauだけという悲しさです。

Email::MIME::JP::Mobile とかが受信や送信で裏でうまくやってくれるといいのかもしれないすねえ。

とりあえず MobileCat では

http://coderepos.org/share/browser/websites/mobilecat/trunk/lib/MobileCat/Controller/API/Mail/Post.pm#L22

のようにエンコーディングを探してdecodeしています。

トラックバック - http://mobilehacker.g.hatena.ne.jp/tomi-ru/20080801

2008-07-25

Email::Address::JP::Mobileのshipit候補版

| 18:15 | はてなブックマーク - Email::Address::JP::Mobileのshipit候補版 - tomi-ruのモバイル日記

http://svn.coderepos.org/share/lang/perl/Email-Address-JP-Mobile/trunk/

Encode::JP::Mobile の方でMIMEエンコーディングをサポートし始めているので、それに合わせて前作りかけのものを手直し。

  use Email::Address::JP::Mobile;

  my $carrier = Email::Address::JP::Mobile->new('docomo.taro.@docomo.ne.jp');
  $carrier->is_mobile; # 1
  $carrier->name; # "DoCoMo"
  $carrier->carrier_letter; # "I"
  $carrier->mime_encoding->encode("\x{E63E}です"); # "=?SHIFT_JIS?B?+J+CxYK3?="
  $carrier->mail_encoding->encode("\x{E63E}です"); # "\xF8\x9F\x82\xC5\x82\xB7"

のように HTTP::MobileAgent のメール版となるように書いた。

mime_encoding や mail_encoding はエンコーディング名じゃなくてEncode::Encodingオブジェクトを返すのでそのまま->encodeとか->decode できます。

これで(Encode::JP::Mobile の時期UP版と合わせて)、http://codezine.jp/a/article/aid/1262.aspx にあるような分岐処理を書かずに処理ができるようになると思います。

  use Email::Address;
  use Email::Address::Loose -override;
  use Email::Address::JP::Mobile;

  my ($email) = Email::Address->parse('docomo.taro.@docomo.ne.jp');
  my $carrier = $email->carrier;

syntax sugarとしてEmail::Addressオブジェクトにcarrierというメソッドを生やすことにしました。

以前PEPにメール投げた時はcarrer->以下のメソッドを直接Email::Addressに生やしていたのですが、carrier->以下に一段下がった形です。生やしすぎよりずっとよいかと。

トラックバック - http://mobilehacker.g.hatena.ne.jp/tomi-ru/20080725

2008-07-24

Encode::JP::Mobile MIME ブランチ

| 15:27 | はてなブックマーク - Encode::JP::Mobile MIME ブランチ - tomi-ruのモバイル日記

いつぞや#mobilejpで話がでたメール送信系BK(http://codezine.jp/a/article/aid/1262.aspx)の吸収の話です。

いまや世界的にも伝説が広まったmiyagawaさんが、エンコーディングでいいんじゃないかと言っていたのでそう実装してみました。

http://coderepos.org/share/browser/lang/perl/Encode-JP-Mobile/branches/mime

Encode 本体に MIME エンコード機能が付いているのは、Jcode の後継を名乗るための付け足し機能ぽく思っていたのですが、バイト <=> Unicode 変換フレームワークと考えるとアリですね。

decode()のことも考えないといけなくなり..

もともと送信時のことしか考えてませんでしたが、エンコーディングなのでdecodeも考えないといけない、と。gmail.com ドメイン以外だと絵文字はゲタになって送られるので使う機会はあまりないのですが。

auからのメールは Encode::JP::Mobile::KDDIJIS を使い、AirH からのは Encode::JP::Mobile::AirHJIS を使っています。

問題は softbank で、 gmail.com ドメインにメールを送ると謎のISO-2022-JPで届きます。絵文字はウェブコードで埋め込まれているぽい?です。

KDDIJIS をまねて Encode::JP::Mobile::SoftBankJIS を作ればなんとかなりそうですが、KDDIJIS のコードを追えていません。id:tokuhirom さんか id:clouder さんが SoftBankJIS 作ってくれたらうれしいです! > <

追記

chibaさんが名乗り出てくれました!

トラックバック - http://mobilehacker.g.hatena.ne.jp/tomi-ru/20080724

2008-07-18

use utf8; と => 演算子

| 12:40 | はてなブックマーク - use utf8; と => 演算子 - tomi-ruのモバイル日記

http://d.hatena.ne.jp/fbis/20080701/1214890867

なお、MIME::LiteでもEmail::Sendでも、SMTPを使う場合、最新版のNet::Cmd-v2.29でもやり方によってはまだ化けます。たとえば、以下のコードは化けます。

use utf8;
use MIME::Lite;
my $mime = MIME::Lite->new(
    To       => 'test@example.com',
    From     => '.........@ezweb.ne.jp',
    Subject  => Encode::encode("shift_jis", "あいう"),
    Data     => "test",
    Type     => 'text/plain; charset="Shift_JIS"',
    Encoding => 'base64',
);

$mime->send(smtp => 'localhost', Debug => 1);

とりあえず、auが =?Shift_JIS? を理解してくれないからメールとしては変なものを流さなければいけない、という点は置いておいておきます。

化ける原因は Net::Cmd の datasend で(perl 5.8やEncodeが使える場合)要するに以下のようにされているのが原因です。

utf8::encode($ソース) if utf8::is_utf8($ソース);

先のサンプルは utf8::is_utf8($ソース)がtrueになるので、utf8::encodeされてlatin-1扱いにされてしまっています。

use utf8 プラグマ以下だと => 演算子の前の値にフラグが付く

サンプルは use utf8 プラグマが効いてるので確かに "あああ" はutf8フラグ付ですが、Encode::encode でバイトになっているはずなのに、なぜフラグ付きになってるかというと、実はヘッダ名のToとかFromとかにフラグが付いているのです。

use Devel::Peek;

sub test { Dump shift }

{
    test(eee => "foo"); # eee にフラグは付かない
}

{
    use utf8;
    test(eee => "foo"); # eee にフラグは付く <= ポイント
}

{
    use utf8;
    test("eee", "foo"); # eee にフラグは付かない
}

どうやら => 演算子は "" + カンマ に等しいと思っていたのですが、use utf8 効果内では utf8::upgrade 相当の処理も走ってしまってるぽいです。これが想定どおりの動作なのか、バグなのか(もしかして5.10では直ってたりするのか)までは追っていません。

とりあえずNet::Cmdにもしくは手前のEmail::Sendにでフラグを落とすとかパッチを送ろうかとも思いましたが、auに生なSubjectを送りたい時にしか発生しない現象だし、ちょwおまw変な国wwと思われるのが関の山なので自分の方で対応するとよいと思いました。

  • ヘッダを並べる時にuse utf8プラグマが効かないようにする。(use bytes とか do{ } で局所化)。実際、テストコードのときくらいで、実はuse utf8が効いていることは少ないですよね。
  • ヘッダ名を 'To' => みたくする
  • 心配性なら、sendする前にheadersの内容をフラグ落として回る

KendraKendra2012/07/18 16:32This could not possibly have been more helfpul!

afpcmjnlafpcmjnl2012/07/19 01:23SYPDkU <a href="http://pxnsqexnmdgr.com/">pxnsqexnmdgr</a>

wubvkujlvwubvkujlv2012/07/19 23:56471IYa , [url=http://augjbrgqusja.com/]augjbrgqusja[/url], [link=http://jqftumltktnu.com/]jqftumltktnu[/link], http://qcwemrdzkrho.com/

zwyklahednzwyklahedn2012/07/20 15:275rtiei <a href="http://mmvzmtljnycz.com/">mmvzmtljnycz</a>

トラックバック - http://mobilehacker.g.hatena.ne.jp/tomi-ru/20080718

2008-07-11

Email::MIME::XPath++

| 00:08 | はてなブックマーク - Email::MIME::XPath++ - tomi-ruのモバイル日記

Email::MIME系でメールパースする話で

  • 添付画像を取るときAttachment::StripperだとDoCoMo携帯から画像一個本文なしで添付してきた時みたいな画像一個だけのシングルパートだと取れない(たぶん携帯のMUAがRFC的におかしいのだと思う)
  • 一番最初にでてくるテキストぽいパートを取得」ってよくやるけど$email->body はマルチパートだと使えないしMIMEは入れ子になってるから再帰的にさがさないと行けなくてめんどう

とかいう話があると思うのですが、

添付ファイルの話は、ぼくは以下みたいに空のパートを付けたりしてました。typesterさんは$email->partsを回して探すことにしたと言ってました。

use Email::MIME::Attachment::Stripper;
use Email::MIME::Modifier;

sub Email::MIME::attachment_files {
    my $self  = shift;
    my $email = Email::MIME->new($self->as_string);

    if ($email->parts == 1) {
        $email->parts_add([ Email::MIME->new("Content-Type: text/plain\n\ndummy") ]);
    }

    my $stripper = Email::MIME::Attachment::Stripper->new($email);
    my @attachments;
    for my $attach ($stripper->attachments) {
        next if $attach->{content_type} =~ m{^(?:text|multipart|message)/};
        push @attachments, $attach;
    }

テキストぽい最初のパートをとる話は、MIMEパートが入れ子の場合$email->bodyでは取れないので、以下のように再帰的にがんばったりしていました。

sub Email::MIME::first_text {
    my $self = shift;
    _first_text_part($self->parts);
}

sub _first_text_part {
    my @parts = @_;
    for my $part (@parts) {
        if ($part->{ct}{discrete} eq 'multipart') {
            return _first_text_part($part->parts);
        }
        if ($part->{ct}{discrete} eq 'text' and
            $part->{ct}{composite} =~ /^plain|html$/) {
            return $part;
        }
    }
}

が、

Email::MIME::XPath を使えば超絶楽だったってことを最近知りました。さっそく今日のCPANモジュールで紹介しようと思ったのですが、Email::MIMEの紹介が先かなとか思ったらめんどうになったのでここで紹介。

最初の、画像パートを抜き出すのは、以下の一行!

my @parts = $email->xpath_findnodes('//*[@content_type=~"^image/"]');

画像一個のシングルパートな場合も問題ないし、変な再帰を書かなくてもよいし、Attachment::Stripperを使うのと比べ、取りたいタイプを指定できて良いです。

テキストぽい最初のパートをとるのも一行

my ($part) = $email->xpath_findnodes('//*[@content_type=~"^text"][1]');

楽だ。なんで言及がすくないんだろう。

Tree::XPathEngine の全機能をサポートしてないですが、xpath_findnodes() と、特別に使える属性の中でcontent_typeというのがあるということだけ覚えておけばよいと思います。

wteiqbtcwteiqbtc2011/03/20 14:39gzTW9S <a href="http://mmdhpeqrvcuc.com/">mmdhpeqrvcuc</a>, [url=http://jfkgbmjhgalo.com/]jfkgbmjhgalo[/url], [link=http://yotgvlprpnlr.com/]yotgvlprpnlr[/link], http://nnycpbqcvebp.com/

HannesHannes2012/09/23 13:44Articles like this make life so much simpelr.

fpwlzscxcfpwlzscxc2012/09/25 16:04uTwDex , [url=http://zqnaoismzlwg.com/]zqnaoismzlwg[/url], [link=http://ihjmypmptmvs.com/]ihjmypmptmvs[/link], http://uvnggiwecjha.com/

EkainEkain2015/08/11 17:52You've got it in one. Cou'dnlt have put it better.

KryDogeKryDoge2018/02/11 20:46Resultados Con Propecia <a href=http://ciali5mg.com>cialis buy online</a> Achat Viagra Acheter Viagra Cephalexin Anxiety Foro Cialis O Levitra