Search code examples
phpimap

Weird E-Mail parsing error with Paypal Donation Mail


I want to automatically process E-Mails which I get from Paypal for donations to my E-Mail-Adress. (via cronjob and php script) So far, so good. I made a test donation and for further testing, I copy this mail with Outlook to INBOX several times. Everything worked fine with the copied Mail (I'm checking a String in E-Mail Body) but now I've made another test donation and it wasn't working. It turned out that the E-Mail-Body is not parsed correctly. I've tried already with Ararat Synapse in Delphi but same result.

The correct E-Mail Body from copied Mail looks like this:

Guten Tag Peter Meier ! Diese E-Mail bestätigt den Erhalt einer Spende über €1,50 EUR von Peter Meier ([email protected] ). Sie können die Transaktionsdetails online abrufen . Spendendetails Gesamtbetrag: €1,50 EUR

But the original Mail from Paypal is parsed as

PGh0bWwgPgogICA8aGVhZD4KICAgCQk8bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUi IGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1VVEYtOCI+CiAgIAkJPG1ldGEgbmFtZT0i dmlld3BvcnQiIGNvbnRlbnQ9ImluaXRpYWwtc2NhbGU9MS4wLG1pbmltdW0tc2NhbGU9MS4w LG1heGltdW0tc2NhbGU9MS4wLHdpZHRoPWRldmljZS13aWR0aCxoZWlnaHQ9ZGV2aWNlLWhl aWdodCx0YXJnZXQtZGVuc2l0eWRwaT1kZXZpY2UtZHBpLHVzZX...

And so on, copiedmail.html is 3KB, original is 28KB.

My Code:

$connection = imap_open("{imap.gmx.net:993/imap/ssl}", "[email protected]", "password"); //connect
$count = imap_num_msg($connection); //get E-Mail count in INBOX
for($msgno = 1; $msgno <= $count; $msgno++)  //walk through INBOX mails
{
  $headers = imap_headerinfo($connection, $msgno); //read E-Mail header
  $subject = $headers->subject; //read subject
  //decode subject
  $elements = imap_mime_header_decode($subject);
  $decodedsubject="";
  for ($i=0; $i<count($elements); $i++) 
  {
    $decodedsubject = $decodedsubject.$elements[$i]->text;
  }
  $body = imap_fetchbody ($connection, $msgno, 1); //read body
  echo $body; <--- Here I get long cryptic Text in original Mail
}

Solution

  • Thanks to NineBerry, I found out that paypal uses base64 encoding for their mails. So the body was parsed correctly by this code

    $body = imap_fetchbody ($connection, $msgno, 1); //read E-Mail-Body
    $body = imap_base64($body);
    echo $body;
    

    To check encoding as suggested, you could do:

    $structure = imap_fetchstructure($connection, $msgno);
    $encoding = $structure->encoding;
    $body = imap_fetchbody ($connection, $msgno, 1);
    $body=decodebody($encoding, $body);
    echo $body;
    
    function decodebody($encoding, $body)
    {
    switch ($encoding) 
    {
        # 7BIT
        case ENC7BIT:
            echo "7BIT<br>";//
            return $body;
            break;
        # 8BIT
        case ENC8BIT:
            echo "8BIT<br>";//
            return quoted_printable_decode(imap_8bit($body));
            break;
        # BINARY
        case ENCBINARY:
            echo "BINARY<br>";//
            return imap_binary($body);
            break;
        # BASE64
        case ENCBASE64:
            echo "BASE64<br>";//
            return imap_base64($body);
            break;
        # QUOTED-PRINTABLE
        case ENCQUOTEDPRINTABLE:
            echo "QUOTED<br>";//
            return quoted_printable_decode($body);
            break;
        # OTHER
        case ENCOTHER:
            echo "OTHER<br>";//
            return $body;
            break;
        # UNKNOWN
        default:
            echo "UNKNOWN<br>";//
            return $body;
            break;
    }
    }
    

    Of course echo in function is only for you to check. BTW, I pasted the snippet from my Original Question to this online decoder: https://www.base64decode.org and it also worked :)