Email Servers: There are two main email server technologies (more).
- Post Office Protocol version 3 (POP3) is simpler, used to download mail and to remove it from the mail server.
- Internet Message Access Protocol (IMAP) has some more advanced features, and is used when mail is kept on the remote server.
- imap_open() and imap_close()
- imap_headers()
- imap_header()
- imap_fetchheader()
- imap_body()
- imap_delete()
- imap_expunge()
Project Overview: The project is diagrammed in fig. 29.1, p. 660. After logging in, the user can
- Set up an account
- select an account
- view mailbox
- view messages
- Reply
- Reply All
- Forward
- Delete
- Show/hide Headers
- view messages
- New Mail
- Logout
Project Database: There is a small database with the project, to store information about users and accounts. (listing 29.1, p. 662), 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:
- 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=...).
- Headers: Send appropriate page headers and menus, depending on "action".
- Body: Send main content, depending on "action".
- 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 p. 669-72.
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, p. 672). Notice the use of stacked cases (p.673)
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, p. 673), 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, p. 674).
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, p. 675) 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, p. 676-7) which....
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, p. 678), 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 shown on p. 679). The dropdown runs on javascript (see p. 679), 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, p. 680-1) 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, p. 682), 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 (p. 684), 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, p. 685). The message is downloaded separately from the header, although both use the function open_mailbox(). Downloads use
- imap_headers()—summary of the headers for all messages in the mailbox, as an array, one per message
- imap_header()—returns an object that holds the headers for one specific message. (Notes, NOT imap_headerS()
- imap_fetchheader()—returns a string version of the header for one specific message.
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, p. 687).
Deleting mail: Deleting a message calls delete_message() (listing 29.11, p. 688) 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. 689). This is the same form used to forward messages. If you click on the send message button, you call send_message() (listing 29.12, p. 690), 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 copies on p. 691-92.