メールフォームでメールを送信する際に長い行があると文字化けする現象が...。
どうもSMTP送信時に一行で998バイトを超える文字列を利用するのは禁止されているみたいで(RFC2822)、どうしても超える場合はQuoted-Printable形式でエンコードしないといけないそうです。
PHPの標準関数ではこの形式のエンコードをする関数はないようだったので、RFC2045を参考にして、文字コードJIS用のエンコード用関数を作ってみました↓
function quotedPrintableEncode($str) {
$cano = "";
$flg = false; // 日本語フラグ
// エスケープシーケンス
$st = array("1B2842", "1B284A", "1B2849", "1B2440", "1B2442",
"1B2444");
$ofs = 0; // $strから切り取られる文字数
while(strlen($str)) {
$eFlg = false; // QPエンコするフラグ
// エスケープシーケンスの場合
if(is_numeric($idx = array_search(strtoupper(bin2hex(
$b = substr($str, 0, 3))), $st))) {
$ofs = 3;
$flg = $idx > 1;
$eFlg = true;
// 文字の場合
} else {
$b = substr($str, 0, 1); // 1文字ずつ切り出し
$ofs = 1;
if($flg) {
// 日本語文字の場合は、文字コードにかかわらずとりあえずエンコード
$eFlg = true;
} else {
// ASCII文字の場合は、文字によって処理を変更
$ord = ord($b);
if($ord > 127 || $ord==95 || $ord==63 || $ord==61) {
// RFC 2045で名指しされている文字をエンコ
$eFlg = true;
} elseif($ord == 32 || $ord == 9) {
// SPACE | TABはそのまま
} elseif($ord == 13) {
// CRのときはCRLFを疑う
if(substr($str, 0, 2) == "\r\n") { // CRLFであれば行をリセット
// 行末のスペースとタブは削除
if(preg_match("/^(.*[^ \t])[ \t]+\$/s", $cano, $reg))
$cano = $reg[1];
$b = "";
$cano .= "\r\n";
$ofs = 2;
} else {
// 裸のCRはエンコード
$eFlg = true;
}
} elseif($ord < 32) {
$eFlg = true;
}
// その他文字はそのまま
}
}
$append = $b;
if($eFlg) {
$append = "";
for($i=0; $i < strlen($b); $i++)
$append .= sprintf("=%02X", ord(substr($b, $i, 1)));
}
$lines = split("\r\n", $cano);
if(strlen($lines[count($lines)-1]) + strlen($append) >= 76)
$cano .= "=\r\n";
$cano .= $append;
$str = substr($str, $ofs);
}
return $cano;
}
汚いコードで時間もかかりますが、一応動くようです。
でも、もう少し効率のいいものに変えたいですね...。
もう少し処理時間が短くて済む関数を作りました。
コードを見ると性格がわかりますよねー
せんせーは、とても素直な方だということがわかりました。
わたしは古い人間なので、アセンブラ、BASIC、C、pascalなのですが、基本力技です。
我流でサーセン
コードは確かに性格をよく反映してる気がしますね。
コメントをどこに入れるかで、なにを重要視しているかとか分かったり、変数の定義やフローを見れば整理好きかどうかが分かったりとか。
コードでも他人の真似しかしない子は、私は信用しません!
アセンブラ言語使えるのってすごいですねぇ。
しかし、アセンブラ、BASIC(N88?)、Pascal…時代がよくわk…いや、クラシックでいいんじゃないんでしょうか^^