Reading message information

array imap_headers ( resource imap_stream)

object imap_header ( resource imap_stream, int msg_number [, int from_length [, int subject_length [, string default_host]]])

As you should have come to expect by now, there is more than one way to solve most problems in PHP, and in the case of reading messages you have to ways to list the messages: imap_headers() and imap_header(). The difference between them is that imap_headers() downloads all the information about every email in the mail box and parses it into a pretty format, whereas imap_header() returns detailed information on just one email.

As imap_headers() is easier to use, we will start there. To use the function, pass in the return value from imap_open() as its only parameter, and it will return an array of the messages in the mail box. Each message is formatted like this:

Flags Number) Date Sender Subject (Size)

For example:

A 454)22-Jun-2004 Your Order (5284 chars)

From that you can see:

  • The message was replied to ("A" means "Answered")

  • The message is #454 in the mailbox

  • It was received on the 22nd March 2004

  • It was from

  • The subject was "Your Order"

  • The message and its attachments were 5284 characters in length

If you have many messages in your inbox, calling imap_headers() may take some time to execute as it has a lot of information to download. This is lessened by the fact that once you have called it the first time, subsequent calls are a great deal faster. Note that imap_headers() will return false if it fails, so you should consider adding a little error checking to your scripts to watch out for this value.

As well as A for Answered, there is a selection of other flags that may get returned. There are:

  • N - New

  • R - Recent

  • U - Unread

  • F - Flagged

  • D - Deleted

  • X - Draft

Here is a usage example for you to try out:

    $imap = imap_open("{}INBOX", "username", "password");
    $headers = imap_headers($imap);

    if (!$headers) {
        print "Failed to retrieve headers\n";
    } else {
        foreach($headers as $header) {
            print "$header\n";


That should output information on all the messages currently in the inbox. You have to admit, that was pretty easy! Although it is true that the format of the output leaves a lot to be desired, but if you want total control you need to go for imap_header(). Like imap_headers(), this takes an IMAP stream resource as its first parameter, but you also have to pass in the message number to read as its second parameter. The message numbers here are the literal sequence number as shown in imap_headers(), which there should not be any gaps in numbering.

The return value of imap_header() is an array with a massive amount of data - try this script:

    $imap = imap_open("{}INBOX", "username", "password");
    $header = imap_header($imap, 250);

The number 250 is just an example from one of the oldest messages still in my inbox, and you will need to change it if you have fewer than 250 messages in your inbox right now. Although I have taken care to edit out as much whitespace as possible, that script should output the following:

stdClass Object (
    [Date] => 23 Apr 2003 22:10:21 +0100
    [Subject] => Top Deals: GBP 15 Gift Certificate Offer and at Least 30% off Recommended Books
    [message_id] => <.AAA-39045660-13180,>
    [toaddress] =>
    [to] => Array ([0] => stdClass Object ([mailbox] => xxxx [host] => ) )
    [fromaddress] => "" <>
    [from] => Array ( [0] => stdClass Object ( [personal] => [mailbox] => foryou [host] => ) )
    [reply_toaddress] => "" <>
    [reply_to] => Array ( [0] => stdClass Object ( [personal] => [mailbox] => foryou [host] => ) )
    [senderaddress] => "" <>
    [sender] => Array ( [0] => stdClass Object ( [personal] => [mailbox] => foryou [host] => ) )
    [Recent] =>
    [Unseen] =>
    [Flagged] => F
    [Answered] =>
    [Deleted] =>
    [Draft] =>
    [Msgno] => 250
    [MailDate] => 23-Apr-2003 22:22:32 +0100
    [Size] => 36375
    [udate] => 1051132952

As you can see, there is a lot of information returned by imap_header(), much of which is the same information in different forms. For example, "fromaddress" and "from" contain the same data, except that "fromaddress" formats it nicely, whereas "from" contains the personal name (""), mail box name ("foryou") and the host ("") all separately. Also, "from" is actually an array capable of storing several from addresses. In this situation, "fromaddress" would contain each name separated by a comma.

Although you will not find many emails sent by more than one person, this system works the same in "toaddress" and "to" - each person who received the email is an element of the "to" array, and each person is split up into personal, mail box, and host.

The elements Recent, Unseen, Flagged, Answered, Deleted, and Draft correspond to the single-lettered flags we looked at already, and if any of them are set you will see the appropriate letter next to it rather than an empty space. In the example above, the email is flagged as the value F is in the Flagged element.

Finally, there are the size and udate elements. The size is the number of characters in the email, so you can divide it by 1024 to get a rough estimate of file size. The udate element is a Unix timestamp, and you can use it to convert to more readably time values. The two date values in there (Date and MailDate) are not really reliable, and should be avoided.


Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Reading message contents >>

Previous chapter: Opening a mailbox

Jump to:


Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.