2011-12-24 9 views
7

Próbuję przesłać przychodzące wiadomości e-mail do skryptu PHP, aby móc je przechowywać w bazie danych i innych rzeczach. Używam klasy MIME E-mail message parser (registration required), chociaż nie sądzę, że to ważne.Właściwy sposób dekodowania tematu wiadomości przychodzących (utf 8)

Mam problem z tematami wiadomości e-mail. To działa dobrze, gdy tytuł jest w języku angielskim, ale jeśli przedmiotem wykorzystuje znaki spoza alfabetu łacińskiego uzyskać coś podobnego

=?UTF-8?B?2KLYstmF2KfbjNi0?= 

o tytuł jak یک دو سه

I zdekodować przedmiot takiego:

$subject = str_replace('=?UTF-8?B?' , '' , $subject); 
    $subject = str_replace('?=' , '' , $subject);  
    $subject = base64_decode($subject); 

Działa dobrze na krótkich tematach z 10-15 znakami, ale z dłuższym tytułem otrzymuję połowę oryginalnego tytułu z czymś podobnym na końcu.

Jeśli tytuł jest dłuższy, np. 30 znaków, nic nie dostaję. Czy robię to dobrze?

+1

To nie jest oprogramowanie najwyższej jakości, które wybrałeś. Sprawdź http://stackoverflow.com/questions/4721410/best-way-to-handle-email-parsing-decoding-in-php, prawdopodobnie wszyscy wykonują dekodowanie i nie wymagają takich hacków. – mario

Odpowiedz

12

Mimo że minęło już prawie rok - znalazłem to i stoję przed podobnym problemem.

Nie jestem pewien, dlaczego otrzymujesz nieparzyste znaki, ale być może próbujesz wyświetlić je gdzieś, gdy Twój zestaw znaków jest nieobsługiwany.

Oto napisany przeze mnie kod, który powinien obsługiwać wszystko z wyjątkiem konwersji zestawu znaków, co jest dużym problemem, który wiele bibliotek radzi sobie znacznie lepiej. (PHP MB library, na przykład)

class mail { 
    /** 
     * If you change one of these, please check the other for fixes as well 
    * 
    * @const Pattern to match RFC 2047 charset encodings in mail headers 
    */ 
    const rfc2047header = '/=\?([^ ?]+)\?([BQbq])\?([^ ?]+)\?=/'; 

    const rfc2047header_spaces = '/(=\?[^ ?]+\?[BQbq]\?[^ ?]+\?=)\s+(=\?[^ ?]+\?[BQbq]\?[^ ?]+\?=)/'; 

    /** 
    * http://www.rfc-archive.org/getrfc.php?rfc=2047 
    * 
    * =?<charset>?<encoding>?<data>?= 
    * 
    * @param string $header 
    */ 
    public static function is_encoded_header($header) { 
     // e.g. =?utf-8?q?Re=3a=20Support=3a=204D09EE9A=20=2d=20Re=3a=20Support=3a=204D078032=20=2d=20Wordpress=20Plugin?= 
     // e.g. =?utf-8?q?Wordpress=20Plugin?= 
     return preg_match(self::rfc2047header, $header) !== 0; 
    } 

    public static function header_charsets($header) { 
     $matches = null; 
     if (!preg_match_all(self::rfc2047header, $header, $matches, PREG_PATTERN_ORDER)) { 
      return array(); 
     } 
     return array_map('strtoupper', $matches[1]); 
    } 

    public static function decode_header($header) { 
     $matches = null; 

     /* Repair instances where two encodings are together and separated by a space (strip the spaces) */ 
     $header = preg_replace(self::rfc2047header_spaces, "$1$2", $header); 

     /* Now see if any encodings exist and match them */ 
     if (!preg_match_all(self::rfc2047header, $header, $matches, PREG_SET_ORDER)) { 
      return $header; 
     } 
     foreach ($matches as $header_match) { 
      list($match, $charset, $encoding, $data) = $header_match; 
      $encoding = strtoupper($encoding); 
      switch ($encoding) { 
       case 'B': 
        $data = base64_decode($data); 
        break; 
       case 'Q': 
        $data = quoted_printable_decode(str_replace("_", " ", $data)); 
        break; 
       default: 
        throw new Exception("preg_match_all is busted: didn't find B or Q in encoding $header"); 
      } 
      // This part needs to handle every charset 
      switch (strtoupper($charset)) { 
       case "UTF-8": 
        break; 
       default: 
        /* Here's where you should handle other character sets! */ 
        throw new Exception("Unknown charset in header - time to write some code."); 
      } 
      $header = str_replace($match, $data, $header); 
     } 
     return $header; 
    } 
} 

Po uruchomieniu przez skrypt i wyświetlane w przeglądarce za pomocą UTF-8, wynik jest:

آزمایش

by uruchomić go tak:

$decoded = mail::decode_header("=?UTF-8?B?2KLYstmF2KfbjNi0?="); 
+0

Możesz użyć '$ data = iconv ($ charset, 'UTF-8 // TRANSLIT', $ data);' lub '$ data = mb_convert_encoding ($ dane, 'UTF-8', $ charset);' dla dekodowanie nietypowych znaków.Wolę drugą drogę. – Stalinko

+0

dziękuję .. @razzed – NaveenDA

2

Zastosowanie php:

<?php 
imap_utf8($text); 
?> 
2

Zastosowanie natywna funkcja

<?php 
mb_decode_mimeheader($text); 
?> 

Ta funkcja może obsługiwać utf8 jak izo-8859-1 łańcucha. Testowałem to.

+0

To również odszyfruje non utf8 podmiotów. Spróbuj, jeśli (preg_match ('/ \? Utf-8 \?//,, Temat $)) $ subject = mb_decode_mimeheader ($ subject); – Juergen

Powiązane problemy