The Code Cave

June 28, 2006

Please include your work to support the answer…

Filed under: PHP — Brian @ 5:59 pm

Cindy’s comment on my last post reminded me that I did not show any of the routines I tried while trying to figure out how to get the full raw email from the built in PHP imap_ routines.

So, here it is… It is obviously scrap work, but some one might find it useful to have all in one place. Just save this as a php file on your server (some place not shared since you’ll have your email password in it in raw text) and then change the mail server, username and password references (3 of them) to your own. As is, this routine will display a VERY simple webmail reader. It displays a list of messages in your box and the contents of 1 message.

It should give you the groundworks for building something more complex.

However, what it does not include is any part of the TRUE header which is what I pointed out here that I really need.

BTW this routine is OBVIOUSLY NOT safe html. If you display an email that has an embedded code that does nasty stuff, this testing routine will not protect you from it. It is JUST test code. Use it wisely.

PHP:
  1. <?php
  2. print(‘<br/>This is just an example of how I research a topic.  <br/>’);
  3. print(‘Therefore it is not fully documented or clean.  <br/>It contains code fragments of my own making and those found on the web, who knows where.  <br/><br/>’);
  4. print(‘There are THREE places where you must put in your email server, email username and email password. <br/>’);
  5. print(‘Otherwise, you will get very limited results.<br/><br/>’);
  6.  
  7. function list_emails(){
  8.   $MAILSERVER=“{imap.1and1.com:143}”;
  9.   // or $MAILSERVER="{pop.1and1.com:110}";
  10.   // or $MAILSERVER="{localhost:143}";
  11.   $PHP_AUTH_USER = “YourAddrHere@thecodecave.com”;
  12.   $PHP_AUTH_PW = “YOUR_PW_HERE”;
  13.  
  14.   $mbox=imap_open($MAILSERVER,
  15.                  $PHP_AUTH_USER,
  16.                  $PHP_AUTH_PW);
  17.  
  18.   print(‘<br/><hr/><br/>’);
  19.   print(‘<br/><strong>THIS SECTION REPORTS ON THE FULL MAIL BOX</strong><br/><br/>’);
  20.  
  21.   echo “Number of Total Emails: “
  22.        .imap_num_msg($mbox);
  23.   echo “  Number of Recent Emails: “
  24.        .imap_num_recent($mbox).“<BR><BR>”;
  25.   $headers=imap_headers($mbox);
  26.   for($x=0; $x <count($headers); $x++) {
  27.      $idx=($x+1);
  28.      echo $idx.“  <a href=\”$PHP_SELF?num=$idx\”>
  29.                    $headers[$x]
  30.                      </a><br>”;
  31.   }
  32.   imap_close($mbox);
  33. }
  34.  
  35. function view_message_num($num){
  36.   $MAILSERVER=“{imap.1and1.com:143}”;
  37.   // or $MAILSERVER="{pop.1and1.com:110}";
  38.   // or $MAILSERVER="{localhost:143}";
  39.   $PHP_AUTH_USER = “YourAddrHere@thecodecave.com”;
  40.   $PHP_AUTH_PW = “YOUR_PW_HERE”;
  41.  
  42.   $mbox=imap_open($MAILSERVER,
  43.                  $PHP_AUTH_USER,
  44.                  $PHP_AUTH_PW);
  45.   $header=imap_headerinfo($mbox,
  46.                          $num,
  47.                          180, 180);
  48.   print(‘<br/><hr/><br/>’);
  49.   print(‘<br/><strong>This is a print_r of the header contents.</strong><br/><br/>’);
  50.   print_r($header);
  51.   print(‘<br/><hr/><br/>’);
  52.   print(‘<br/><strong>This is a print_r of only the header->from contents.<br/>I wanted to ensure the print_r contained all the info from the subarrays.  This text should also be found above.</strong><br/><br/>’);
  53.   print_r($header->from);
  54.   print(‘<br/><hr/><br/>’);
  55.   print(‘<br/><strong>This is the header info parsed out</strong><br/><br/>’);
  56.   $from = $header->from;
  57.   $udate=$header->udate;
  58.   $date=Date(“F j, Y, g:i a”, $udate);
  59.   echo “Message Number: “. $num.“<br>”;
  60.   $subject= $header->fetchsubject;
  61.   if (is_array($from)){
  62.     while(list($key, $val) = each($from)) {
  63.       echo “From Address:  “;
  64.       echo $fromaddr=sprintf(“%s@%s”,
  65.                          $from[0]->mailbox,
  66.                          $from[0]->host).
  67.                          “<BR>”;
  68.       echo “Personal    :  “.
  69.       $from[0]->personal.
  70.         “<br>”;
  71.       echo “Adl        :  “.
  72.       $from[0]->adl.
  73.         “<br>”;
  74.       echo “Mailbox    :  “.
  75.       $from[0]->mailbox.
  76.         “<br>”;
  77.       echo “Host        :  “.
  78.         $from[0]->host.
  79.         “<br>”;
  80.       echo “Subject    :  “.
  81.         $subject.
  82.         “<br>”;
  83.       echo “Date        :  “.
  84.         $date.
  85.         “<br>”;
  86.       echo “To Address  :  “.
  87.         $header->toaddress.
  88.         “<br><BR><BR>”;
  89.     }
  90.   }
  91.  
  92.   print(‘<br/><hr/><br/>’);
  93.   print(‘<br/><strong>This is a print_r of the results of a fetchstructure</strong><br/><br/>’);
  94.   $mid = $num;
  95.   $struct = imap_fetchstructure($mbox, $mid);
  96.   print_r($struct);
  97.        $parts = $struct->parts;
  98.        $i = 0;
  99.  
  100.        if (!$parts)
  101.        {
  102.             /* Simple message, only 1 piece */
  103.          $attachment = array(); /* No attachments */
  104.          $content = imap_body($mbox, $mid);
  105.        }
  106.        else
  107.        {
  108.             /* Complicated message, multiple parts */
  109.  
  110.          $endwhile = false;
  111.  
  112.          $stack = array(); /* Stack while parsing message */
  113.          $content = “”;    /* Content of message */
  114.          $attachment = array(); /* Attachments */
  115.  
  116.          while (!$endwhile)
  117.          {
  118.            if (!$parts[$i])
  119.            {
  120.              if (count($stack)> 0)
  121.              {
  122.                $parts = $stack[count($stack)-1][“p”];
  123.                $i    = $stack[count($stack)-1][“i”] + 1;
  124.                array_pop($stack);
  125.              }
  126.              else
  127.              {
  128.                $endwhile = true;
  129.              }
  130.            }
  131.  
  132.            if (!$endwhile)
  133.            {
  134.              /* Create message part first (example ‘1.2.3′) */
  135.              $partstring = “”;
  136.              foreach ($stack as $s)
  137.              {
  138.                $partstring .= ($s[“i”]+1) . “.”;
  139.              }
  140.              $partstring .= ($i+1);
  141.  
  142.              if (strtoupper($parts[$i]->disposition) == “ATTACHMENT”) { /* Attachment */
  143.                $attachment[] = array(“filename” => $parts[$i]->parameters[0]->value,
  144.                                      “filedata” => imap_fetchbody($mbox, $mid, $partstring));
  145.              }
  146.              elseif (strtoupper($parts[$i]->subtype) == “PLAIN”)
  147.              { /* Message */
  148.                $content .= imap_fetchbody($mbox, $mid, $partstring);
  149.              }
  150.            }
  151.  
  152.            if ($parts[$i]->parts)
  153.            {
  154.              $stack[] = array(“p” => $parts, “i” => $i);
  155.              $parts = $parts[$i]->parts;
  156.              $i = 0;
  157.            }
  158.            else
  159.            {
  160.              $i++;
  161.            }
  162.          } /* while */
  163.        } /* complicated message */
  164.  
  165.   print(‘<br/><hr/><br/>’);
  166.   print(‘<br/><strong>This is a print_r of the results of the entire content of the email turned into an array as offered by RJ<br/>NOTE: THIS MIGHT NOT BE SAFE HTML</strong><br/><br/>’);
  167.   print_r($content);
  168.  
  169.  
  170.   print(‘<br/><hr/><br/>’);
  171.   print(‘<br/><strong>This is a print_r of the body in text format.  This in theory should be included above, but this is quote protected.</strong><br/><br/>’);
  172.   $Body_text = quoted_printable_decode($content);
  173.   print_r($Body_text);
  174.  
  175.   imap_close($mbox);
  176. }
  177.  
  178. /*********************************************************************************/
  179. /*                             Calling routines                                  */
  180. /*********************************************************************************/
  181. list_emails();
  182. if (!isset($num)) {
  183.   $num =1;
  184. }
  185. view_message_num($num);
  186. ?>
  187. <hr/>
  188. <br/>
  189. <hr/>
  190.  
  191.  
  192. <?php
  193. function parsepart($p,$i){
  194.    global $link,$msgid,$partsarray;
  195.    //where to write file attachments to:
  196.    $filestore = ‘.’;
  197.  
  198.    //fetch part
  199.    $part=imap_fetchbody($link,$msgid,$i);
  200.    //if type is not text
  201.    if ($p->type!=0){
  202.        //DECODE PART
  203.        //decode if base64
  204.        if ($p->encoding==3)$part=base64_decode($part);
  205.        //decode if quoted printable
  206.        if ($p->encoding==4)$part=quoted_printable_decode($part);
  207.        //no need to decode binary or 8bit!
  208.  
  209.        //get filename of attachment if present
  210.        $filename=;
  211.        // if there are any dparameters present in this part
  212.        if (count($p->dparameters)>0){
  213.            foreach ($p->dparameters as $dparam){
  214.                if ((strtoupper($dparam->attribute)==‘NAME’) ||(strtoupper($dparam->attribute)==‘FILENAME’)) $filename=$dparam->value;
  215.                }
  216.            }
  217.        //if no filename found
  218.        if ($filename==){
  219.            // if there are any parameters present in this part
  220.            if (count($p->parameters)>0){
  221.                foreach ($p->parameters as $param){
  222.                    if ((strtoupper($param->attribute)==‘NAME’) ||(strtoupper($param->attribute)==‘FILENAME’)) $filename=$param->value;
  223.                    }
  224.                }
  225.            }
  226.        //write to disk and set partsarray variable
  227.        if ($filename!=){
  228.            $partsarray[$i][attachment] = array(‘filename’=>$filename,‘binary’=>$part);
  229.            $fp=fopen($filestore.$filename,“w+”);
  230.            fwrite($fp,$part);
  231.            fclose($fp);
  232.            }
  233.    //end if type!=0
  234.    }
  235.  
  236.    //if part is text
  237.    else if($p->type==0){
  238.        //decode text
  239.        //if QUOTED-PRINTABLE
  240.        if ($p->encoding==4) $part=quoted_printable_decode($part);
  241.        //if base 64
  242.        if ($p->encoding==3) $part=base64_decode($part);
  243.  
  244.        //OPTIONAL PROCESSING e.g. nl2br for plain text
  245.        //if plain text
  246.  
  247.        if (strtoupper($p->subtype)==‘PLAIN’)1;
  248.        //if HTML
  249.        else if (strtoupper($p->subtype)==‘HTML’)1;
  250.        $partsarray[$i][text] = array(‘type’=>$p->subtype,’string’=>$part);
  251.    }
  252.  
  253.    //if subparts… recurse into function and parse them too!
  254.    if (count($p->parts)>0){
  255.        foreach ($p->parts as $pno=>$parr){
  256.            parsepart($parr,($i.‘.’.($pno+1)));
  257.            }
  258.        }
  259. return;
  260. }
  261.  
  262. //open resource
  263.   $MAILSERVER=“{imap.1and1.com:143}”;
  264.   // or $MAILSERVER="{pop.1and1.com:110}";
  265.   // or $MAILSERVER="{localhost:143}";
  266.   $PHP_AUTH_USER = “YourAddrHere@thecodecave.com”;
  267.   $PHP_AUTH_PW = “YOUR_PW_HERE”;
  268.  
  269.   $link=imap_open($MAILSERVER,
  270.                  $PHP_AUTH_USER,
  271.                  $PHP_AUTH_PW);
  272.  
  273. $msgid = 2;
  274. //fetch structure of message
  275. $s=imap_fetchstructure($link, $msgid);
  276. print_r($s);
  277. die();
  278. //see if there are any parts
  279. if (count($s->parts)>0){
  280.    foreach ($s->parts as $partno=>$partarr){
  281.    //parse parts of email
  282.    parsepart($partarr,$partno + 1);
  283.    }
  284. }
  285.  
  286. //for not multipart messages
  287. else{
  288.    //get body of message
  289.    $text=imap_body($link,$msgid);
  290.    //decode if quoted-printable
  291.    if ($s->encoding==4) $text=quoted_printable_decode($text);
  292.    //OPTIONAL PROCESSING
  293.    if (strtoupper($s->subtype)==‘PLAIN’) $text=$text;
  294.    if (strtoupper($s->subtype)==‘HTML’) $text=$text;
  295.  
  296.    $partsarray[‘not multipart’][text]=array(‘type’=>$s->subtype,’string’=>$text);
  297. }
  298.   print(‘<br/><hr/><br/>’);
  299.   print(‘<br/><strong>This is a print_r of another method of getting the complete parts of the email.  This is the parts array.</strong><br/><br/>’);
  300.   print_r($partsarray);
  301. ?>

1 Comment »

  1. At this point, in light of RFC3501 s6.4.5, I'd be trying imap_fetchbody() with a variety of part numbers, such as "0", "HEADER" and "HEADER.FIELDS Received-SPF".

    IMAP is a crazy protocol. IMAP servers are even crazier.

    Comment by Libertus (Paul Mitchell) — July 2, 2006 @ 4:03 am

RSS feed for comments on this post. TrackBack URL

Leave a comment