PHP IMAP: Looping through messages to find a specific subject

Posted in PHP -

This post is part of a series about downloading email using the PHP IMAP functions. The ultimate goal of the series is to show how to export Google Analytics data by email, and then use PHP to connect to the mail server, find and download the appropriate message and then load the data into a database. This post looks at how to look for a specific email message using the PHP IMAP functions.

Looping through the messages

The most obvious solution is to loop through the messages and either do a string comparison on the sender and subject etc and then process the message if it matches the criteria.

Here's how you would do this:

$connection = imap_open($server, $login, $password);
$count = imap_num_msg($connection);
for($msgno = 1; $msgno <= $count; $msgno++) {

    $headers = imap_headerinfo($connection, $msgno);
    if( ... matching criteria here ... ) {
        call_a_function_to_do_something( ... parameters ... );

The first line connects to the mail server; the second works out how many messages there are in the mailbox. Then the script loops through each message, grabbing a copy of the headers and then doing something if some search criteria is matched.

For example, if you were looking for a message from "" with a subject "this is a test", you could make the if() statment like this:

if(strtolower($headers->subject) == 'this is a test'
    && strtolower($headers->fromaddress) == '') {

The string comparisons are done using strtolower() and a lower cased constant to ensure there are no case sensitivity issues.

You could also use regular expressions. The ultimate aim of these posts is to download the Google Analytics attachments and an example subject is something along these lines: "Analytics 20090202-20090304 (Top Content)"

To extract the domain, from date, to date and the customisable subject you can do this:

preg_match('/Analytics (.*) (\d{8})\-(\d{8}) \((.*)\)/i', 
    $headers->subject, $matches)

$matches is populated with the matches from the regular expression, and in the case of the example above would return this:

    [0] => Analytics 20090202-20090304 (Top Content)
    [1] =>
    [2] => 20090202
    [3] => 20090304
    [4] => Top Content

Using the imap_search function

imap_search is a powerful searching function which saves you from having to loop through the messages like in the above examples. Pass it the connection and then some criteria like so to match the above email:

$result = imap_search($connection,
    'SUBJECT "Analytics" FROM ""');

The way this works is the criteria are things like SUBJECT and FROM and you put the values to match in a double quoted string after the criteria name. It must be a double quoted string (not a single quoted one) otherwise it will not work. A full list of criteria can be found on the PHP imap_search manual page.

Matches are done in a case-insensitive fashion, and will match anywhere in the string. So in the above example 'SUBJECT ""', ''SUBJECT "Analytics"' etc would match the full subject "Analytics 20090202-20090304 (Top Content)". You may then need to do further validation on the subject etc before processing the message.

The function returns an array of message numbers which can then be looped through and the messages processed as in the following example:

foreach($result as $msgno) {
    $headers = imap_fetchheader($connection, $msgno);
    if( ... any optional additional matching criteria here ... ) {
        call_a_function_to_do_something( ... parameters ... );

Next posts in this series

Now that I've covered how to connect to a mailbox using PHP IMAP, extract attachments from a message and loop through looking for a specific message, I'll put it all together in the next post to show how to get an email attachment from Google Analytics with PHP. The following posts will then look at how to parse the data.

Read more about the series here, including a full list of posts in it.

Related posts: