星期二, 8月 16, 2011

修正8 bit header在Roundcube顯示亂碼問題

之前寫過很多次,一直找到能接替Openwebmail的下一代webmail,最後採用Roundcube

RFC裏明明規定email header必須用7bit,但是早期的email client如Outlook Express、Becky等都有允許8bit的功能,因此亞洲不少國家流通的email都還有人在用8bit header。會出現允許八位元標頭是因為早期Unix上pine/elm等client軟體沒有編碼/解碼功能,為了讓收件人在elm上能看得到主旨才這麼做。現在新的email client都沒有允許八位元標頭的選項。

Openwebmail若指定預設語系Big5編碼,在收到Big5碼 8bit header郵件時完全正常,但若指定為UTF-8預設語系,則在Big5碼 8bit主旨會亂碼。

Roundcube內定即是UTF-8編碼,大部份的email轉碼都很正常,但是Big5、GB2312等8bit 標頭則會變成亂碼;我在求助無門的情況下只好自力救濟。

Update: Roundcube會對其他編碼處理,但是限於在header有指定Content-Type, charset才行。

原本想利用Roundcube的plugin方式修改subject,但是改了3小時一無所獲,最後只好用硬改的方式搞定。我是在FreeBSD 8.2上改roundcube-0.5.3,相信其他系統應該也類似。
在 roundcube/program/include/rcube_imap_generic.php 第 1666行加上以下兩列即可:

$encoding = mb_detect_encoding($string, "ascii,  cp950, big5, gb2312, gbk, cp936, utf-8, JIS, EUC-JP, auto");
$string =  mb_convert_encoding($string, "utf-8", $encoding );
Update:還要刪掉1690行對charset的判斷,因為原本Roundcube依此對標頭轉碼,反而會把已經是UTF-8的字串轉爛

patch file如下
--- /usr/local/www/roundcube/program/include/rcube_imap_generic.php 2011-05-05 00:02:53.000000000 +0800
+++ /usr/local/www/roundcube/program/include/rcube_imap_generic.php 2011-08-16 11:55:13.000000000 +0800
@@ -1663,6 +1663,9 @@
$field = strtolower($field);
$string = preg_replace('/\n[\t\s]*/', ' ', trim($string));

+ $encod = mb_detect_encoding($string, "ascii, cp950, big5, gb2312, gbk, cp936, utf-8, JIS, EUC-JP, auto");
+ $string = mb_convert_encoding($string, "utf-8", $encod);
+
switch ($field) {
case 'date';
$result[$id]->date = $string;
@@ -1690,11 +1693,6 @@
$result[$id]->encoding = $string;
break;
case 'content-type':
- $ctype_parts = preg_split('/[; ]/', $string);
- $result[$id]->ctype = strtolower(array_shift($ctype_parts));
- if (preg_match('/charset\s*=\s*"?([a-z0-9\-\.\_]+)"?/i', $string, $regs)) {
- $result[$id]->charset = $regs[1];
- }
break;
case 'in-reply-to':
$result[$id]->in_reply_to = str_replace(array("\n", '<', '>'), '', $string);

沒有留言: