It calls the retrieve_messagefunction to get the appropriate message from the mailbox: $message = retrieve_message$auth_user, $accountid, $messageid, $fullheaders; The retrieve_messagefu
Trang 1The line
$fullheaders = ($action==’show-headers’);
could have been more verbosely—and perhaps more clearly—written as
if($action==’show-headers’)
$fullheaders = true;
else
$fullheaders = false;
Next, we call the display_message()function Most of this function outputs plain HTML, so
we will not go through it here It calls the retrieve_message()function to get the appropriate
message from the mailbox:
$message = retrieve_message($auth_user, $accountid, $messageid, $fullheaders);
The retrieve_message()function is in the mail_fns.phplibrary You can see the code for it
in Listing 27.10
L ISTING 27.10 retrieve_message() Function from mail_fns.php—This Function Retrieves
One Specific Message from a Mailbox
function retrieve_message($auth_user, $accountid, $messageid, $fullheaders)
{
$message = array();
if(!($auth_user && $messageid && $accountid))
return false;
$imap = open_mailbox($auth_user, $accountid);
if(!$imap)
return false;
$header = imap_header($imap, $messageid);
if(!$header)
return false;
$message[‘body’] = imap_body($imap, $messageid);
if(!$message[‘body’])
$message[‘body’] = ‘[This message has no body]\n\n\n\n\n\n’;
if($fullheaders)
$message[‘fullheaders’] = imap_fetchheader($imap, $messageid);
else
$message[‘fullheaders’] = ‘’;
27
Trang 2$message[‘subject’] = $header->subject;
$message[‘fromaddress’] = $header->fromaddress;
$message[‘toaddress’] = $header->toaddress;
$message[‘ccaddress’] = $header->ccaddress;
$message[‘date’] = $header->date;
// note we can get more detailed information by using from and to // rather than fromaddress and toaddress, but these are easier imap_close($imap);
return $message;
}
Again we have used open_mailbox()to open the user’s mailbox
This time, however, we are after a specific message Using this function library, we download the message headers and message body separately
The three IMAP functions we use here are imap_header(),imap_fetchheader(), and
imap_body() Note that the two header functions are distinct from imap_headers(), the one
we used previously They are somewhat confusingly named In summary,
• imap_headers()—Returns a summary of the headers for all the messages in a mailbox
It returns them as an array with one element per message
• imap_header()—Returns the headers for one specific message in the form of an object
• imap_fetchheader()—Returns the headers for one specific message in the form of a string
In this case we use imap_header()to fill out specific header fields and imap_fetchheader()
to show the user the full headers if requested (We’ll come back to this.)
We use imap_header()and imap_body()to build an array containing all the elements of a message that we are interested in
We call imap_header()as follows:
$header = imap_header($imap, $messageid);
We can then extract each of the fields we require from the object:
$message[‘subject’] = $header->subject;
We call imap_body()to add the message body to our array as follows:
$message[‘body’] = imap_body($imap, $messageid);
L ISTING 27.10 Continued
Trang 3Finally we close the mailbox with imap_close()and return the array we have built The
display_message()function can then display the message’s fields in the form you can see in
Figure 27.6
Viewing Message Headers
As you can see in Figure 27.6, there is a Show Headers button This activates the show-headers
option, which adds the full message headers to the message display If the user clicks this
but-ton, he will see output similar to that shown in Figure 27.7
27
F IGURE 27.7
As you probably noticed, the event handling for view-messagecovers show-headers(and its
counterpart hide-headers) too If this option is selected, we do the same things as before But
in retrieve_message(), we also grab the full text of the headers, as follows:
if($fullheaders)
$message[‘fullheaders’] = imap_fetchheader($imap, $messageid);
We can then display these headers for the user
Trang 4Deleting Mail
If a user clicks the Delete button on a particular email, he will activate the “delete”action This will execute the following code from index.php:
case ‘delete’ : {
delete_message($auth_user, $selected_account, $messageid);
//note deliberately no ‘break’ - we will continue to the next case }
case ‘select-account’ : case ‘view-mailbox’ : {
// if mailbox just chosen, or view mailbox chosen, show mailbox display_list($auth_user, $selected_account);
break;
}
As you can see, the message is deleted using the delete_message()function, and then the resulting mailbox is displayed as discussed previously
The code for the delete_message()function is shown in Listing 27.11
L ISTING 27.11 delete_message() Function from mail_fns.php—This Function Deletes One Specific Message from a Mailbox
function delete_message($auth_user, $accountid, $message_id) {
// delete a single message from the server
$imap = open_mailbox($auth_user, $accountid);
if($imap) {
imap_delete($imap, $message_id);
imap_expunge($imap);
imap_close($imap);
return true;
} return false;
}
As you can see, this function uses a number of the IMAP functions The new ones are
imap_delete()and imap_expunge() Note that imap_delete()only marks messages for dele-tion You can mark as many messages as you like The call to imap_expunge()actually deletes the messages
Trang 5Sending Mail
Finally we come to sending mail There are a few ways to do this from this script: The user
can send a new message, reply to, or forward mail Let’s see how these work
Sending a New Message
The user can choose this option by clicking the New Message button This activates the
“new-message”action, which executes the following code in index.php:
case ‘new-message’ :
{
display_new_message_form($auth_user, $to, $cc, $subject, $body);
break;
}
The new message form is just a form for sending mail You can see what it looks like in Figure
27.8 This figure actually shows mail forwarding rather than new mail, but the form is the
same We’ll look at forwarding and replies next
27
F IGURE 27.8
Using mail forwarding, we can report the spammer.
Trang 6Clicking the Send Message button invokes the “send-message”action, which executes the fol-lowing code:
case ‘send-message’ : {
if(send_message($to, $cc, $subject, $message)) echo “<p>Message sent.<br><br><br><br><br><br>”;
else echo “<p>Could not send message.<br><br><br><br><br><br>”;
break;
}
This code calls the send_message()function, which actually sends the mail This function is shown in Listing 27.12
L ISTING 27.12 send_message() Function from mail_fns.php—This Function Sends the Message that the User Has Typed In
function send_message($to, $cc, $subject, $message) {
//send one email via PHP global $auth_user;
if (!db_connect()) {
return false;
}
$query = “select address from users where username=’$auth_user’”;
$result = mysql_query($query);
if (!$result) {
return false;
} else if (mysql_num_rows($result)==0) {
return false;
} else {
$other = “From: “.mysql_result($result, 0, “address”).”\r\ncc: $cc”;
if (mail($to, $subject, $message, $other)) return true;
else { return false;
Trang 7} }
}
As you can see, this function uses mail()to send the email First, however, it loads the user’s
email address out of the database to use in the From field of the email
Replying To or Forwarding Mail
The Reply, Reply All, and Forward functions all send mail in the same way that New Message
does The difference in how they work is that they fill in parts of the new message form before
showing it to the user Look back at Figure 27.8 The message we are forwarding has been
indented with the >symbol, and the Subject line prefaced with To Similarly, the Reply and
Reply All options will fill in the recipients, subject line, and indented message
The code to do this is activated in the body section of index.php, as follows:
case ‘reply-all’ :
{
//set cc as old cc line
if(!$imap)
$imap = open_mailbox($auth_user, $selected_account);
if($imap)
{
$header = imap_header($imap, $messageid);
if($header->reply_toaddress)
$to = $header->reply_toaddress;
else
$to = $header->fromaddress;
$cc = $header->ccaddress;
$subject = ‘Re: ‘.$header->subject;
$body = add_quoting(stripslashes(imap_body($imap, $messageid)));
imap_close($imap);
display_new_message_form($auth_user, $to, $cc, $subject, $body);
}
break;
}
case ‘reply’ :
{
//set to address as reply-to or from of the current message
if(!$imap)
$imap = open_mailbox($auth_user, $selected_account);
if($imap)
{
27
L ISTING 27.12 Continued
Trang 8$header = imap_header($imap, $messageid);
if($header->reply_toaddress)
$to = $header->reply_toaddress;
else
$to = $header->fromaddress;
$subject = ‘Re: ‘.$header->subject;
$body = add_quoting(stripslashes(imap_body($imap, $messageid)));
imap_close($imap);
display_new_message_form($auth_user, $to, $cc, $subject, $body);
} break; //note deliberately no ‘break’
} case ‘forward’ : {
//set message as quoted body of current message if(!$imap)
$imap = open_mailbox($auth_user, $selected_account);
if($imap) {
$header = imap_header($imap, $messageid);
$body = add_quoting(stripslashes(imap_body($imap, $messageid)));
$subject = ‘Fwd: ‘.$header->subject;
imap_close($imap);
display_new_message_form($auth_user, $to, $cc, $subject, $body);
} break;
}
You can see that each of these options sets up the appropriate headers, applies formatting as necessary, and calls the display_new_message_form()function to set up the form
That’s the full set of functionality for our Web mail reader
Extending the Project
There are many extensions or improvements you could make to this project You can look to the mail reader you normally use for inspiration, but some useful additions are the following:
• Add the ability for users to register with this site (You could reuse some of the code from Chapter 24, “Building User Authentication and Personalization,” for this purpose.)
• Many users have more than one email address; perhaps a personal address and a work address By moving their stored email address from the users table to the accounts table,
Trang 9you could allow them to use many addresses You would need to change a limited amount of other code too The send mail form would need a drop-down box to select from which address to use
• Add the ability to send, receive, and view mail with attachments If users are to be able
to send attachments, you will need to build in file upload capabilities as discussed in Chapter 16, “Interacting with the File System and the Server.” Sending mail with attach-ments is covered in Chapter 28, “Building a Mailing List Manager.”
• Add address book capabilities
• Add network news reading abilities Reading from an NNTP server using the IMAP functions is almost identical to reading from a mailbox You just need to specify a differ-ent port number and protocol in the imap_open()call Instead of naming a mailbox like INBOX, you name a newsgroup to read from instead You could combine this with the thread-building capabilities from the project in Chapter 29, “Building Web Forums,” to build a threaded Web-based newsreader
Next
In the next chapter, we’ll build another email-related project—an application to support sending
newsletters on multiple topics to people who subscribe through our site
27