1

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 (peter.meier@gmx.de ). 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}", "peter.meier@gmx.de", "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
}
computerjulian
  • 173
  • 1
  • 11
  • Possible duplicate of [PHP IMAP decoding messages](http://stackoverflow.com/questions/15539902/php-imap-decoding-messages) – NineBerry Feb 22 '17 at 17:18
  • In addition to any issues with processing a particular PayPal email, you should be aware that PayPal actually has several different formats of acknowledgement emails and changes them periodically - new images, different layout, etc. So once you get it working "perfectly" you need to include some error checking to catch the format changes and save those messages for a new/updated processing script. – manassehkatz-Moving 2 Codidact Feb 22 '17 at 17:29
  • @NineBerry the solution from the post gives me this: Notice: Undefined variable: part in C:\xampp\htdocs\test\stackoverflow.php on line 34 Notice: Trying to get property of non-object in C:\xampp\htdocs\test\stackoverflow.php on line 34 Notice: Undefined variable: message in C:\xampp\htdocs\test\stackoverflow.php on line 37 – computerjulian Feb 22 '17 at 17:38
  • @manassehkatz thanks, I already hate paypal for delivering me this crap :D – computerjulian Feb 22 '17 at 17:41

1 Answers1

1

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 :)

computerjulian
  • 173
  • 1
  • 11