Check your email with PHP and IMAP

Check your email with PHP and IMAP

At some point I wanted to check if there was any unread messages in a couple mailboxes from inside an website administration panel, so I ended up with a simple script like the one described here. What we want is to fetch the all the messages in the INBOX of each e-mail account for the past week, using the IMAP functions of PHP. Also, we are going to mark the unread messages with a different style.

WARNING: This is only an example on how to use some PHP IMAP functions.
It is NOT recommended to store your passwords in an unencoded php file on a shared server.

Create an array of your mailboxes

<?
// Configure your imap mailboxes
$mailboxes = array(
    array(
        'label'     => 'Gmail',
        'mailbox'   => '{imap.gmail.com:993/imap/ssl}INBOX',
        'username'  => 'yourusername@gmail.com',
        'password'  => 'yourpassword'
    ),
    array(
        'label'     => 'My Cpanel website',
        'mailbox'   => '{mail.yourdomain.com:143/notls}INBOX',
        'username'  => 'info+yourdomain.com',
        'password'  => 'yourpassword'
    ),
    array(
        'label'     => 'Another mail account',
        'mailbox'   => '{mail.yourdomain.com:143/notls}INBOX',
        'username'  => 'info@yourdomain.com',
        'password'  => 'yourpassword'
    )
);
?>

Fetch this week's messages from each mailbox

<div id="mailboxes">
<?
foreach ($mailboxes as $current_mailbox) {
?>
    <div class="mailbox">
    <h2><?=$current_mailbox['label']?></h2>
    <?      
    // Open an IMAP stream to our mailbox
    $stream = @imap_open($current_mailbox['mailbox'], $current_mailbox['username'], $current_mailbox['password']);
    
    if (!$stream) { 
    ?>
        <p>Could not connect to: <?=$current_mailbox['label']?>. Error: <?=imap_last_error()?></p>
    <?
    } else {
        // Get our messages from the last week
        $emails = imap_search($stream, 'SINCE '. date('d-M-Y',strtotime("-1 week")));

        // Instead of searching for this week's messages, you could search 
        // for all the messages in your inbox using: $emails = imap_search($stream, 'ALL');
        
        if (!count($emails)){
        ?>
            <p>No e-mails found.</p>
        <?
        } else {

            // If we've got some email IDs, sort them from new to old and show them
            rsort($emails);
            
            foreach($emails as $email_id){
            
                // Fetch the email's overview and show subject, from and date. 
                $overview = imap_fetch_overview($stream,$email_id,0);                       
                ?>
                <div class="email_item clearfix <?=$overview[0]->seen?'read':'unread'?>"> <!-- add a different class for seperating read and unread e-mails -->
                    <span class="subject"><?=$overview[0]->subject?></span>
                    <span class="from"><?=$overview[0]->from?></span>
                    <span class="date"><?=$overview[0]->date?></span>
                </div>
                <?
            } 
        } 

        // Close our imap stream.
        imap_close($stream); 
    }
    ?>
    </div>
<?
} // end foreach 
?>
</div>

Decoding MIME extensions

Add the following function in order to decode headers that may contain non ASCII text. For example "=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=" should print "Keld Jørn Simonsen"

<?
// A function to decode MIME message header extensions and get the text
function decode_imap_text($str){
    $result = '';
    $decode_header = imap_mime_header_decode($str);
    foreach ($decode_header AS $obj) {
        $result .= htmlspecialchars(rtrim($obj->text, "\t"));
    }
    return $result;
}
?>

and change the output part to:

<div class="email_item clearfix <?=$overview[0]->seen?'read':'unread'?>"> 
    <span class="subject"><?=decode_imap_text($overview[0]->subject)?></span>
    <span class="from"><?=decode_imap_text($overview[0]->from)?></span>
    <span class="date"><?=$overview[0]->date?></span>
</div>

That's all - regarding PHP. Try putting it all together, adding some CSS and some icons for read/unread messages, and you will come out with something like this demo page, or download all the files of the demo.

What else?

You could go a step further and get the message body with imap_fetchbody(), or add the functionality to mark a message as "read" or "unread". This could be as simple as this:

imap_setflag_full($stream,$email_id, "\\Seen"); // Set the flag "Seen" 
imap_clearflag_full($stream,$email_id,'\\Unseen'); // Clear the flag "Unseen"

Comments

