parole accentate nell'object della posta elettronica interrompono la spaziatura – come posso fermarlo?

Abbiamo un'app personalizzata di email marketing php e un problema interessante: se l'object del messaggio contiene una parola con accenti, "inghiotte" gli spazi tra esso e la parola seguente. Un esempio: la frase

Ángel Ríos escucha y sorprende

viene mostrato (da alless gmail e note di loto) come

ÁngelRíos escucha y sorprende

La linea specifica nella fonte del messaggio mostra:

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

(intestazioni semi-piene):

 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]> 

MODIFICARE:

L'app utilizza una vecchia versione di Html Mime Mail per preparare i messaggi, proverò ad aggiornare a una versione più recente. Ad each modo, questa è la function che codifica il sobject:

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

E qui è il codice in cui il sobject è codificato:

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

Incartare

Il problema era che, in effetti, il programma non codificava lo spazio nel caso menzionato. La risposta accettata ha risolto il mio problema, dopo una leggera modifica (menzionata nei commenti a quella risposta) perché la versione installata di PHP non supportva particolari dettagli di implementazione.

Risposta finale

Sebbene la risposta accettata abbia risolto il problema, abbiamo riscontrato che, combinata con molte migliaia di e-mail, stava masticando tutta la memory disponibile sul server. Ho controllato il sito web dello sviluppatore originale di questo framework email e ho scoperto che la function era stata aggiornata al seguente:

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

che risolveva perfettamente il problema e rimaneva sotto il limite del mem.

Devi anche codificare lo spazio intermedio (vedi RFC 2047 ):

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

Lo spazio bianco tra le "parole codificate" adiacenti non viene visualizzato.

[…]

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

Per far sì che uno SPAZIO venga visualizzato all'interno di una porzione di text codificato, lo SPAZIO DEVE essere codificato come parte della 'parola codificata'.

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

Per far sì che uno SPAZIO venga visualizzato tra due stringhe di text codificato, SPACE MAGGIO può essere codificato come parte di una delle "parole codificate".

Quindi questo dovrebbe farlo:

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

Modifica Prova questa 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); } 

Inserisci

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

in questo frammento:

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

Cerca le conversioni mbstring e UTF. Molti dei caratteri speciali in lingue diverse dall'inglese sono trattati nel set di caratteri UTF8.

Convertire la string sobject in UTF8 e assicurando che l'e-mail sia inviata come tale deve rendere correttamente le righe dell'object.

Alless lo ha fatto per noi quando abbiamo avuto un problema simile inviando email

Sembrerebbe che sia meglio submit Subject: =?ISO-8859-1?Q?=C1ngel R=EDos escucha y sorprende?= , Subject: =?ISO-8859-1?Q?=C1ngel R=EDos escucha y sorprende?= il problema appare vicino alla fine della codifica? =.