21.1 Mail Systems


E-mail has become a everyday task. Checking your e-mail in the morning or at work is almost as important as brushing your teeth. The Internet is a fundamental tool. E-mail is essential, and not only for business processes. This section is dedicated to e-mail and what you can do with e-mail. You will learn to check your e-mail with the help of PHP and you will see how to store information about e-mail in the database.

21.1.1 Fundamentals

Before we start with some nice source code, it is necessary to take a look at the fundamentals.

In many systems text was encoded using 7-bit code. Although an ASCII character needs 8 bits, many mail systems relied on 7-bit coding. In addition to ASCII characters, it is necessary to transmit binary data. To transmit data that cannot be coded using 7-bit characters, mechanisms for encoding the data have been invented. Several standards have been defined:

  • UUencode Unix-To-Unix-Encode was invented for managing the communication of Unix machines. The algorithm was widespread because back in the early days Unix servers were widespread. An encoded file is about 42% larger than the original file.

  • MIME MIME stands for Multipurpose Internet Mail Extensions. This format was invented for transmitting attachments as well as structured messages consisting of various components. In some cases Base64 encoding is used in combination with MIME. The exact definition can be found in RFC 2045.

  • Base64 Base64 is a standard way of transmitting attachments. The size of a Base64-encoded file is about 37% percent higher.

  • Quoted Printable This algorithm is used in combination with MIME. Usually it is used for non-English text. The main idea is that all characters that are not ASCII characters are escaped. Normally the size of an encoded file is 3% higher than the size of a file that is not encoded.

  • BinHex In Macenvironments BinHex is widespread. The encoded data is compressed, so the encoded file can even be smaller than the original file.

  • HTML With the arrival of modern Web technologies, HTML e-mail messages have become more and more popular. In combination with MIME, this is a simple and comfortable way. In addition, it is a standard format that can be read by every platform.

  • Binary Binary data is transmitted directly.

Additional methods are BTOA, BOO, or ROT-13.

Now that you have seen which algorithms are used for coding e-mail messages, it is time to see which protocols are involved when working with e-mail:

  • SMTP This protocol is used for the communication between various mail servers. The definition of the protocol can be found in RFC 821.

  • POP3 In contrast to SMTP, the POP3 protocol is used for retrieving messages from the server.

  • IMAP IMAP is an additional protocol for retrieving messages from the server. In contrast to POP3, the mail stays on the server.

All three protocols are standard protocols and they are supported by every reasonable mail program.

21.1.2 Sending E-Mail Messages

The first thing you have to learn is how to send e-mail messages. In the case of PHP, you can send e-mail messages easily. Take a look at the following example:

 <html> <title>Mail ...</title> <body bgcolor="#EEEEEE"> <b>Mail ...</b><br><br> <form action="mail.php" method="post">         <table>         <tr>                 <td>Mail To: </td>                         <td><input type="text" name="email" value=""></td>         </tr><tr>                 <td>Subject: </td>                         <td><input type="text" name="subject" value=""></td>         </tr><tr>                 <td>Content: </td>                         <td><textarea cols="50" rows="10" name="content">                                 </textarea></td>         </tr>         </table>         <br>         <td><input type="submit" name="submit" value="Send Mail"></td> </form> </body> </html> 

A form is displayed that can be used to send e-mail messages. Just enter the e-mail address of the person you want to send an e-mail to. In addition, you can insert the subject and the content of the e-mail. As soon as the button is clicked, the mail is sent to the recipient. In Figure 21.1 you can see what the form looks like.

Figure 21.1. A simple mailing tool.

graphics/21fig01.jpg

As you can see in the HTML document, clicking the button will start a script named mail.php. This program displays some HTML code and sends a message to the desired user:

 <html> <title>Mail ...</title> <body bgcolor="#EEEEEE"> <b>Mail ...</b><br><br> <?php         if      (mail("$email", "$subject", "$content"))         {                 echo "Mail has been sent successfully.";         }         else         {                 echo "An error has occurred.";         } ?> 

