CGIの質問です。いちばん下の「この質問・回答へのコメント」に記載の内容は誕生日にメール配信するCGIの一部です。

一部の方から配信されるメールが文字化けして見えないとの指摘があります。
恐らく”print "Content-type:~”の箇所に問題があると思うのですが、CGIの知識が浅く、私の環境では文字化けしないため確かめようがありません。
文字化けしないようにするにはどのように修正すればよいのでしょうか?
CGIの知識が浅いため、解決方法そのものを教えていただければうれしいです。
解決にいたる完全な回答していただいた最初の回答者の方には300ポイントを差し上げます。よろしくお願いいたします。

回答の条件
  • 1人2回まで
  • 登録:2008/02/27 01:47:16
  • 終了:2008/02/28 14:08:29

回答(1件)

id:tukihatu No.1

牛乳先生(tukihatu)回答回数180ベストアンサー獲得回数322008/02/27 10:08:43

ポイント500pt

このCGIで化けないのが逆に不思議です^^;

とりあえずパッと見た感じ、エンコードが多種多様になっているところが原因ですね…EUCとかsjisとか

とりあえずCGIのエンコードを一つにしましょう。

sjisでいいなら、まずCGI本体と読み込むデータのエンコードをSJISにします。

そして

To:やFrom:に入っている変数はエンコードしない(&jcode'convert(*from, 'euc');とか外す)

submitは&jcode'sjis2jis(*subject);でjisにした後、base64にエンコードして"=?iso-2022-jp?B?$subject?="とする

http://home.kanto-gakuin.ac.jp/~ahero/perl/net/mail/mail_title.s...

>||print MAIL "To: $email\n";

print MAIL "From: $myaddress\n";||<

の後に

>||print MAIL "Content-Type: text/plain; charset=iso-2022-jp\n";

print MAIL "Content-Transfer-Encoding: 7bit\n";||<

を追加

print "Content-type: image/gif\n\nGIF89a\1\0\1\0\200\0\0\0\0\0\0\0\0!\371\4\1\0\0\0\0,\0\0\0\0\1\0\1\0\0\2\2D\1\0\n";

は削除

その他の&jcode'convert(何か,'sjis');になっているものはすべて外す

http://internet.watch.impress.co.jp/www/article/1999/1122/specia...

その他にも問題がありそうですが、ひとまずエンコードのあたりをいじってみると解決するかもしれません。

id:icta

早々の回答ありがとうございます。

思った以上に修正箇所が多く、ご指摘の修正内容が私の知識が浅いのが原因なのですが残念ながらよく理解できませんでした。

文字コードはsjisを使用しております。

理解不十分のまま私自身で修正して正常に動かなくなることを大変心配しております。

このようなことをお願いするのは心苦しいのですが、修正した完全なコードを記載していただけませんでしょうか?

何卒ご理解の上、お力添えいただければ幸いです。

2008/02/27 18:54:00
  • id:icta
    require './jcode.pl';
    require './conf/conf.pl';
    #########################################################
    $datefile = "date.txt";
    $mailcontents = 'birthday.txt';
    #########################################################

    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time + ($timediff * 60 * 60));
    $mon++;
    #if ($mon < 10) { $mon = "0$mon"; }
    #if ($mday < 10) { $mday = "0$mday"; }
    $tday = "$mon/$mday";
    $tday2 = "$mon月$mday日";

    open (DATA,"$datefile");
    $day = <DATA>;
    close (DATA);

    if ($day ne "$tday") {
    open (DATA,">$datefile");
    flock(DATA,2);
    print DATA $tday;
    close (DATA);
    flock(DATA,8);
    &sub1;
    }

    print "Content-type: image/gif\n\nGIF89a\1\0\1\0\200\0\0\0\0\0\0\0\0!\371\4\1\0\0\0\0,\0\0\0\0\1\0\1\0\0\2\2D\1\0\n";

    exit;


    sub sub1{
    open(DF,"$mailcontents");
    @DATAM = <DF>;
    close(DF);
    foreach $linem (@DATAM) {
    $mailtext ="$mailtext$linem";
    }
    open (DB,"$database");
    @DATA = <DB>;
    close(DB);
    foreach $line (@DATA) {
    ($name,$email,$birth1,$birth2,) = split(/\,/,$line);
    $birth= "$birth1/$birth2";
    if ($tday eq "$birth") {
    &mailcheck;
    if ($errorh eq "0") {&sub2;}
    }
    }
    &sub3;
    }

    sub sub2{
    open(MAIL,"|$sendmail $email");
    &jis("Subject: $mailtitle"); print MAIL "$msg\n";
    print MAIL "To: $email\n";
    print MAIL "From: $myaddress\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $name様

    $mailtext

    END_OF_MESSAGE
    &jcode'convert(*message,'sjis');
    print MAIL "$message";
    close(MAIL);

    $tosendall="$tosendall$name,$email\n";

    }

    sub sub3{
    open(MAIL,"|$sendmail $myaddress");
    &jis("Subject: $tday2の誕生日処理完了"); print MAIL "$msg\n";
    print MAIL "To: $myaddress\n";
    print MAIL "From: $myaddress\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $tday2の誕生日処理正常に終わりました

    【メール送信先】
    $tosendall

    【メール文】
    $mailtext
    END_OF_MESSAGE
    &jcode'convert(*message,'sjis');
    print MAIL "$message";
    close(MAIL);
    }

    sub mailcheck{
    $errorh = "0";
    $xx =$email;
    &transmail;
    $email = $xx;
    @email2 = split(/\@/,$email);
    @email3 = split(/\./,@email2[1]);
    unless($email =~ /.+\@.+\..+/){$errorh = "1";}
    if($email =~ /[^a-zA-Z0-9_\@\.\-]/){$errorh = "1";}
    if($email =~ /[^a-zA-Z]$/){$errorh = "1";}
    if(@email3[0] eq "") {$errorh = "1";}
    if(@email3[1] eq "") {$errorh = "1";}
    if(@email3[2] ne "") {
    if(@email3[2] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if(@email3[3] ne "") {
    if(@email3[3] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if ($email eq "") {$errorh = "1";}
    }

    sub transmail{
    $from='[@01-9A-Za-z._-]';
    $to='[@01-9A-Za-z._-]';
    &jcode'convert(*xx, 'euc');
    &jcode'convert(*from, 'euc');
    &jcode'convert(*to, 'euc');
    &jcode'tr(*xx, $from, $to);
    &jcode'convert(*xx, 'sjis');
    }

    sub jis { $msg = $_[0]; &jcode'convert(*msg, 'jis'); }
  • id:tukihatu
    次は自分でやってみてくださいね。
    完全なのは無理ですが…(外部データの内容がわからないので)
    元のCGIが動いていればちゃんと動くのではないかと。


    require './jcode.pl';
    require './conf/conf.pl';
    #########################################################
    $datefile = "date.txt";
    $mailcontents = 'birthday.txt';
    #########################################################

    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time + ($timediff * 60 * 60));
    $mon++;
    #if ($mon < 10) { $mon = "0$mon"; }
    #if ($mday < 10) { $mday = "0$mday"; }
    $tday = "$mon/$mday";
    $tday2 = "$mon月$mday日";

    open (DATA,"$datefile");
    $day = <DATA>;
    close (DATA);

    if ($day ne "$tday") {
    open (DATA,">$datefile");
    flock(DATA,2);
    print DATA $tday;
    close (DATA);
    flock(DATA,8);
    &sub1;
    }

    exit;


    sub sub1{
    open(DF,"$mailcontents");
    @DATAM = <DF>;
    close(DF);
    foreach $linem (@DATAM) {
    $mailtext ="$mailtext$linem";
    }
    open (DB,"$database");
    @DATA = <DB>;
    close(DB);
    foreach $line (@DATA) {
    ($name,$email,$birth1,$birth2,) = split(/\,/,$line);
    $birth= "$birth1/$birth2";
    if ($tday eq "$birth") {
    &mailcheck;
    if ($errorh eq "0") {&sub2;}
    }
    }
    &sub3;
    }

    sub sub2{
    $ttl = &jis("$mailtitle");
    open(MAIL,"|$sendmail $email");
    print MAIL "$msg\n";
    print MAIL "To: $email\n";
    print MAIL "From: $myaddress\n";
    print MAIL "Subject: $ttl\n";
    print MAIL "Content-Type: text/plain; charset=iso-2022-jp\n";
    print MAIL "Content-Transfer-Encoding: 7bit\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $name様

    $mailtext

    END_OF_MESSAGE
    print MAIL "$message";
    close(MAIL);

    $tosendall="$tosendall$name,$email\n";

    }

    sub sub3{

    $ttl = &jis("$tday2の誕生日処理完了");
    open(MAIL,"|$sendmail $myaddress");
    print MAIL "$msg\n";
    print MAIL "To: $myaddress\n";
    print MAIL "From: $myaddress\n";
    print MAIL "Subject: $ttl\n";
    print MAIL "Content-Type: text/plain; charset=iso-2022-jp\n";
    print MAIL "Content-Transfer-Encoding: 7bit\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $tday2の誕生日処理正常に終わりました

    【メール送信先】
    $tosendall

    【メール文】
    $mailtext
    END_OF_MESSAGE
    print MAIL "$message";
    close(MAIL);
    }

    sub mailcheck{
    $errorh = "0";
    $xx =$email;
    &transmail;
    $email = $xx;
    @email2 = split(/\@/,$email);
    @email3 = split(/\./,@email2[1]);
    unless($email =~ /.+\@.+\..+/){$errorh = "1";}
    if($email =~ /[^a-zA-Z0-9_\@\.\-]/){$errorh = "1";}
    if($email =~ /[^a-zA-Z]$/){$errorh = "1";}
    if(@email3[0] eq "") {$errorh = "1";}
    if(@email3[1] eq "") {$errorh = "1";}
    if(@email3[2] ne "") {
    if(@email3[2] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if(@email3[3] ne "") {
    if(@email3[3] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if ($email eq "") {$errorh = "1";}
    }

    sub transmail{
    $from='[@01-9A-Za-z._-]';
    $to='[@01-9A-Za-z._-]';
    }

    sub jis {
    $msg = $_[0];
    &jcode'sjis2jis(*msg);
    $msg = &base64($msg);
    $msg = "=?iso-2022-jp?B?$msg?=";
    return($msg);
    }

    sub base64 {
    my($base) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    my($xx, $yy, $zz, $i);
    $xx = unpack("B*", $_[0]);
    for ($i = 0; $yy=substr($xx, $i, 6); $i+=6){
    $zz .= substr($base, ord(pack("B*", "00" . $yy)), 1);
    if (length($yy)==2) {
    $zz .= "==";
    }elsif(length($yy)==4) {
    $zz .= "=";
    }
    }
    return($zz);
    }

    必ずしも動く保障はありませんのであしからず。
  • id:icta
    tukihatuさん回答ありがとうございます。
    教えていただいたコードに早速置き換えてみました。
    Hotmailで見ているユーザが「文字化けしている」という指摘が多いことに先ほど気が付き、Hotmailアドレスで試してみることにしました。

    結果は残念ながら文字化けは修正されませんでした。
    それどころか以前は文字化けされなかった件名が空白になり、差出人にメールアドレスが入らなくなってしまいました。
    教えていただいた内容をそのまま置き換えただけなのですが私のやり方に何か問題がありましたでしょうか?
    文字コードはすべてShift-JISに設定しています。
    何が原因でこうなってしまったのかさっぱり検討がつきません。
    以下は修正前と修正後の異なる点を列挙したものです。

    ◆修正前

    ○ユーザーに届くメール
     差出人:xxxxxx\@hotmail.com
     件名:お誕生日おめでとうございます
     内容:文字化け 

    ○管理者に届くメール
     差出人:xxxxxx\@hotmail.com
     件名:2月27日の誕生日処理完了
     内容:文字化け 

    ◆修正後

    ○ユーザーに届くメール
     差出人:User
     件名:なし
     内容:文字化け(※韓国語) 

    ○管理者に届くメール
     差出人:User
     件名:なし
     内容:文字化け(※韓国語) 


    恐らく▼こちらの設定ファイルをお知らせしていなかったのが原因のひとつではないか思われます。
    もし何か良い解決方法がお分かりでしたら教えていただければ幸いです。

    ◆conf.pl

    ################################################
    #        birthday.cgi用の設定ファイル
    ################################################

    #=========↓誕生月を迎える人に送るメールのタイトルです===============#
    $mailtitle = "お誕生日おめでとうございます";
    #=========↓ショップのメールアドレスを入れます。===============#
    #=========↓@の前には必ず\を入れます(半角)=================#
    $myaddress = "xxxxxx\@zzzzz.net";
    #=========↓サーバーの時差がある場合(半角)==================#
    $timediff = '0';
    #=========↓お客さんデータファイルの場所を指定。=============#
    $database = 'birthmail.csv';
    #=========↓sendmail のパス===============================#
    $sendmail = '/usr/sbin/sendmail';
    #=====================================================#
    1;#触らないで下さい。


  • id:tezcello
    > 何が原因でこうなってしまったのかさっぱり検討がつきません。
    tukihatu さんのスクリプトから、
    print MAIL "$msg\n";
    の行(sub2, sub3 の2ヶ所あり)を削除すると件名や差出人がおかしい件は直るかも知れません。
      $msg は質問者さんのスクリプトでは、jis サブルーチンで定義されていますが
      tukihatu さんのは jis での変換結果(既に $ttl に渡した値)が入っています。
      不正なヘッダとして無視されると思うのですが、出すべきものではないので。
  • id:tukihatu
    >tezcelloさん
    あれ、ほんとだ^^;なんで入れたんだっけ…指摘ありがとうございます。
    ついでに&jcode'sjis2jis(*message);とprint "Content-type: text/html\n\n";も追加~。これでまず大丈夫でしょ、確認してないけど。


    require './jcode.pl';
    require './conf/conf.pl';
    #########################################################
    $datefile = "date.txt";
    $mailcontents = 'birthday.txt';
    #########################################################

    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time + ($timediff * 60 * 60));
    $mon++;
    #if ($mon < 10) { $mon = "0$mon"; }
    #if ($mday < 10) { $mday = "0$mday"; }
    $tday = "$mon/$mday";
    $tday2 = "$mon月$mday日";

    open (DATA,"$datefile");
    $day = <DATA>;
    close (DATA);

    if ($day ne "$tday") {
    open (DATA,">$datefile");
    flock(DATA,2);
    print DATA $tday;
    close (DATA);
    flock(DATA,8);
    &sub1;
    }

    print "Content-type: text/html\n\n";
    exit;


    sub sub1{
    open(DF,"$mailcontents");
    @DATAM = <DF>;
    close(DF);
    foreach $linem (@DATAM) {
    $mailtext ="$mailtext$linem";
    }
    open (DB,"$database");
    @DATA = <DB>;
    close(DB);
    foreach $line (@DATA) {
    ($name,$email,$birth1,$birth2,) = split(/\,/,$line);
    $birth= "$birth1/$birth2";
    if ($tday eq "$birth") {
    &mailcheck;
    if ($errorh eq "0") {&sub2;}
    }
    }
    &sub3;
    }

    sub sub2{
    $ttl = &jis("$mailtitle");
    open(MAIL,"|$sendmail $email");
    print MAIL "To: $email\n";
    print MAIL "From: $myaddress\n";
    print MAIL "Subject: $ttl\n";
    print MAIL "Content-Type: text/plain; charset=iso-2022-jp\n";
    print MAIL "Content-Transfer-Encoding: 7bit\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $name様

    $mailtext

    END_OF_MESSAGE
    &jcode'sjis2jis(*message);
    print MAIL "$message";
    close(MAIL);

    $tosendall="$tosendall$name,$email\n";

    }

    sub sub3{

    $ttl = &jis("$tday2の誕生日処理完了");
    open(MAIL,"|$sendmail $myaddress");
    print MAIL "To: $myaddress\n";
    print MAIL "From: $myaddress\n";
    print MAIL "Subject: $ttl\n";
    print MAIL "Content-Type: text/plain; charset=iso-2022-jp\n";
    print MAIL "Content-Transfer-Encoding: 7bit\n";
    print MAIL "\n";
    $message = <<END_OF_MESSAGE;
    $tday2の誕生日処理正常に終わりました

    【メール送信先】
    $tosendall

    【メール文】
    $mailtext
    END_OF_MESSAGE
    &jcode'sjis2jis(*message);
    print MAIL "$message";
    close(MAIL);
    }

    sub mailcheck{
    $errorh = "0";
    $xx =$email;
    &transmail;
    $email = $xx;
    @email2 = split(/\@/,$email);
    @email3 = split(/\./,@email2[1]);
    unless($email =~ /.+\@.+\..+/){$errorh = "1";}
    if($email =~ /[^a-zA-Z0-9_\@\.\-]/){$errorh = "1";}
    if($email =~ /[^a-zA-Z]$/){$errorh = "1";}
    if(@email3[0] eq "") {$errorh = "1";}
    if(@email3[1] eq "") {$errorh = "1";}
    if(@email3[2] ne "") {
    if(@email3[2] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if(@email3[3] ne "") {
    if(@email3[3] =~ /[^a-zA-Z]/){$errorh = "1";}
    }
    if ($email eq "") {$errorh = "1";}
    }

    sub transmail{
    $from='[@01-9A-Za-z._-]';
    $to='[@01-9A-Za-z._-]';
    }

    sub jis {
    $msg = $_[0];
    &jcode'sjis2jis(*msg);
    $msg = &base64($msg);
    $msg = "=?iso-2022-jp?B?$msg?=";
    return($msg);
    }

    sub base64 {
    my($base) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    my($xx, $yy, $zz, $i);
    $xx = unpack("B*", $_[0]);
    for ($i = 0; $yy=substr($xx, $i, 6); $i+=6){
    $zz .= substr($base, ord(pack("B*", "00" . $yy)), 1);
    if (length($yy)==2) {
    $zz .= "==";
    }elsif(length($yy)==4) {
    $zz .= "=";
    }
    }
    return($zz);
    }
  • id:icta
    tukihatuさん回答ありがとうございます。
    Hotmailでも文字化けせずに見ることができるようになりました。
    教えていただいた内容を参考に文字化けする別のCGIの修正を試みました。
    しかしエラーが出てなかなか前に進むことができません。
    試行錯誤してみたもののCGIの知識が決定的に不足しているようです。
    新たに質問をすることにしましたのでお手すきの時にでもご覧いただければ幸いです。
    http://q.hatena.ne.jp/1204181425

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません