Key Takeaways
- The PHP IMAP library allows web applications to incorporate features of an email client, including connecting to mail servers, reading messages, deleting messages, and downloading attachments.
- Connection to IMAP servers is established using the imap_open() function, with the mailbox path, username, and password as required parameters. For example, imap_open(“{localhost:993/imap/ssl/novalidate-cert}”, “username”, “password”).
- To list all available folders in an account, imap_list() function is used. For example, imap_list($imap, “{imap.gmail.com:993/imap/ssl}”, “*”).
- To read an email’s content, the getBody() function is used, which calls the get_part() function with the content type as TEXT/HTML. The structure of the email is read using the imap_fetchstructure() function, and the content is decoded according to the encoding type of the message.
func
– the type of functionality required (ex: read email, view inbox, delete message)folder
– the name of the mailbox folder to connect to (ex: inbox, sent, spam)uid
– the unique ID of the email targeted
$_GET
and a switch
statement can be used to invoke the appropriate actions.
<?php
$func = (!empty($_GET["func"])) ? $_GET["func"] : "view";
$folder = (!empty($_GET["folder"])) ? $_GET["folder"] : "INBOX";
$uid = (!empty($_GET["uid"])) ? $_GET["uid"] : 0;
// connect to IMAP
// ...
switch ($func) {
case "delete":
deleteMail($imap, $folder, $uid);
break;
case "read":
deleteMail($imap, $folder, $uid);
break;
case "view":
default:
viewMail($imap, $folder);
break;
}
Connecting to IMAP
To establish a connection to the IMAP server, we use theimap_connect()
function as shown here:
<?php
$imap = imap_open($mailboxPath, $username, $password);
The mailbox path, username, and password strings are required parameters to connect to the server. You can learn about the optional parameters in the manual.
The mailbox path is a string that identifies server and port information in braces followed by the name of the desired mail folder. Here are a few strings for the inbox folder for popular mail providers:
- Gmail
{imap.gmail.com:993/imap/ssl}INBOX
- Yahoo
{imap.mail.yahoo.com:993/imap/ssl}INBOX
- AOL
{imap.aol.com:993/imap/ssl}INBOX
<?php
$imap = imap_open("{localhost:993/imap/ssl/novalidate-cert}", "username", "password");
With an open connection to the mail server, now we can look at the functions used for the following activities:
- Displaying the list of mailbox folders in your email account
- Displaying the list of email messages in the folder
- Viewing the email’s content
Listing the Folders
Inbox, sent, trash, and spam folders are seen in pretty much every email account, and users can often create custom folders as well. In order to view messages in these folders, we need to change our connection string. For example, I used “INBOX” in the path string earlier. If I wanted to connect to the spam folder, I might want to use something like “Spam” instead. But even though it might be listed as Spam in your email account when viewed through a mail client, the real folder name might be different behind the scenes. We can list all of the available folders in an account usingimap_list()
.
<?php
$folders = imap_list($imap, "{imap.gmail.com:993/imap/ssl}", "*");
echo "<ul>";
foreach ($folders as $folder) {
$folder = str_replace("{imap.gmail.com:993/imap/ssl}", "", imap_utf7_decode($folder));
echo '<li><a href="mail.php?folder=' . $folder . '&func=view">' . $folder . '</a></li>';
}
echo "</ul>";
We have to pass the connection handle obtained with imap_open()
as the initial parameter to imap_list()
. We also need to pass a bare path sting (without the folder, e.g. “INBOX”). The star as the third parameter requests all of the available folders.
Listing Email Messages
Each folder has a list of available email messages, so let’s see how we can generate a listing of the messages in our inbox. We need to first get the number of messages available usingimap_num_msg()
. Then we can use the imap_header()
function to get the header information for each message.
Let’s say if we wanted to the last 20 emails:
<?php
$numMessages = imap_num_msg($imap);
for ($i = $numMessages; $i > ($numMessages - 20); $i--) {
$header = imap_header($imap, $i);
$fromInfo = $header->from[0];
$replyInfo = $header->reply_to[0];
$details = array(
"fromAddr" => (isset($fromInfo->mailbox) && isset($fromInfo->host))
? $fromInfo->mailbox . "@" . $fromInfo->host : "",
"fromName" => (isset($fromInfo->personal))
? $fromInfo->personal : "",
"replyAddr" => (isset($replyInfo->mailbox) && isset($replyInfo->host))
? $replyInfo->mailbox . "@" . $replyInfo->host : "",
"replyName" => (isset($replyTo->personal))
? $replyto->personal : "",
"subject" => (isset($header->subject))
? $header->subject : "",
"udate" => (isset($header->udate))
? $header->udate : ""
);
$uid = imap_uid($imap, $i);
echo "<ul>";
echo "<li><strong>From:</strong>" . $details["fromName"];
echo " " . $details["fromAddr"] . "</li>";
echo "<li><strong>Subject:</strong> " . $details["subject"] . "</li>";
echo '<li><a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=read">Read</a>';
echo " | ";
echo '<a href="mail.php?folder=' . $folder . '&uid=' . $uid . '&func=delete">Delete</a></li>';
echo "</ul>";
}
The $imap
connection should be open to the desired folder. We can then traverse through the last 20 emails using the number of messages received by imap_num_msg()
. The connection and email number are given to imap_header()
to retrieve the header information, which can then be parsed for the interesting details like the sender’s email address and name, subject, etc.
Note that the email number we get from using the total message count is not a unique ID for the message. If you have 100 emails in your inbox, then the last number will be 100, the previous will be 99, and so on. But its not unique. If you delete message number 100 and then receive a new message, it’s number will also will be 100.
We have to get the unique ID for an email in order to proceed with other actions. Each email does have an unique ID, called UID, which we can get by providing the email number to the imap_uid()
function. The UID is unique and will not change over time.
Viewing Message Contents
Reading email is not really as simple as the previous tasks, so I’m going to use the Receive Mail class developed by Mitul Koradia as a starting point to help make things easier. From the class I’ve extracted and adapted the following three functions for our example here:<?php
function getBody($uid, $imap) {
$body = get_part($imap, $uid, "TEXT/HTML");
// if HTML body is empty, try getting text body
if ($body == "") {
$body = get_part($imap, $uid, "TEXT/PLAIN");
}
return $body;
}
function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false) {
if (!$structure) {
$structure = imap_fetchstructure($imap, $uid, FT_UID);
}
if ($structure) {
if ($mimetype == get_mime_type($structure)) {
if (!$partNumber) {
$partNumber = 1;
}
$text = imap_fetchbody($imap, $uid, $partNumber, FT_UID);
switch ($structure->encoding) {
case 3: return imap_base64($text);
case 4: return imap_qprint($text);
default: return $text;
}
}
// multipart
if ($structure->type == 1) {
foreach ($structure->parts as $index => $subStruct) {
$prefix = "";
if ($partNumber) {
$prefix = $partNumber . ".";
}
$data = get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1));
if ($data) {
return $data;
}
}
}
}
return false;
}
function get_mime_type($structure) {
$primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
if ($structure->subtype) {
return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype;
}
return "TEXT/PLAIN";
}
The getBody()
function gets the email’s content by passing its UID and the IMAP connection. Inside the function, we call the get_part()
function with the content type as TEXT/HTML. Plain text emails are much easier to read. So we first try to find the HTML content inside the email.
Then we read the structure of the email using imap_fetchstructure()
function. This function would have taken the email number by default, but we changed the library function to use the UID instead by passing the FT_UID
constant.
Then we get the mime type of the email message using the get_mime_type()
function. There are eight mime types returned by this function as integers:
- 0 – TEXT
- 1 – MULTIPART
- 2 – MESSAGE
- 3 – APPLICATION
- 4 – AUDIO
- 5 – IMAGE
- 6 – VIDEO
- 7 – OTHER
imap_fetchBody()
when the correct part is found using the mime type.
Then, we use an appropriate decode function according to the encoding type of the message and return the content. A complete list of available encoding types is shown here:
- 0 – 7BIT
- 1 – 8BIT
- 2 – BINARY
- 3 – BASE64
- 4 – QUOTED-PRINTABLE
- 5 – OTHER
Summary
We started this series by reviewing the basics of connecting to IMAP servers, then moved on to listing message inside available folders, and finished with reading an email message’s content. In the next part I’ll discuss the functions which can be used to implement additional functionality expected from an email client, like deleting messages and handling attachments. Image via FotoliaFrequently Asked Questions (FAQs) about PHP’s IMAP Library
How can I connect to an IMAP server using PHP’s IMAP library?
To connect to an IMAP server using PHP’s IMAP library, you need to use the imap_open() function. This function takes three parameters: the mailbox, the username, and the password. The mailbox parameter is a string that specifies the location of the mailbox. The username and password parameters are self-explanatory. Here’s an example of how to use this function:$connection = imap_open("{imap.example.com:993/imap/ssl}INBOX", "username", "password");
In this example, we’re connecting to the INBOX of the user “username” on the server imap.example.com using a secure SSL connection.
How can I retrieve emails from an IMAP server using PHP’s IMAP library?
After establishing a connection to the IMAP server, you can retrieve emails using the imap_search() function. This function takes two parameters: the IMAP stream and the search criteria. The search criteria is a string that specifies the conditions that the emails must meet to be returned. Here’s an example:$emails = imap_search($connection, 'ALL');
In this example, we’re retrieving all emails from the server. The imap_search() function returns an array of email numbers, which you can then use with other functions to retrieve the emails’ content.
How can I read the content of an email using PHP’s IMAP library?
To read the content of an email, you can use the imap_fetchbody() function. This function takes three parameters: the IMAP stream, the email number, and the part number. The part number specifies which part of the email to retrieve. Here’s an example:$body = imap_fetchbody($connection, $email_number, 1);
In this example, we’re retrieving the first part of the email with the number $email_number. The imap_fetchbody() function returns the content of the specified part of the email.
How can I close a connection to an IMAP server using PHP’s IMAP library?
To close a connection to an IMAP server, you can use the imap_close() function. This function takes one parameter: the IMAP stream. Here’s an example:imap_close($connection);
In this example, we’re closing the connection to the IMAP server.
How can I handle errors when using PHP’s IMAP library?
PHP’s IMAP library provides several functions for error handling. The imap_errors() function returns an array of all the errors that have occurred, while the imap_last_error() function returns the last error that occurred. Here’s an example of how to use these functions:if (!imap_errors()) {
echo imap_last_error();
}
In this example, we’re checking if any errors have occurred and, if so, printing the last error.
How can I move an email to a different mailbox using PHP’s IMAP library?
To move an email to a different mailbox, you can use the imap_mail_move() function. This function takes three parameters: the IMAP stream, the email number, and the mailbox name. Here’s an example:imap_mail_move($connection, $email_number, 'INBOX.Trash');
In this example, we’re moving the email with the number $email_number to the Trash mailbox.
How can I delete an email using PHP’s IMAP library?
To delete an email, you can use the imap_delete() function. This function takes two parameters: the IMAP stream and the email number. Here’s an example:imap_delete($connection, $email_number);
In this example, we’re deleting the email with the number $email_number.
How can I mark an email as read using PHP’s IMAP library?
To mark an email as read, you can use the imap_setflag_full() function. This function takes three parameters: the IMAP stream, the email number, and the flag. The flag should be “\Seen” to mark the email as read. Here’s an example:imap_setflag_full($connection, $email_number, "\\Seen");
In this example, we’re marking the email with the number $email_number as read.
How can I retrieve the headers of an email using PHP’s IMAP library?
To retrieve the headers of an email, you can use the imap_headerinfo() function. This function takes two parameters: the IMAP stream and the email number. Here’s an example:$headers = imap_headerinfo($connection, $email_number);
In this example, we’re retrieving the headers of the email with the number $email_number. The imap_headerinfo() function returns an object with the headers’ information.
How can I retrieve the attachments of an email using PHP’s IMAP library?
Retrieving the attachments of an email is a bit more complex. You need to use the imap_fetchstructure() function to get the structure of the email, and then iterate over the parts of the email to find the attachments. Here’s an example:$structure = imap_fetchstructure($connection, $email_number);
$attachments = array();
if (isset($structure->parts) && count($structure->parts)) {
for ($i = 0; $i < count($structure->parts); $i++) {
if ($structure->parts[$i]->ifdparameters) {
$attachments[$i] = imap_fetchbody($connection, $email_number, $i+1);
}
}
}
In this example, we’re retrieving the attachments of the email with the number $email_number. The attachments are returned as an array of strings.
Rakhitha Nimesh is a software engineer and writer from Sri Lanka. He likes to develop applications and write on latest technologies. He is available for freelance writing and WordPress development. You can read his latest book on Building Impressive Presentations with Impress.js. He is a regular contributor to 1stWebDesigner, Tuts+ network and SitePoint network. Make sure to follow him on Google+.