PHP
  Home arrow PHP arrow Page 4 - Building A PHP-Based Mail Client (part 2)
Dev Shed Forums  
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Smartphone Development  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Mobile Linux  
App Generation ROI  
IBM® developerWorks  
Forums Sitemap  
E-Commerce Hosting  
Linux Web Hosting  
Managed Hosting  
Small Business Hosting  
VPS Hosting  
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid  
Request Media Kit
Contact Us  
Site Map  
Privacy Policy  
Support  
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

Building A PHP-Based Mail Client (part 2)
By: icarus, (c) Melonfire
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: starstarstarstarstar / 12
    2002-01-11


    Table of Contents:
  • Building A PHP-Based Mail Client (part 2)
  • A Picture Is Worth A Thousand Words
  • The Way Things Work
  • Structure And Syntax
  • Room With A View
  • Getting Down
  • Miles To Go

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      error-file:tidyout.log Del.ici.ous error-file:tidyout.log Digg
      error-file:tidyout.log Blink error-file:tidyout.log Simpy
      error-file:tidyout.log Google error-file:tidyout.log Spurl
      error-file:tidyout.log Y! MyWeb error-file:tidyout.log Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article

     
     
    ADVERTISEMENT


    Building A PHP-Based Mail Client (part 2) - Structure And Syntax
    ( Page 4 of 7 )

    Using this process flow as reference, let's now begin implementing the code for the mail client.

    A quick look at the PHP manual reveals that PHP provides a number of useful functions to assist in this process:

    1. imap_fetchstructure() - read and return information on message structure

    2. imap_header() - return an object containing header elements

    3. imap_body() - retrieve the complete message body

    4. imap_fetchbody() - retrieve a specific section of the body

    Of these, you've already seen the imap_fetchstructure() function in action - using a mailbox handle and message number as arguments, this function reads the message body and returns an object containing information on the message size, message body and MIME parts within it.

    This object exposes a "parts" property, which is itself an array; the elements of this array are objects representing the various sections of the message. Therefore, it's possible to identify whether or not a message contains multiple parts, and obtain information on those parts, simply by iterating through this array.

    Each of the objects in the "parts" array provides information on the corresponding message section - the encoding, the size, the type and subtype, the filename and so on. A complete list of the properties exposed by each of these objects is available in the PHP manual at http://www.php.net/manual/en/function.imap-fetchstructure.php - you should look at it before proceeding further.

    Using this information, it's possible to write a couple of simple functions that build on imap_fetchstructure() to deliver customized information about message sections:

    <? // define some constants // message types $type = array("text", "multipart", "message", "application", "audio", "image", "video", "other"); // message encodings $encoding = array("7bit", "8bit", "binary", "base64", "quoted-printable", "other"); // parse message body function parse($structure) { global $type; global $encoding; // create an array to hold message sections $ret = array(); // split structure into parts $parts = $structure->parts; for($x=0; $x<sizeof($parts); $x++) { $ret[$x]["pid"] = ($x+1); $this = $parts[$x]; // default to text if ($this->type == "") { $this->type = 0; } $ret[$x]["type"] = $type[$this->type] . "/" . strtolower($this->subtype); // default to 7bit if ($this->encoding == "") { $this->encoding = 0; } $ret[$x]["encoding"] = $encoding[$this->encoding]; $ret[$x]["size"] = strtolower($this->bytes); $ret[$x]["disposition"] = strtolower($this->disposition); if (strtolower($this->disposition) == "attachment") { $params = $this->dparameters; foreach ($params as $p) { if($p->attribute == "FILENAME") { $ret[$x]["name"] = $p->value; break; } } } } return $ret; } ?>
    The parse() function accepts an object, as returned by imap_fetchstructure(), and parses it to produce an array holding some very specific information on each message part.

    First, parse() creates an empty array named $ret, which will ultimately contain as many elements as there are message parts.

    <? // create an array to hold message sections $ret = array(); ?>
    Every element of $ret will itself be an associative array, with keys representing the part number, part type, encoding, disposition, size and filename.

    Next, parse() creates an array named $parts, to hold the object array returned by the "parts" property of the imap_fetchstructure() object.

    <? // split structure into parts $parts = $structure->parts; ?>
    parse() then iterates through $parts, adding each element to $ret and creating keys to represent the characteristics of each part found.

    <? for($x=0; $x<sizeof($parts); $x++) { $ret[$x]["pid"] = ($x+1); $ret[$x]["type"] = $type[$this->type] . "/" . strtolower($this->subtype); $ret[$x]["encoding"] = $encoding[$this->encoding]; $ret[$x]["size"] = strtolower($this->bytes); $ret[$x]["disposition"] = strtolower($this->disposition); // some parts snipped for brevity } ?>
    The IMAP specification (available at http://www.faqs.org/rfcs/rfc2060.html) defines a number, or part ID, for every part of a multipart message, starting from 1 (which is usually the message text itself); my array defines this part ID via the "pid" key, and I'm recording it at this stage itself because I'm sure to need it when handling messages containing more than one attachment.

    The type and encoding of each part are stored as integers by imap_fetchstructure(); these correspond to elements of the $type and $encoding arrays respectively. If you look at the complete function definition above, you'll see that these arrays are defined outside the function, and imported into it with the "global" keyword.

    Here's an example of the array returned by parse():

    Array ( [0] => Array ( [pid] => 1 [type] => text/plain [encoding] => 7bit [size] => 41 [disposition] => ) [1] => Array ( [pid] => 2 [type] => application/zip [encoding] => base64 [size] => 50634 [disposition] => attachment [name] => photos1.zip ) [2] => Array ( [pid] => 3 [type] => application/zip [encoding] => base64 [size] => 44882 [disposition] => attachment [name] => photos2.zip ) )
    As you can see, this is a fairly clear representation of the various sections that make up a MIME message.{mospagebreak title=Getting Attached} I've also written another function to extract the attachments only from the array returned by parse() - take a look at the get_attachments() function:

    <? // iterate through object returned by parse() // create a new array holding information only on message attachments function get_attachments($arr) { for($x=0; $x<sizeof($arr); $x++) { if($arr[$x]["disposition"] == "attachment") { $ret[] = $arr[$x]; } } return $ret; } ?>
    Let's now backtrack a little and add this code to the message listing, "list.php", where it will be used to identify which messages have attachments (so that an attachment icon can be displayed next to those messages).

    Here's the revised version of that script:

    <?php // list.php - display message list // includes include("functions.php"); // session check session_start(); if (!session_is_registered("SESSION")) { header("Location: error.php?ec=2"); exit; } // open mailbox $inbox = @imap_open ("{". $SESSION_MAIL_HOST . "/pop3:110}", $SESSION_USER_NAME, $SESSION_USER_PASS) or header("Location: error.php?ec=3"); // get number of messages $total = imap_num_msg($inbox); ?> <html> <head> </head> <body bgcolor="White"> <? // page header ?> <table width="100%" border="0" cellspacing="3" cellpadding="5"> <!-- command buttons - snipped --> </table> <? if ($total > 0) { ?> <table width="100%" border="0" cellspacing="0" cellpadding="5"> <form action="delete.php" method="post"> <!-- message info columns --> <tr> <td width="5%"><font size="-1">&nbsp;</font></td> <td width="5%"><font size="-1">&nbsp;</font></td> <td width="15%"><font face="Verdana" size="-1"><b>Date</b></font></td> <td width="20%"><font face="Verdana" size="-1"><b>From</b></font></td> <td width="45%"><font face="Verdana" size="-1"><b>Subject</b></font></td> <td width="10%"><font face="Verdana" size="-1"><b>Size</b></font></td> </tr> <?php // iterate through messages for($x=$total; $x>0; $x--) { // get header and structure $headers = imap_header($inbox, $x); $structure = imap_fetchstructure($inbox, $x); ?> <tr bgcolor="<?php echo $bgcolor; ?>"> <td align="right" valign="top"> <input type="Checkbox" name="dmsg[]" value="<? echo $x; ?>"> </td> <td valign="top"> <? // attachment handling code goes here // parse structure to see if attachments exist // display icon if so $sections = parse($structure); $attachments = get_attachments($sections); if(is_array($attachments)) { echo "<img alt=\"Message has attachment\" src=images/list.gif width=30 height=30 border=0>"; } else { echo "&nbsp;"; } ?> </td> <td valign="top"> <font face="Verdana" size="-1"><? echo substr($headers->Date, 0, 22); ?></font> </td> <td valign="top"> <font face="Verdana" size="-1"><? echo htmlspecialchars($headers->fromaddress); ?></font> </td> <td valign="top"> <font face="Verdana" size="-1"> <a href="view.php?id=<? echo $x; ?>"> <? // correction for empty subject if ($headers->Subject == "") { echo "No subject"; } else { echo $headers->Subject; } ?> </a> </font> </td> <td valign="top"> <font face="Verdana" size="-1"> <? // display message size echo ceil(($structure->bytes/1024)), " KB"; ?> </font> </td> </tr> <? } // clean up imap_close($inbox); ?> </form> </table> <? } else { echo "<font face=Verdana size=-1>You have no mail at this time</font>"; } ?> </body> </html>
    And here's what the listing looks like, after making the addition:



     
     
    >>> More PHP Articles          >>> More By icarus, (c) Melonfire
     

       

    PHP ARTICLES

    - Building Dynamic Queries with Chainable Meth...
    - PHP Encryption and Decryption Methods
    - Building a MySQL Abstraction Class with Meth...
    - Completing a Sample String Processor with Me...
    - Mastering WHILE Loops for PHP and MySQL
    - Method Chaining: Adding More Methods to the ...
    - Method Chaining in PHP 5
    - The Role of Interfaces in Applying the Depen...
    - Dependency Injection: Using a Setter Method ...
    - Using a Model Class with the Dependency Inje...
    - Injecting Objects Using Setter Methods with ...
    - Injecting Objects by Constructor with the De...
    - The Dependency Injection Design Pattern in P...
    - Performing Inferential Statistical Analysis ...
    - Performing Descriptive Statistical Analysis ...





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 5 Hosted by Hostway
    Stay green...Green IT