If the mail cannot be sent, an error message is displayed. In the case of multiple recipients, the addresses must be separated by a comma.

21.1.3 Working with IMAP and POP3

IMAP and POP3 are the two most important protocols for accessing the data stored on a mail server. In contrast to POP3, IMAP servers store the messages on the server and the data is retrieved whenever a message is requested. Because the data is not stored on the user's machine, the owner of the mailbox is far more flexible because he can change offices whenever he or she wants to. The disadvantage of IMAP is that it can take longer to retrieve e-mail because the data has to be transmitted to the client every time the mailbox is opened. In the case of bad or slow lines, this can be a burden. In this section we will focus on IMAP because this is the better protocol for implementing Web mail systems.

21.1.3.1 Retrieving Data

In the first example in this section, you will see how to retrieve basic information about a mailbox from the mail server. Therefore we have created the e-mail address phpbook@cybertec.at on a local machine (this is not the official Cybertec server). The system is running Sendmail in combination with an IMAP daemon. One message has been sent to phpbook@cybertec.at. Let's take a look at a short PHP script retrieving information about the mailbox:

 <?php         echo '<b>Displaying information about phpbook@cybertec.at</b><br><br>';         $mbox = imap_open("{212.186.25.84}INBOX","phpbook", "test123")                 or die("cannot connect to IMAP server: ".imap_last_error());         $testconn = imap_mailboxmsginfo($mbox);         if      ($testconn)         {                 echo "Date: ".$testconn->Date."<br>\n" ;                 echo "Deleted: ".$testconn->Deleted."<br>\n" ;                 echo "Driver: ".$testconn->Driver."<br>\n" ;                 echo "Mailbox: ".$testconn->Mailbox."<br>\n" ;                 echo "Messages: ".$testconn->Nmsgs."<br>\n" ;                 echo "Recent: ".$testconn->Recent."<br>\n" ;                 echo "Size: ".$testconn->Size."<br>\n" ;                 echo "Unread: ".$testconn->Unread."<br>\n" ;         }         else         {                 print "An error has occurred: ".imap_last_error(). "<br>\n";         }         imap_close($mbox); ?> 

At the beginning of the script, a header is displayed and a connection to the mail server is opened. In this scenario the IP address of the mail server is 212.186.25.84. The user phpbook having the password test123 is used for authentication. If the connection has been established successfully, information about the mailbox is retrieved and the various components are displayed onscreen using simple echo commands.

In the next listing, you can see what comes out when the script is executed:

 Displaying information about phpbook@cybertec.at Date: Sat, 9 Feb 2002 15:30:10 +0100 (CET) Deleted: 0 Driver: imap Mailbox: {212.186.25.84:143/imap/user="phpbook"}INBOX Messages: 1 Recent: 0 Size: 1515 Unread: 1 

As you can see, a lot of information is retrieved. In this scenario an IMAP server is used. The size of the message is 1515 bytes. One message is in the INBOX.

In the next step you will see how to retrieve the content of a message. Two files will be used. The file called mailserver.php will contain a library for interacting with the IMAP server. The file fetchmail.php will call the IMAP library. Let's take a look at mailserver.php first:

 <?php # library for interacting with an IMAP server class mailserver {         var $server;         var $user;         var $passwd;         var $mbox;         function mailserver()         {                 $this->server = "212.186.25.84";                 $this->user = "phpbook";                 $this->passwd = "test123";                 $this->mbox = @imap_open("{".$this->server."}INBOX",                                  $this->user, $this->passwd)                         or die("cannot connect to IMAP server: ".                                 imap_last_error());                 return $mbox;         }         function summary()         {                 $headers=imap_headers($this->mbox);                 $number = count($headers);                 echo "<b>Number of messages on server: $number<br><br></b>\n";                 for     ($i = 1; $i <= $number; $i++)                 {                         $message['body'] = imap_body($this->mbox, $i);                         echo "body: ".$message['body']."<br>\n";                 }         } } ?> 