Motyar  •  January 17, 2012 05:00

Very useful and well described.
thank you for sharing.
Your theme of site is just COOL.

Tony-o  •  October 28, 2012 07:04

This script def does not work, you should check and update your work.

Zain  •  October 31, 2012 14:13

This script is not working, Check it again

Mangalasamy  •  November 20, 2012 17:52

nice script,working well

saeed  •  January 2, 2013 19:28

i just waste my time to read this blog. Author just copy and paste code from other side

Moullablad  •  January 18, 2013 12:12

thank you for your good tutorial :)

nimahkh  •  January 25, 2013 16:54

Admin please answer.. this script don't work for me on local .
when is remove @ from imap_open function , i see fatall error .. and when i write it , nothing show me. whats the problem?

zameer  •  February 7, 2013 11:47

first time it works...but second time it gives error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, webmaster@vss-mobi.co.in and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

Lucas de Carvalho  •  March 6, 2013 06:05

Really good!

So, can you show how/where I can use "imap_fetchbody()" to show the body of the message as well or simply say where I must put this to works?

Thank you in advance.

Vikas  •  March 13, 2013 09:26

Wow.... Very nice script. I was searching for this kind of script since a long time. Its a big sigh of relief...
Thanks a lot.

Can some body tell me the port of MSN for fetching emails, like google has 993 in this script

American Mail & Parcel  •  April 15, 2013 16:41

Very nice script, thanks

طراحی سایت  •  April 23, 2013 15:00

That was very useful article. I'll test it soon !

J  •  May 1, 2013 22:49

Great article. Any plans for proxy support?

nishant mathur  •  May 25, 2013 17:01

This is script is very help full but i face a problem i am not fetch of attachment of mail....

IRAGUI  •  May 28, 2013 17:32

Thanks

Pablo  •  September 20, 2013 00:25

Nice script, just one thing, you forgot to put this
'enable' => 'true'

$mailboxes = array(
array(
'label' => 'Another mail account',
'mailbox' => '{mail.xxxx.com:110/pop3/novalidate-cert}INBOX',
'username' => 'xxxx@xxxx.com',
'password' => 'xxxx',
'enable' => 'true'
)

/novalidate-cert in may case, i need this

can you make somthing to view the mail ?

Amir  •  November 30, 2013 22:42

Hi,

How Is it possible to fetch only new emails by Ajax without refreshing the page ?

Max  •  February 7, 2014 02:26

Excellent script! Works perfect !!

If doesn't work for anyone check tath "php5-imap" mod is installed and enabled!

Bye!

Tomek  •  March 15, 2014 19:21

Script works. Good job. :)

Amzad Khan  •  May 24, 2014 12:22

Very nice tutorial for synchronize the gmail account to localhost.

Aris  •  May 26, 2014 04:54

In my case, even if there is no email, count($emails) still returns value of 1. It means that in this case, the variable $email is not an array but an empty string (value ''). So it creates error when passing through the foreach($emails as $email_id) and the rest. So I changed a bit my code:

if (!$emails){
?>
No e-mails found.

Aris  •  May 26, 2014 04:56

And now it's working.

obat pembesar penis  •  June 24, 2014 11:55

banyak wanita yang kurang puas terhadap pasangannya yang diakibatkan penis kurang besar dan panjang, oleh sebab itu kami menawarkan obat pembesar penis yang dapat memperbaiki ukuran penis anda dan bisa merubah gaya hidup anda yang lebih harmonis.

GxE  •  July 24, 2014 12:47

Many thanks for sharing this with us, is really a great solution.
Can you please suggest what to change to show also counter of unread emails (I mean just the number of unread messages)?
Thanks again

GxE  •  July 24, 2014 13:16

I just found a workaround to get unread messages counter:

search for $emails = imap_search($stream,'ALL');

and add this line below it:
$unreadcount = imap_mailboxmsginfo($stream);

and where you want to show the count (lower than above new line added) add this:
echo $unreadcount->Unread;

many thanks again

Ivan Cevcenko  •  July 29, 2014 21:37

hello,
I get this error

Fatal error: Call to undefined function imap_open() in /home/content/html/getmail.php on line 20

please help

Ivan Cevcenko  •  July 29, 2014 21:45

sorry, I uploaded it again and now I get nothing

Post your comment

(optional)
(optional, will not be shown)
NOTE: Any links will have rel="nofollow"

back