![]() | ← | はせがわさん作成の GMail-Filter のバナーです。 気が向いたら、これを使って宣伝よろしくです。m(__)m |
#!/usr/local/bin/perl
use strict;
our $ver = 'X-GMail-Filter: gmail-filter.pl(ver0.20.01) by yamagata@openmya';
our $LINF = "\r\n";
#$LINF = "\n"; #←fmlの時は行頭のコメント外す
use Encode qw(from_to);
use MIME::Base64; use MIME::QuotedPrint;
my $mail = ''; my $header = -1; my $sCT = ''; my $sCTE = ''; my $cte = 0;
my @kugiri; my $cnt = 0; my $kc = ''; my $dmy;
my $kcodes0 = 'UTF-8|EUC-JP|shift_jis|GB2312|GB18030|EUC-KR|BIG5';
my $kcodes = "$kcodes0|iso-2022-jp";
my $rxCharset = '[\s\t]*charset[\s\t]*=';
my $uuencode = 0; my $uuencode_count = 0;
while(<>) {
s/\r?\n$//;
if($header) {
# ヘッダ部分について処理
s{=\?($kcodes)\?([BQ])\?([^\?]+)\?=}{
# ヘッダ内の =?UTF-8?B?...?= などの変換処理
my($kc, $bq, $str) = ($1, $2, $3);
if($bq eq 'B' || $bq eq 'b') {
# base64
$str = decode_base64(&rmCRLF($str));
} else {
# quoted-printable
$str =~ tr/_/ /;
$str = decode_qp(&rmCRLF($str));
}
# 先頭のatext文字はBase64しない
$str = &toJIS($kc, $str);
$str =~ m"^([[:alnum:]!#$%&'*+/=?^ `{|}-]*)(.*)$";
$str = encode_base64($2, "");
$1."=\?iso-2022-jp\?B\?$str\?=";
}ige;
if(/^Content-Type:/i) {
# Content-Type: ヘッダの処理
$sCT = $_;
while(<>) { s/\r?\n$//; last if(!/^[\s\t]/); $sCT .= "$LINF$_"; }
if($sCT =~ /;$rxCharset/is &&
$sCT !~ /^Content-Type:[\s\t]+[^;]+;$rxCharset/is) {
# type/subtype の直後に charset を移動。(電八,鶴亀メール用)
print "X-Original-Order-$sCT$LINF";
my($ct1, $ct2) = $sCT =~ /^(Content-Type:[\s\t]+[^;]+);[\s\t]*(.*)$/is;
$ct2 .= ";";
my @param =
($ct2 =~ /([^=]+=[\s\t]*(?:"[^"]*"|[^";]*));[\s\t\r\n]*/sg);
$sCT = "";
local($_);
foreach(@param) {
if(/^charset[\s\t]*=/i) { $sCT = "; $_$sCT"; }
else { $sCT .= ";\n $_"; }
}
$sCT = "$ct1$sCT";
}
if($sCT =~ /^Content-Type:[\s\t]*multipart.*boundary[\s\t]*=[\s\t]*(['"]?)([^'";]+)\1/is) {
# MIME の Boundary を確保
unshift @kugiri, $2;
}
redo;
} elsif(/^Content-Transfer-Encoding:[\s\t]*/i) {
# Content-Transfer-Encoding: ヘッダの処理
$sCTE = $_;
while(<>) { s/\r?\n$//; last if(!/^[\s\t]/); $sCTE .= "$LINF$_"; }
redo;
} elsif($_ eq '') {
$header = 0;
if($sCT =~ /^Content-Type:.*$rxCharset(["']?)($kcodes)\1/is &&
$sCTE =~ /^Content-Transfer-Encoding:[\s\t]*base64/i) {
# 漢字コード&base64 の変換をする
$cte = 1;
} elsif(
$sCT =~ /^Content-Type:.*$rxCharset(["']?)($kcodes)\1/is &&
$sCTE =~ /^Content-Transfer-Encoding:[\s\t]*quoted-printable/i) {
# 漢字コード&quoted-printable の変換をする
$cte = 2;
} elsif(
$sCT =~ /^Content-Type:.*$rxCharset(["']?)($kcodes0)\1/is &&
$sCTE =~ /^Content-Transfer-Encoding:[\s\t]*[78]bit/i) {
# 漢字コードの変換のみ
$cte = 3;
} else {
# 変換は行わない
$cte = 0;
}
($dmy, $kc) =
$sCT =~ /^Content-Type:.*$rxCharset(["']?)([^"';]+)\1/is;
if($cte > 0) {
# 変換を実施する場合、ヘッダを置換する
print "X-Original-$sCT$LINF";
print "X-Original-$sCTE$LINF";
$sCT =~
s/^(Content-Type:.*$rxCharset)(["']?)[^"';]+\2/\1"iso-2022-jp"/is;
$sCTE =~ s/^(Content-Transfer-Encoding:)[\s\t]*\S+/\1 7bit/i;
}
# Content-Type, Content-Transfer-Encoding ヘッダを表示
print "$sCT$LINF" if($sCT ne '');
print "$sCTE$LINF" if($sCTE ne '');
print "$ver$LINF" if(++$cnt <= 1);
print "$LINF";
next;
}
} else {
if(length($kugiri[0]) > 0 && /^\Q--$kugiri[0]\E(--)?$/) {
# MIME の Boundary を処理
shift @kugiri if($1 eq '--');
&shori($kc, $mail, $cte); $mail = '';
$header = -1; $sCT = ''; $sCTE = ''; $cte = 0;
} elsif($uuencode) {
if(/^end$/) {
$uuencode = 0;
} elsif(/^[ -_`~]+$/) {
if(++$uuencode_count == 4) {
$_ = '** UUENCODE data was suppressed. **';
} elsif($uuencode_count > 4) {
next;
}
} else {
$uuencode = 0;
}
} elsif(/^begin [0-7]{3,3} ./) {
# uuencode 形式の添付ファイルを抑止
# http://gabacho.reto.jp/tech-note/a-filter を参考にしました。
$uuencode = -1;
$uuencode_count = 0;
}
}
if($cte > 0) {
$mail .= "$_$LINF";
} else {
print "$_$LINF";
}
}
&shori($kc, $mail, $cte);
exit;
sub shori {
# 必要なら漢字コード&転送エンコード形式の変換をする
my($kc, $mail, $cte) = @_;
if($cte == 1) {
$mail = &toJIS($kc, decode_base64($mail)).$LINF.$LINF;
} elsif($cte == 2) {
$mail = &toJIS($kc, decode_qp($mail));
} elsif($cte == 3) {
$mail = &toJIS($kc, $mail);
}
print &convertCRLF($mail);
}
sub rmCRLF {
# 改行コードを取り除く
my($str) = @_;
$str =~ s/[\r\n]+//g;
return $str;
}
sub convertCRLF {
# 改行コードを CR LF に置換する
local($_) = @_;
s/\x0D\x0A/\n/g; tr/\x0D\x0A/\n\n/;
s/\n/\x0D\x0A/g if($LINF ne "\n");
return $_;
}
sub UTF8toJIS {
# UTF-8 から JIS に変換する
my($str) = @_;
$str =~ s/\xEF\xBD\x9E/\xE3\x80\x9C/g;
$str =~ s/\xEF\xBC\x8D/\xE2\x88\x92/g;
from_to($str, 'utf8', 'iso-2022-jp');
return $str;
}
sub toJIS {
# 漢字コードを JIS に変換する
my($kc, $str) = @_;
if($kc =~ /UTF-8/i) {
$str = &UTF8toJIS($str);
} elsif($kc =~ /EUC-JP/i) {
from_to($str, 'euc-jp', 'iso-2022-jp');
} elsif($kc =~ /shift_jis/i) {
from_to($str, 'shiftjis', 'iso-2022-jp');
} elsif($kc =~ /GB2312/i) {
from_to($str, 'cp936', 'utf8');
$str = &UTF8toJIS($str);
} elsif($kc =~ /GB18030/i) {
from_to($str, 'gb18030', 'utf8');
$str = &UTF8toJIS($str);
} elsif($kc =~ /EUC-KR/i) {
from_to($str, 'euc-kr', 'utf8');
from_to($str, 'utf8', 'cp932');
from_to($str, 'cp932', 'iso-2022-jp');
} elsif($kc =~ /BIG5/i) {
from_to($str, 'big5', 'iso-2022-jp');
}
return $str;
}
| << ツール一覧に戻る |