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

Anuncios

Un pensamiento en “PHP, IMAP y encoding

  1. Ruth Escobar

    Hola, me sirvió mucho tu código como guía porque esto de obtener la información correctamente de un correo con las funciones IMAP es cosa de locos. De todas formas hice unas modificaciones, que las dejo aquí por si a alguien le sirve.
    Saludos!

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

    $body = null;
    $is_html = false;
    $charset = 'UTF-8';

    if (!empty($st->parts)) {

    for ($i = 0, $j = count($st->parts); $i parts[$i];
    if ($part->subtype == 'PLAIN') {
    $body = imap_fetchbody($inbox, $email_number, $i+1);
    $part = $st->parts[$i+1];
    } elseif ($part->subtype == 'HTML') {
    $body = imap_fetchbody($inbox, $email_number, $i+1);
    $part = $st->parts[$i+1];
    $is_html = true;
    }

    if(!empty($part->parameters)){
    for ($k = 0, $l = count($part->parameters); $k parameters[$k];

    if(strtolower($attribute->attribute) == 'charset'){
    $charset = $attribute->value;
    }
    }
    }
    }
    } else {
    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);
    $bodytext = mb_convert_encoding($body, 'UTF-8', $charset);

    return $bodytext;
    }

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s