After defining some variables, the constructor has been implemented. It establishes a connection to the mail server and displays an error if no valid connection handle is returned. Let's take a look at the function called summary. It retrieves the headers from the mailbox and counts the number of headers returned. Now a loop is processed that goes through all headers. The body of these messages is retrieved and displayed onscreen.

Let's take a look at fetchmail.php, which is based on the library you have just seen:

 <?php         include("mailserver.php");         $mail = new mailserver();         $mail->summary();         imap_close($mail->mbox); ?> 

First the library is included and a new instance of the mail server object is generated. Now the summary is displayed and the connection to the mail server is closed.

As we have already mentioned, the mailbox of phpbook contains one message, which has been sent from hs@cybertec.at. Figure 21.2 shows what comes out when executing the script.

Figure 21.2. Watching chaos.

graphics/21fig02.jpg

As you can see, the content of the mail is quite confusing. It contains bit-encoded HTML code.

Sometimes it is necessary to take a closer look at the header of messages. This is important to find out where the message comes from and to which e-mail address you have to reply. Much more information can be found in the header. The next example shows a new version of the summary function you have seen before. It displays all important parts of the header in a useful way:

         function summary()         {                 $headers=imap_headers($this->mbox);                 $number = count($headers);                 echo "<b>Number of messages on server: $number<br></b>\n";                 for     ($i = 1; $i <= $number; $i++)                 {                         $h = imap_header($this->mbox, $i);                         echo "<br><b>Subject:</b> ".$h->subject;                         echo "<br><b>Reply to:</b> ".$h->reply_toaddress;                         echo "<br><b>Mail comes from:</b> ".$h->fromaddress;                         echo "<br><b>Cc:</b> ".$h->ccaddress;                         echo "<br><b>Bcc:</b> ".$h->bccaddress;                         echo "<br><b>Sender address:</b> ".$h->senderaddress;                         echo "<br><b>Return path:</b> ".$h->return_path;                         echo "<br><b>Second since UNIX starting time:</b> "                                 .$h->udate;                         echo "<br><b>Fetch from:</b> ".$h->fetchfrom;                         echo "<br><b>Fetch subject:</b> ".$h->fetchsubject;                 }         } 

As you can see, PHP offers a variety of functions for processing the header of an e-mail. The functions return a string that can be processed directly. Figure 21.3 shows how the result will look.

Figure 21.3. Processing the header.

graphics/21fig03.jpg

The line "Mail comes from" is not that useful because it contains the name of the person who has sent the e-mail. This is nice but it might not be what you are looking for. Let's take a look at the next version of summary:

         function summary()         {                 $headers=imap_headers($this->mbox);                 $number = count($headers);                 echo "<b>Number of messages on server: $number<br><br></b>\n";                 for     ($i = 1; $i <= $number; $i++)                 {                         $h = imap_header($this->mbox, $i);                         displayarray($h->to[0], "To:");                         displayarray($h->from[0], "From:");                         displayarray($h->cc[0], "Cc:");                         displayarray($h->bcc[0], "Bcc:");                         displayarray($h->reply_to[0], "Reply to:");                         displayarray($h->sender[0], "Sender:");                         displayarray($h->return_path[0], "Return path:");                 }         } 

Some of the methods you have seen in the previous version can be used to return arrays or objects as well. In the case of "from" this is useful because more details about the sender can be retrieved. In the listing you can see that a function called displayarray is used. This function does nothing but display the content of an array. It must be defined outside the object to work properly. Here is the code of the function:

 function displayarray($data, $text) {         echo "<b>$text</b><br>\n";         while (list($key, $val) = @each($data))         {                 echo "$key => $val<br>";         }         echo "<br>"; } 

The keys as well as the values belonging to the keys are displayed. When executing fetchmail.php, some more information is displayed:

 Number of messages on server: 1 To: mailbox => phpbook host => cybertec.at From: personal => Hans-Juergen Schoenig mailbox => hs host => cybertec.at Cc: Bcc: Reply to: personal => Hans-Juergen Schoenig mailbox => hs host => cybertec.at Sender: mailbox => hs host => bachata Return path: 

