- 2008-01-05 (Sat) 19:20
- プログラミング
PCで受信しているメールを携帯でも受信したい.ただしパケット代が高いので,スパムは転送しない,添付ファイルはファイル名だけわかればいい,本文もある程度の長さで切れてしまえ,という仕様にしたい.
今回とった手段は,ひとまず Gmail に転送してスパムを高確率で殺す,そいつをレンタルサーバの転送専用メールアカウントに転送する,さらにそのアカウントで添付ファイルや本文の短縮の加工を行い携帯側へ転送する,とかいう摩訶不思議なリレー.
で,調べてみたらレンタルサーバのメール振り分けは maildrop とかいうのでやっているらしく,転送設定は通常の .forward ではなく.mailfilter とかいうものを書くらしい.つーことで,.mailfilter を転送用メールアカウントのディレクトリに置いて,中身を次のように指定.パーミッションを 600 とかにしておかないと動いてくれないので困る.
cc "| ../../mail_forwarding.pl"
そんで,次の転送用のプログラム mail_forwarding.pl を適当に配置.いわゆる .eml が添付されてきたときには再帰的に展開して本文にくっつけてしまう.他はテキスト以外の添付は切り捨て.
#!/usr/bin/perl use MIME::Parser; use MIME::Words qw(:all); use Jcode; #use encoding "7bit-jis"; $forward_addr = 'hugahoge_tekitou@docomo.ne.jp'; $sendmail = '/usr/sbin/sendmail'; $length_limit = 512; sub extract_body { my ($entity) = @_; my $body = $entity->bodyhandle; my $head = $entity->head; my $type = $head->mime_type(); my $str = ""; my $nm = $head->recommended_filename; #print "type = $type\n"; if( $type eq "multipart/mixed") { #if($entity->is_multipart()) { my $count = $entity->parts; for(my $i = 0; $i < $count; $i++){ my ($st, $n) = extract_body($entity->parts($i)); if($n ne "") { if($nm ne "") { $nm .= ", "; } $nm .= $n; } if($st ne "") { if($str ne "") { $str .= "===\n"; } $str .= $st; } } } elsif( $type eq "text/plain") { $str = $body->as_string; } elsif( $type eq "text/html") { $str = $body->as_string; } elsif( $type eq "message/rfc822") { # should be recursively decoded my $io = $body->open("r"); my $et = $parser->parse($io); my ($st, $n) = extract_body($et); $str = $st; if($n ne "") { if($nm ne "") { $nm .= ", "; } $nm .= $n; } } else { } return ($str, $nm); } sub extract { my ($head, $attr) = @_; my $dat = $head->get($attr); my @decs = decode_mimewords($dat); my $ret = ""; foreach $data (@decs){ my ($target,$charset) = @$data; if($charset ne "") { Jcode::convert(\$target, $charset, 'jis'); } $target =~ s/\n//g; $ret .= $target } return $ret; } sub stlip_bracket { my ($dat) = @_; $dat =~ s/(^|,)[^>]*<([^<>]*)>/\1\2/g; return $dat; } $parser = new MIME::Parser; $parser->output_to_core(1); $parser->extract_nested_messages(0); $entity = $parser->parse(\*STDIN) or die "parse failed\n"; $head = $entity->head; $from = &extract($head, 'From'); $to = &extract($head, 'To'); $cc = &extract($head, 'CC'); $subj = &extract($head, 'Subject'); $from = stlip_bracket($from); $to = stlip_bracket($to); $cc = stlip_bracket($cc); $body = ""; ($body, $files) = extract_body($entity); $mes = ""; $mes .= "From: $from\n"; $mes .= "To: $to\n"; if($cc ne "") { $mes .= "CC: $cc\n"; } $mes .= "Subj: $subj\n"; if($files ne "") { $mes .= "File: $files\n"; } $mes .= "$body"; if(length $body > $length_limit) { $body = substr($body, 0, $length_limit); } $modbody = $body.($to ne "" ? "\nTo: ".$to : "").($cc ne "" ? "\nCC: ".$cc : "").($files ne "" ? "\nFs: ".$files : ""); #$esub = encode_mimeword($subj); $top = MIME::Entity->build(Type =>"text/plain", From => $from, To => $forward_addr, Data => $modbody, Subject => $subj, Encoding => "7bit", Charset => "ISO-2022-JP", # Subject => $esub); # CC => $cc, # Encoding =>"quoted-printable", ); #print $mes; $top->print(\*STDOUT); #exit(0); open(MAIL, "| $sendmail -t") or die "seinding a mail failed"; $top->print(\*MAIL); print MAIL "\n\n.\n"; #$top->head->replace('To', 'debug_output@hugahoge_tekitou.com'); #open(MAILLOG, "| $sendmail -t") or die "seinding a mail failed"; #$top->print(\*MAILLOG); #print MAILLOG "\n\n.\n";
とりあえず動いてるけど HTML メールのときにタグをなくしてテキスト化したいなぁ.そして perl で書いたけど別の言語で書いたほうが楽だったかなぁ.perl なんて久々に使ったから perl として普通のプログラムなのか怪しいし.
- Newer: AWK - はじめ