COM372: Notes, Chapter 29

building a Web-based Email Service
pages 651-686

Syllabus | Grading | Reading Notes | Dr. Logan

Email Servers: There are two main email server technologies (more).

Both are supported through the php IMAP function library. URI uses both, and you may send on one and receive on the other, for example. We'll also use the Simple Mail Transfer Protocol (SMTP) and mail() to send mail. The PHP IMAP library is much more extensive than the functions covered in this chapter, which include

Project Overview: The project is diagrammed in fig. 29.1, page 654. After logging in, the user can

Program structure relies on an extended select:case within index.php, a long file (listing 29.2, page 657-662!!), augmented by a function library; this is acceptable for a small project, but not for a more complicated one, or one that is being written in pieces by a team. There are eight files in the application, listed in table 29.1 (p. 655).

Project Database: There is a small database with the project, to store information about users and accounts. (SQL listing 29.1, p. 656), contained in create_database.sql in common.... Populate.sql can be used to populate the database.

Program flow: Index.php is divided into four sections:

  1. Pre-headings: Do any logging in or out, start the session, and decide what to include in page headings, base on what was sent from the previous page (sent as a name:value pair for action=...).
  2. Headers: Send appropriate page headers and menus, depending on "action".
  3. Body: Send main content, depending on "action".
  4. Footers: Send page footer.

Logging in: This repeats the pattern from the last chapter. The page looks for form variables, including a value for "action," or user and password, checks these against a database and issues appropriate messages, sets a session variable for later page authentication, etc. The page also checks for administrative logins, adding extra navigation buttons for administrators, etc. This is discussed in detail on pages 663-666.

Managing Accounts

Setting up a new Account: New users will click on the new accounts button and return to index.php for the new account section of code, which produces the appropriate alterations in the headers and a form (fig. 29.4, page 666). Notice the use of stacked cases (p.667)

case 'store-settings' :
case 'account-setup' :
case 'delete-account' :
{
display_account_setup($SESSION['auth_user']);
break;
}

all of which call the same display_account_setup() (listing 29.3, page 667), which displays the blank form via the function display_account_form(). If the form is for an existing user, it will be filled in, with information retrieved as an array by get_accounts() (listing 29.4, page 668).

Creating a new account or modifying an old one: For users who fill out the form and click Save Changes, store_account_settings() (listing 29.5, pages 668-669) takes the form collection data and writes it into the accounts table of the database, either as a new record or an update of an existing record.

Deleting: Under each account listing is an option to delete, a link which sets page action; the case 'delete-account' calls (duh...) delete_account() (listing 29.6, page 670), etc.

Reading Mail

Selecting an account: Remember that users may set up more than one email account (home, office, CIA spy, etc.). If there is only one account (function number_of_accounts(), listing 29.7, page 671), it will be selected when the user logs in; otherwise get_account_list() will retrieve account names and produce a dropdown list (fig. 29.5) from within the do_html_header() function (snippet, page 672). The dropdown runs on javascript (see p. 672), triggered by an onchange event handler which assigns a new URL, with action and account number appended, using the javascript window.location method. Adding the account number to the URL affects the page preprocessing section by storing the email account in the session variable. This SESSION['selected_account'] is then checked before mail for that account is displayed later in the body of the script. (That is, SESSION now hold both the user and the particular user email account.)

Viewing mailbox contents: Clicking on "View Mailbox" sets up viewing of mail. Function display_list() (listing 29.8, pages 674-675) is the first place where the mail server is actually used, to open the mailbox and read the message headers. The mailbox is opened and the connection named by
$imap = open_mailbox($auth_user, $accountid);
(listing 29.9, page 675), which does the actual opening with imap_open(), with prototype int imap_open (string mailbox, string username, string password [, int options]); mailbox is a string with format {hostname / protocol : port}boxname. Imap_open() returns an IMAP stream if the mailbox can be opened, or false if not. The stream is closed with imap_close(imap_stream); imap_headers() retrieves email headers, as in $headers = imap_headers($imap);. Note that there are two closely related functions (click for more), imap_header() ("Alias of imap_headerinfo()", which "Gets information about the given message number by reading its headers") and imap_headers() ("Returns headers for all messages in a mailbox").

Reading a mail message: The list of messages obviously provides links to the entire message. This in also handled in index.php by passing a message number corresponding to the index (starting with 1 for IMAP messages) from the headers retrieved (above). The message is displayed as in fig. 29.6 (page 677), via the display_message() function; the work of getting the messages is done within this function, through a call to retrieve_message() (listing 29.10, pages 678-679). The message is downloaded separately from the header, although both use the function open_mailbox(). Downloads use

Use imap_header() and imap_body() to build an array with all of the message elements that we are going to use. Call as $header=imap_header($imap, $messageid); and then extract each field, e.g., $message['subject'] = $header-%gt;subject; or $message['body'] = imap_body($imap, $messageid);

Close the mailbox with imap_close(). Display messages using display_message() (fig. 29.7, page 680).

Deleting mail: Deleting a message calls delete_message() (listing 29.11, page 681) to remove the message from the mailbox (via open_mailbox(), imap_delete() (marks messages to be deleted), imap_expunge() (deletes marked messages), and imap_close()), and then displays the list of what remains.

Sending mail

New messages: The New Message button links to the new-message action, which displays the mail in a form (fig. 29.8, p. 682). This is the same form used to forward messages. If you click on the send message button, you call send_message() (listing 29.12, page 683), which uses mail() to send the mail, including the user's email address in the "from" field first.

Replying to or forwarding a message: These are done the same as with a new message, except that parts of the form are filled in ahead of time, including recipients, subject line, and an indented message. The code is copied on pages 684-685.