2009-08-18 19 views
7

我們有一個自定義的PHP電子郵件營銷應用程序和一個有趣的問題: 如果郵件的主題行包含帶有重音符的單詞,它會「吞下」它與下一個單詞之間的空格。 一個例子:短語電子郵件主題中斷的重音詞 - 我該如何阻止?

安赫爾Ríos的escuchaýsorprende

被示出(由至少Gmail的和Lotus Notes),爲

ÁngelRíosescuchaýsorprende

的特定線在消息源中顯示:

Subject: =?ISO-8859-1?Q?=C1ngel?= =?ISO-8859-1?Q?R=EDos?= escucha y sorprende

(半滿頭):

Delivered-To: [email protected] 
Received: {elided} 
Return-Path: <[email protected]> 
Received: {elided} 
Received: (qmail 23734 invoked by uid 48); 18 Aug 2009 13:51:14 -0000 
Date: 18 Aug 2009 13:51:14 -0000 
To: "Adriano" <[email protected]> 
Subject: =?ISO-8859-1?Q?=C1ngel?= =?ISO-8859-1?Q?R=EDos?= escucha y sorprende 
MIME-Version: 1.0 
From: {elided} 
X-Mailer: PHP 
X-Lista: 1290 
X-ID: 48163 
Content-Type: text/html; charset="ISO-8859-1" 
Content-Transfer-Encoding: quoted-printable 
Message-ID: <[email protected]> 

編輯:

應用程序使用的是舊版本的Html啞劇郵件的準備的消息,我會嘗試升級到新版本。無論如何,這是編碼主題的功能:

/** 
* Function to encode a header if necessary 
* according to RFC2047 
*/ 
function _encodeHeader($input, $charset = 'ISO-8859-1') 
{ 
    preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches); 
    foreach ($matches[1] as $value) { 
     $replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value); 
     $input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input); 
    } 

    return $input; 
} 

這裏,它是其中標的編碼代碼:收轉

的問題是,

if (!empty($this->headers['Subject'])) { 
    $subject = $this->_encodeHeader($this->headers['Subject'], 
            $this->build_params['head_charset']); 
    unset($this->headers['Subject']); 
} 

,事實上,該方案並沒有對上述案例的空間進行編碼。 The accepted answer解決了我的問題,經過微小的修改(在對該答案的評論中提到),因爲安裝的PHP版本不支持特定的實現細節。

最終答案

雖然接受的答案沒有解決的問題,我們發現它與許多成千上萬的電子郵件的合併,嚼在服務器上的所有可用內存。我檢查這封電子郵件的框架的原始開發商的網站,發現該功能已經更新到以下幾點:

function _encodeHeader($input, $charset = 'ISO-8859-1') { 
     preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches); 
     foreach ($matches[1] as $value) { 
      $replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value); 
      $input = str_replace($value, $replacement , $input); 
     } 
     if (!empty($matches[1])) { 
      $input = str_replace(' ', '=20', $input); 
      $input = '=?' . $charset . '?Q?' .$input . '?='; 
     } 
     return $input; 
    } 

整齊地解決了這個問題,並下MEM限制留了下來。

+0

你在使用,如果有的話,做的主題行和/或發送電子郵件的編碼? – Joe 2009-08-18 14:01:44

+0

你是否嘗試過編碼空間?或者整個主題一次? – Gumbo 2009-08-18 14:44:02

回答

5

您需要進行編碼空間之間以及(見RFC 2047):相鄰之間

(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)  (ab) 

空白'編碼字'不顯示。

[...]

(=?ISO-8859-1?Q?a_b?=)      (a b) 

爲了使一個空間,編碼文本的一部分內被顯示,該空間必須被編碼爲「編碼字」的一部分。

(=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=) (a b) 

爲了使一個空間,編碼文本的兩個字符串之間被顯示,該空間可以被編碼爲「編碼字的中的一個的一部分。

所以這應該這樣做:

Subject: =?ISO-8859-1?Q?=C1ngel=20R=EDos?= escucha y sorprende 

編輯試試這個功能:

function _encodeHeader($str, $charset='ISO-8859-1') 
{ 
    $words = preg_split('/(\s+)/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 
    $func = create_function('$match', 'return $match[0] === " " ? "_" : sprintf("=%02X", ord($match[0]));'); 
    $encoded = false; 
    foreach ($words as $key => &$word) { 
     if (!ctype_space($word)) { 
      $tmp = preg_replace_callback('/[^\x21-\x3C\x3E-\x5E\x60-\x7E]/', $func, $word); 
      if ($tmp !== $word) { 
       if (!$encoded) { 
        $word = '=?'.$charset.'?Q?'.$tmp; 
       } else { 
        $word = $tmp; 
        if ($key > 0) { 
         $words[$key-1] = preg_replace_callback('/[^\x21-\x3C\x3E-\x5E\x60-\x7E]/', $func, $words[$key-1]); 
        } 
       } 
       $encoded = true; 
      } else { 
       if ($encoded) { 
        $words[$key-2] .= '?='; 
       } 
       $encoded = false; 
      } 
     } 
    } 
    if ($encoded) { 
     $words[$key] .= '?='; 
    } 
    return implode('', $words); 
} 
+0

謝謝!這個伎倆。如果找到特殊字符,我修改了html mime郵件源以對空格進行編碼。 – 2009-08-18 16:09:25

+0

必須在foreach中重新實現您使用foreach $ words的位作爲$ key =>&$ word並使用$ words [$ key]。 – 2009-08-26 20:31:26

0

看起來您最好發送Subject: =?ISO-8859-1?Q?=C1ngel R=EDos escucha y sorprende?=,因爲問題出現在?=編碼結尾附近。

1

查找mbstring和UTF轉換。非英語語言中的許多特殊字符以UTF8字符集處理。

將您的主題字符串轉換爲UTF8並確保發送電子郵件應該正確顯示主題行。

至少它爲我們做的時候,我們也有類似的問題發送電子郵件

2

添加

$input = str_replace('?', '=3F', $input); 

在這個片段:

if (!empty($matches[1])) { 
$input = str_replace('?', '=3F', $input); 
$input = str_replace(' ', '=20', $input); 
$input = '=?' . $charset . '?Q?' .$input . '?='; 
} 
相關問題