电子邮件主题中断间距的重音单词 - 我如何停止这个? [英] accented words in email subject break spacing - how do I stop this?

查看:151
本文介绍了电子邮件主题中断间距的重音单词 - 我如何停止这个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个自定义的php电子邮件营销应用程序,并且有一个有趣的问题:
如果邮件的主题行包含带重音的单词,它会吞下它和下面的单词之间的空格。
例如:





至少显示为





消息源中的特定行显示:



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



(半完整标题):

  Delivered-To:me@gmail.com 
收到:{elided}
返回路径:< return @ path>
Received:{elided}
Received:(qmail 23734 invoked by uid 48); 18 Aug 2009 13:51:14 -0000
日期:2009年8月18日13:51:14 -0000
到:Adriano< me@gmail.com>
主题:=?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:< kokrte.rpq06m@example.com>

编辑



应用程式使用旧版本的Html Mime Mail来准备邮件,我会尝试升级到较新版本。无论如何,这是对主题进行编码的函数:

  / ** 
*
*根据RFC2047
* /
函数_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 (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']);
}

总结
$ b

问题是,程序确实不是在提到的情况下编码空间。 接受的答案解决了我的问题,稍作修改(在对该答案的评论中提到),因为安装的PHP版本不支持特定的实现细节。



最终答案



虽然接受的答案确实解决了问题,但我们发现,它与数以千计的电子邮件一起,内存在服务器上。我检查了这个电子邮件框架的原始开发者的网站,发现该函数已更新为以下内容:

 函数_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 (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限制。

解决方案

你需要对两者之间的空格进行编码(参见 RFC 2047 ):


   

不显示相邻的编码字之间的空格。



[...]

 (=?ISO-8859-1?Q?a_b?=)(ab)

为了使空格显示在编码文本的一部分中,空格必须编码为编码字的一部分。

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

为了使空格显示在两个编码文本字符串之间,空格可以编码为


因此,应该这样做:

 主题:=?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?'。
} 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);
}


We have a custom php email marketing app, and an interesting problem: If the subject line of the message contains a word with accents, it 'swallows' the spaces between it and the following word. An example: the phrase

Ángel Ríos escucha y sorprende

is shown (by at least gmail and lotus notes) as

ÁngelRíos escucha y sorprende

The particular line in the message source shows:

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

(semi-full headers):

Delivered-To: me@gmail.com
Received: {elided}
Return-Path: <return@path>
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" <me@gmail.com>
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: <kokrte.rpq06m@example.com>

EDIT:

The app uses an old version of Html Mime Mail to prepare messages, I'll try to upgrade to a newer version. Anyway, this is the function that encodes the subject:

/**
 * 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;
}

And here it's the code where the subject is encoded:

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

Wrap-up

The problem was that, indeed, the program wasn't encoding the space in the case mentioned. The accepted answer solved my problem, after a slight modification (mentioned in the comments to that answer) because the installed version of PHP didn't support a particular implementation detail.

Final answer

Although the accepted answer did solve the problem, we found that it, combined with many thousands of emails, was chewing all the available memory on the server. I checked the website of the original developer of this email framework, and found that the function had been updated to the following:

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;
    }

which neatly solved the problem and stayed under the mem limit.

解决方案

You need to encode the space in between as well (see RFC 2047):

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

White space between adjacent 'encoded-word's is not displayed.

[…]

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

In order to cause a SPACE to be displayed within a portion of encoded text, the SPACE MUST be encoded as part of the 'encoded-word'.

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

In order to cause a SPACE to be displayed between two strings of encoded text, the SPACE MAY be encoded as part of one of the 'encoded-word's.

So this should do it:

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


Edit    Try this function:

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);
}

这篇关于电子邮件主题中断间距的重音单词 - 我如何停止这个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