Thanks to PHP, we can check our email account remotely using PHP and its imap_xxx functions, which allow us to communicate with mail servers via IMAP, POP3 or NNTP protocols. In this article Mitchell shows us how to create a completely web-based email checking script which can also delete, send and reply to emails… all using only PHP’s IMAP functions.How many times have you been away from your home PC and wished that you could check your IMAP/POP3 mail account? If you’re anything like me then you’re always on the move and your laptop is your best friend.
Thanks to PHP, we can check our email account remotely using PHP and its imap_xxx functions, which allow us to communicate with mail servers via IMAP (Internet Message Access Protocol), POP3 (Post Office Protocol) and/or NNTP (Network News Transfer Protocol).
In this article we’re going to build a mail script that will accept an email account, password and optional IMAP port number. The script will then login to that mail account and display the users inbox in a similar fashion to the way Hotmail does: all using only PHP and HTML. From the inbox screen, we have the option to compose a new email, view our emails and even reply to them.
To test the source code and examples in this article you should be running either a Windows/Linux server with IIS/Apache and PHP 4+ installed. You should also have the IMAP libraries installed, which we will look at shortly.
Create Your Own Mail Script With PHP and IMAP - What is IMAP?
(Page 2 of 6 )
IMAP is a method of accessing email messages stored on a remote mail server. The reason IMAP is so popular is because it allows clients to connect to and interact with their mail server without the need to download their emails and files locally. In other words, IMAP allows us to treat a remote mail server as is if it was on our local machine, checking our accounts, manipulating emails, replying to emails, etc.
IMAP shouldn’t be confused with the POP3 protocol, however. If you’ve ever used Outlook or Eudora or any other client mail access program, then you’ll know that you can “check” your email, disconnect from the Internet and your mail will be stored on your local machine, saving you the hassle of being on the ‘net to read your email. This is POP’s biggest advantage: offline access to your email. POP downloads all new messages off the server onto your local PC and then deletes them from that server. IMAP on the other hand queries the server, leaving all emails intact unless you specifically tell it to delete them.
POP was designed for use with client side email applications such as Outlook, whereas IMAP was designed for people on the move, wanting to check their email but not necessarily retrieve it.
The key goals for IMAP are:
- Be fully compatible with Internet messaging standards, e.g. MIME.
- Allow message access and management from more than one computer.
- Allow access without reliance on less efficient file access protocols.
- Provide support for online, offline and disconnected access modes.
- Support for concurrent access to shared mailboxes.
- Client software needs no knowledge about the server’s file store format.
Let’s take the last point into configuration: “Client software needs no knowledge about the server’s file store format”. In my opinion this is one of IMAP’s best features. The client simply queries the mail server using IMAP specific commands and that server returns the data the client’s after.
It doesn’t matter how the server stores the actual email messages (whether it be in a flat file, a MySQL database, an MSSQL server database or any other format) as long as the server returns the data that the client requests, then the storage method and location are irrelevant.
Bringing PHP into the picture
If you’ve worked with PHP extensions then you’ll know that it supports IMAP through an extension library, which isn’t installed by default. Before we can play around with PHP and IMAP, we have to install the necessary IMAP libraries first.
Configuring PHP on Windows with IMAP support
It’s easy to configure your Windows server to work with IMAP. Firstly, grab the php_imap.dll file from your PHP download (it should be in the extensions directory). If you can’t find it then download the PHP zip package here.
Next, copy php_imap.dll to your PHP extension directory, which you can find in your php.ini file as the extension_dir variable. Lastly, open php.ini and look for the line starting “;extension=php_imap.dll”. Remove the semicolon from the front, save the file and restart your web server.
Configuring PHP on Linux with IMAP support
To enable IMAP support on your PHP installation you need to compile PHP with the –with-imap argument. You also need to download the IMAP library here. Once you’ve downloaded it, copy c-client/c-client.a to /usr/local/lib/libc-client.a. Also copy c-client/rfc822.h, mail.h and linkage.h to /usr/local/include or some other directory in your include path.
Testing for IMAP support
To make sure IMAP support is configured correctly, create a new file called phpinfo.php and save it into a directory that your web server can process. Add the following code to it and run it in your web browser:
<?php echo phpinfo(); ?>
Scroll down the page about half way and look for the IMAP section. You should see something like this:

