Archivo de la etiqueta: encoding

Unicode y UTF8

Después de varios intentos frustrados logré leer completa la nota de Joel On Software sobre encodings con interés genuino.

Resumiendo, lo mas importante de esa nota es que:

Unicode es un estándar que le asigna un código único (único posta) a cada caracter posible, chinos, occidentales, etc. Sin embargo Unicode no especifica cómo guardar en el disco estos caracteres. Incluye o es compatible con encodings viejos como ASCII7 y ISO 8859.

UTF-8 es un encoding que guarda los caracteres Unicode en al menos un byte cada uno y es compatible con algunos encodings mas limitados de caracteres con respecto a los caracteres en inglés, como ASCII7.

UTF-16 en cambio guarda todos los caracteres en 2 bytes o 4 bytes. La desventaja es que en general usa mas espacio que UTF-8.

Y hay varios mas. Básicamente estos encodings especifican cómo guardar físicamente los caracteres definidos en el estandar Unicode que es abstracto, independiente de la forma de guardarlos en disco. También hay temas de los que se abstrae como por ejemplo si los caracteres están dispuestos con Big-Endian o Little-Endian.

PHP, IMAP y encoding

Hoy sí que estuve renegando con los encoding y las funciones IMAP de PHP. El problema es que hay dos encodings, uno es el encoding de caracteres del body (UTF-8, ISO, etc.) y otro el encoding “quotable string” que es una especie de encoding de transporte. El tema es que para lograr, por ejemplo, que los mails que obtenemos de un servidor vengan en UTF-8 tenemos que hacer toda esta magia:


private function _get_plain_text_email_body($inbox, $email_number) {
 $st = imap_fetchstructure($inbox, $email_number);

 $body = null;
 $is_html = false;

 if (!empty($st->parts)) {
 for ($i = 0, $j = count($st->parts); $i < $j; $i++) {
 $part = $st->parts[$i];
 if ($part->subtype == 'PLAIN') {
 $body = imap_fetchbody($inbox, $email_number, $i+1);
 $part = $st->parts[$i+1];
 break;
 } elseif ($part->subtype == 'HTML') {
 $body = imap_fetchbody($inbox, $email_number, $i+1);
 $part = $st->parts[$i+1];
 $is_html = true;
 // No break - keep looking for PLAIN part
 }
 }
 } else {
 // TODO: implementar el checkeo de encoding cuando los mails vienen SOLO en texto plano o SOLO en HTML
 if ($st->subtype == 'PLAIN') {
 $body = imap_body($inbox, $email_number);
 } elseif ($st->subtype == 'HTML') {
 $body = imap_body($inbox, $email_number);
 $is_html = true;
 }
 }

 $body = imap_qprint($body);
 $charset = 'UTF-8';

 if(!empty($part->parameters)){
 for ($k = 0, $l = count($part->parameters); $k < $l; $k++) {
 $attribute = $part->parameters[$k];
 if(strtolower($attribute->attribute) == 'charset'){
 $charset = $attribute->value;
 }
 }
 }
 echo "Body's character encoding: $charset";

 $bodytext = mb_convert_encoding($body, 'UTF-8', $charset);

// Probablemente querramos implementar un método para evitar tener contenido HTML en los mails.
//if ($is_html){
//$bodytext = convert_html_to_text($bodytext);
//}
 return $bodytext;
 }

De donde saqué parte de la solución: http://stackoverflow.com/questions/10462212/mail-reading-in-php-with-imap