In the listing you can see that the name of the host is always cybertec.at. There is only one section where the name of the host is bachata instead of cybertec.at. The reason is that the mail has been sent from the internal network. The internal name of the mail server is bachata, so this name has been used instead of cybertec.at.

21.1.3.2 Attachments and Other Components of an E-mail

Up to now you have seen how to extract messages and information about these messages from the mail server. In this section you will take a closer look at how to process messages consisting of more than just one component.

You can send a second e-mail to your test mail server. In this example, I have sent an e-mail containing a picture to phpbook@cybertec.at. The goal of the next example is to find out how many messages are in the mailbox and how many parts the various messages consist of. In addition, information about these parts should be displayed.

Here is an additional version of summary that does exactly what we want it to do:

         function summary()         {                 $headers=imap_headers($this->mbox);                 $number = count($headers);                 echo "<b>Number of messages on server: $number<br><br></b>\n";                 for     ($i = 1; $i <= $number; $i++)                 {                         echo "<b>message number: $i</b><br>\n";                         $struct = imap_fetchstructure($this->mbox, $i);                         $data = $struct->parts;                         foreach ($data as $x)                         {                                 while (list($key, $val) = @each($x))                                 {                                         echo "$key => $val<br>";                                 }                                 echo "<br>";                         }                 }         } 

The imap_fetchstructure function returns an object containing the structure of the e-mail. $data contains an array of all components. This array is processed and the various parts and fields of the array are displayed.

With the help of this simple function, it is possible to retrieve a lot of information about an e-mail or a set of e-mail messages. Let's see which kind of data the script displays:

 Number of messages on server: 2 message number: 1 ifsubtype => 1 subtype => PLAIN ifdescription => 0 ifid => 0 lines => 12 bytes => 218 ifdisposition => 0 ifdparameters => 0 ifparameters => 1 parameters => Array ifsubtype => 1 subtype => HTML ifdescription => 0 ifid => 0 lines => 11 bytes => 388 ifdisposition => 0 ifdparameters => 0 ifparameters => 1 parameters => Array message number: 2 ifsubtype => 1 subtype => PLAIN ifdescription => 0 ifid => 0 lines => 4 bytes => 52 ifdisposition => 0 ifdparameters => 0 ifparameters => 1 parameters => Array type => 5 encoding => 3 ifsubtype => 1 subtype => JPEG ifdescription => 0 ifid => 0 bytes => 201382 ifdisposition => 1 disposition => INLINE ifdparameters => 1 dparameters => Array ifparameters => 1 parameters => Array 

As we promised, two messages are on the server. The first message consists of two components. The first component is PLAIN, which means that it is a text component. The second component consists of HTML code. Information such as the length or the number of lines a message consists of can be found in the result, and this information can easily be extracted and used by your application. When you take a look at the second message, you will find that the second part of the second message has the subtype called JPEG. In addition, the encoding is said to be 3. The message type is 5. This tells us that this part of the message is an attachment.