Now that we’ve setup IMAP support, it’s time to take a look at the various IMAP functions that we will be using later in this article to create our email script.
Create Your Own Mail Script With PHP and IMAP - IMAP functions
(Page 3 of 6 )
The IMAP library has 61 functions. Luckily we only need to use a handful of these to create a fully functional email script. The functions we will be using in this article are shown and detailed below:
- imap_open: Opens an IMAP stream to a mailbox.
- imap_headers: Returns headers for all emails in a mailbox.
- imap_headerinfo: Reads the header of an email.
- imap_delete: Mark an email for deletion from current mailbox.
- imap_expunge: Delete all emails marked for deletion.
- imap_mail: Sends an email message to a recipient.
- imap_body: Reads the body of an email from a mailbox.
As mentioned earlier, we’re going to create a script that allows us to check our email account on the move using IMAP. Before we create the script however, let’s start with the basics. Create a new file called testimap.php and enter the following code into it:
<?php
$server = “mail.com”;
$user = “john”;
$pass = “mypass”;
$conn = @imap_open(”\{$server/imap}INBOX”, $user, $pass)
or die(”Connection to server failed”);
?>
Replace the $server variable with the host name of your mail server. Replace $user with your mailbox account name and also replace $pass with the password for your mailbox. To connect to our mail server we use the imap_open function, passing in our mailbox, user ID and password. The format of the mailbox parameter looks like this:
{host_name[:port number]/imap}INBOX
The port number part of the mailbox parameter is optional. If we refer back to the testimap.php file above, our mailbox parameter looks like this:
{mail.com/imap}MAILBOX
In our example we’ve left out the port number. We could’ve optionally specified the port number like this:
{mail.com:25/imap}INBOX
The imap_open function returns an IMAP stream on success and FALSE on failure. We use this returned IMAP stream with various other imap_xxx function calls to manipulate our mailbox, send emails, etc.
To retrieve a list of emails in our mailbox, we can use the following code:
$headers = @imap_headers($conn)
or die(”Couldn’t get emails”);
$numEmails = sizeof($headers);
echo “You have $numEmails in your mailbox”;
In the example above I’ve called the imap_headers function, passing in our IMAP stream as the only parameter. The imap_headers function returns an array of headers. Each of these headers contains the details of one email in our mailbox, and we can use the values of these headers to show who these emails have come from, their subjects, date received, etc. These headers do not however contain the body of each email message, and we must use the imap_body function to get them.
Now that we’ve got an array of headers representing each email in our mailbox, we can loop through them to display the details of each message with the imap_headerinfo function, like this:
for($i = 1; $i < $numEmails+1; $i++)
{
$mailHeader = @imap_headerinfo($conn, $i);
$from = $mailHeader->fromaddress;
$subject = strip_tags($mailHeader->subject);
$date = $mailHeader->date;
echo “Email from $from, subject $subject, date $date<br>”;
}
As you can see from the code above, we use the imap_headerinfo function to get the header details for each message. We extract the from address, subject and date for each message and use the echo command to output them to the browser.
Now that we’ve displayed each message in our mailbox, we can use the imap_close function to close the IMAP stream we created earlier with imap_open:
imap_close($conn);
On this page we’ve taken a look at the basic imap_xxx functions that are required to open an IMAP stream, retrieve headers and display the details of each email from these headers. On the next page we’re going to put everything we’ve learnt so far to good use and create the email script I’ve been mentioning.
Create Your Own Mail Script With PHP and IMAP - Creating our email script
(Page 4 of 6 )
There are a huge number of email applications on the market, however most of them expose the same core functionality:
- You can check your mailbox on any mail server.
- You can create and send emails.
- You can reply to emails.
- You can delete emails from your mailbox.
The script we’re about to discuss implements each of the bullet points shown above. We will run through the code step by step, describing various function calls where necessary.
Our script contains several functions and a switch statement. The switch statement works with the $what variable, which can be either a query string or form posted variable. Each time our script is called, a different function is executed, depending on the value of $what:
switch($what)
{
case “login”:
ProcessLogin();
break;
case “inbox”:
ShowInbox();
break;
case “delete”:
DeleteEmails();
break;
case “compose”:
ShowComposeForm();
break;
case “send”:
SendMessage($to, $subject, $message, $cc, $bcc);
break;
case “read”:
ShowEmail();
break;
case “reply”:
ShowComposeForm($to, $subject, $message);
break;
default:
ShowLoginForm();
}
As you can see, the default option calls the ShowLoginForm function, which allows us to enter our email address and password. The ShowLoginForm function simply displays a HTML form which includes a hidden form variable, $what, which is set to “login”.
The ProcessLogin function is called when $what is equal to “login”. It validates the email address from the login form using the ereg function and creates some session variables containing our mailbox, username, host and password:
$validEmail = ereg(”^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$”, $email);
$validPass = ($password == “” ? false: true);
$portString = (is_numeric($port) == true ? “:$port” : “”);
if(!$validEmail || !$validPass)
{
// Email or password are bad
die(”<h2>Invalid Login Credentials</h2>”);
}
else
{
// Email and password are fine, get the user and hosts
$arr = split(”@”, $email);
$user = $arr[0];
$host = $arr[1];
$mailbox = “\{$host$portString/imap}INBOX”;
// Set the login credentials as session variables
setcookie(”mailbox”, $mailbox);
setcookie(”user”, $user);
setcookie(”host”, $host);
setcookie(”password”, $password);
header(”Location: $PHP_SELF?what=inbox”);
}
As you can see, we use the split function to separate the users email address into the $user and $host variables. We also create the $mailbox variable from the host name and port number, which may or may not be specified in the login form. The user is then redirected to the same scripting using $PHP_SELF, passing “inbox” as the $what query string variable. This results in the ShowInbox function being called.
The ShowInbox function connects to our mail server using imap_open (which we saw in our first example) and retrieves the headers for each email message in our mailbox. These headers are then extracted into variables and a HTML table is created that lists the details of each email. Each email is also hyper linked to the script, setting the query variables $what to “read”, and $id to the ID of the email, which is the index of that particular email in the array returned from a call to imap_headers:
<td width=”50%”>
<a href=”<?php echo $PHP_SELF; ?>?what=read&id=<?php echo $i; ?>”>
<?php echo $subject; ?>
</a>
</td>
When $what is “read”, the ShowEmail function is called.
Create Your Own Mail Script With PHP and IMAP - The ShowEmail function and more
(Page 5 of 6 )
ShowEmail connects to our IMAP server using imap_open and retrieves both the header and body details of one specific email. As we saw earlier, imap_headerinfo returns the header details of an email as an array, like this:
$mailHeader = @imap_headerinfo($conn, $id);
…
$from = $mailHeader->fromaddress;
$subject = strip_tags($mailHeader->subject);
$date = $mailHeader->date;
The body of the email is then retrieved with a call to imap_body. Because our email script only displays plain text emails, we use strip_tags to remove all HTML formatting from the email:
$body = nl2br(strip_tags(imap_body($conn, $id)));
We then output all of these details to a form, including a button that lets us reply to this specific email:
<form name=”frmLogin” action=”<?php echo $PHP_SELF; ?>” method=”post”>
<input type=”hidden” name=”what” value=”reply”>
<input type=”hidden” name=”to” value=”<?php echo $from; ?>”>
<input type=”hidden” name=”subject” value=”Re: <?php echo $subject; ?>”>
<input type=”hidden” name=”message” value=”<?php echo str_replace(”<br />”, “”, str_replace(”\r\n”, “\r\n>>”, $body)) ?>”>
<h2><?php echo $subject; ?></h2>
<hr noshade size=”1″ color=”#20158F”>
<b>From:</b> <?php echo str_replace(”<”, “<”, $from); ?><br>
<b>Date:</b> <?php echo $date; ?><br>
<hr noshade size=”1″ color=”#20158F”>
<?php echo $body; ?>
<hr noshade size=”1″ color=”#20158F”>
<input type=”submit” name=”submit” value=”Reply >>”>
</form>
As you can see, this form passes the value “reply” for the hidden form variable “what”. The to, subject and message fields are also passed as hidden form variables, which in turn calls the ShowComposeForm function, which displays a HTML form in exactly the same was as the ShowEmail function.
Although this might sound a little confusing, the ShowComposeForm function is also used to compose a new email. The parameters passed to the function are the values for each text box in the form: if we don’t pass any parameters then we’re creating a new form. If we do, then we’re replying to a message. Here’s the function signature of ShowComposeForm:
function ShowComposeForm($to = “”, $subject = “”, $message = “”)
The ShowComposeForm function includes a hidden form variable, what, which is set to “send”, triggering a call to the SendMessage function when the form is submitted.
The function signature of SendMessage looks like this:
SendMessage($to, $subject, $message, $cc, $bcc);
SendMessage uses the imap_open function to connect to our mail server. If the connection was successful, it then uses imap_mail to send an email message to the intended recipient, like this:
imap_mail($to, $subject, $message, “From: $user@$host”, $cc, $bcc);
One last function that I will mention is our DeleteEmails function. This function calls imap_delete as well as imap_explunge to remove email messages from our mailbox based on their ID. The ID’s for the DeleteEmails function are passed as an array from the form generated by the ShowInbox function:
for($i = 1; $i < $numEmails+1; $i++)
…
<td width=”5%”">
<input type=”checkbox” name=”emails[]” value=”<?php echo $i; ?>”>
</td>
The imap_delete function accepts two parameters: an IMAP stream object and the ID of the email to delete:
for($i = 0; $i < sizeof($emails); $i++)
{
@imap_delete($conn, (int)$emails[$i]);
}
Once we’ve called imap_delete for each email, we must call the imap_expuge function to actually remove the messages from the server:
@imap_expunge($conn);