电子邮件主题突破间距中的重音字母 - 我该如何阻止? [英] accented words in email subject break spacing - how do I stop this?

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

问题描述

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



ÁngelRíosescucha y sorprende





ÁngelRíosescucha y sorprende



消息源中的特定行显示:



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



(半满标题):

  Delivered-To:me@gmail.com 
收到:{elided}
返回路径:< return @路径>
收到:{elided}
收到:(由uid 48调用的qmail 23734);日期: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版本:1.0
从:{elided}
X-Mailer:PHP
X-Lista:1290
X-ID:48163
内容类型:text / html; charset =ISO-8859-1
内容转移编码:quoted-printable
Message-ID:< kokrte.rpq06m@example.com>

编辑:



应用程序使用旧版本的Hime 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']);
}

总结



问题是,事实上,在提到的情况下,程序没有编码空间。 接受的答案解决了我的问题,经过轻微修改(在该回答的评论中提到),因为安装的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 ='=?'。 $字符集。 '?Q?'$输入。 =;
}
return $ input;
}

它整齐地解决了这个问题,并保持在mem限制之下。

解决方案

您还需要对其间的空格进行编码(请参阅 RFC 2047 ):


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

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



[...]

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

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

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

为了使空格在两个编码文本串之间显示,空格可能是编码为编码词之一的一部分。


所以应该这样做:

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




修改尝试此功能:

 函数_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);
}


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天全站免登陆