The next function shows a way of downloading attachments. Again, we have tried to make the function as simple and as easy to understand as possible:

 function summary() {         $headers=imap_headers($this->mbox);         $number = count($headers);         echo "<b>Number of messages on server: $number<br><br></b>\n";         for     ($i = 1; $i <= $number; $i++)         {                 echo "<b>message number: $i</b><br>\n";                 $struct = imap_fetchstructure($this->mbox, $i);                 $pnumber = 0;                 foreach ($struct->parts as $part)                 {                         $pnumber++;                         if ($part->disposition == "INLINE")                         {                                 echo "size: ".$part->bytes."<br>\n";                                 $fname = $part->dparameters[0]->value;                                 print "filename: $filename<br>\n";                                 $body = imap_fetchbody($this->mbox,                                         $i, $pnumber);                                 $file = imap_base64($body);                                 $fh = fopen("/tmp/".$fname, "w");                                 fputs($fh, $file);                                 fclose($fh);                         }                         elseif ($part->disposition == "ATTACHMENT")                         {                                 # do further work ...                         }                 }         } } 

You should already be familiar with the first few lines of the function. The most important part of the code starts after generating $struct. All components of the structure are processed one after the other. $pnumber is used to count the current part of the message being processed. This is important because this information will be needed to retrieve the correct body of the part. If $part->disposition contains INLINE, an attachment has been found. Nowadays most attachments are sent inline. This is a comfortable way of encoding e-mail and it works well. If $part->disposition was ATTACHMENT, an attachment would have been found as well. Let's go on with INLINE messages. After computing the size of the attachment, the original filename is retrieved. This is important because you will need this filename to write the file to disk. In the next step the body of the message is retrieved. It is important to retrieve the correct body because otherwise the wrong piece of data will be treated as attachment. After the data is read, the string is decoded. Because an INLINE attachment is Base64-encoded, imap_base64 can be used to regenerate the original piece of data. After retrieving and decoding, the data is written to disk. This is done with the help of fopen, fputs, and fclose.

After the script has been executed, a few lines are displayed onscreen:

 Number of messages on server: 2 message number: 1 message number: 2 size: 201382 filename: nura.jpg 

More important than these lines is the fact that the file has been written to disk. To check that, you can use ls:

 [root@duron mail]# ls -l /tmp/nura.jpg -rw-r--r--    1 apache   apache     146953 Feb 14 18:28 /tmp/nura.jpg 

The most interesting thing is that the size of the file on disk is around 140KB. The size of the attachment is much larger (around 200KB). As we promised in the introduction to this section about Web mail systems, the encoded file is around 42% bigger than the original file.

The last thing we have to check is whether the file can be used correctly. Writing data to disk is simply not enough you have to check whether the image can be displayed correctly. Just take a look at Figure 21.4, and if you can see a wonderful woman, everything has been done correctly.

Figure 21.4. The image is correct.

graphics/21fig04.jpg

21.1.3.3 Retrieving Status Information

In this section you will see how to retrieve status information from an IMAP server. PHP offers a command called imap_status. It asks the server for some basic information. Let's take a look at a simple example:

 <?php         $server = "212.186.25.84";         $user = "phpbook";         $passwd = "test123";         $mbox = @imap_open("{".$server."}INBOX", $user, $passwd)                 or die("cannot connect to IMAP server: ".                         imap_last_error());         $status = imap_status ($mbox, "{212.186.25.84}INBOX", SA_ALL);         if      ($status)         {                 echo "<table>\n";                 echo "<tr><td>Messages:</td><td>".                         $status->messages."</td><tr>\n";                 echo "<tr><td>Recent:</td><td>".                         $status->recent."</td><tr>\n";                 echo "<tr><td>Unseen:</td><td>".                         $status->unseen."</td><tr>\n";                 echo "<tr><td>UIDnext:</td><td>".                         $status->uidnext."</td><tr>\n";                 echo "<tr><td>UIDvalidity:</td><td>".                         $status->uidvalidity."</td><tr>\n";         }         else         {                 echo "error: ".imap_lasterror() . "\n";         } ?> 

After the information has been fetched from the server, it is displayed onscreen using a table. Just access the various components of the object returned and display them onscreen. Figure 21.5 shows what comes out when you execute the script.

Figure 21.5. Status information.

graphics/21fig05.jpg

21.1.4 E-Mail Summary

PHP provides a rich set of functions for working with e-mail messages. Whether you want to work with News, POP, or IMAP servers, PHP offers the right functions for you. Especially when working with IMAP, you can build applications easily.

Messages can consist of various parts that can contain attachments. Even files that are attached to an e-mail can be processed with the help of PHP.



PHP and PostgreSQL. Advanced Web Programming2002
PHP and PostgreSQL. Advanced Web Programming2002
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 201

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net