Reading Emails with PHP

Last week I got to do a fun little side project which we called My Slow Low. The site is a simple photo collection of slow/low carb meals for those that are out of ideas on what to eat, but want to stick to their diet. While conceptualizing how we would build the site, the idea of emailing in photos came up. We didn’t want the hassle of account management and were trying to go for a more “mobile capable” option. This was my first time coding for IMAP with PHP and I figured some others could use a jump start from what I’ve learned.

PHP already has a nice IMAP extension which needs to be installed and enabled before going further. The core functionality is all there, but the specifics on how to use it aren’t necessarily all that clear.

Here’s a PHP class I put together to do some basic operations on an IMAP Inbox. It’s a bit tailored to this project, but could be easily revised to fit other needs or extended to be more full featured.


class Email_reader {

	// imap server connection
	public $conn;

	// inbox storage and inbox message count
	private $inbox;
	private $msg_cnt;

	// email login credentials
	private $server = '';
	private $user   = '';
	private $pass   = 'yourpassword';
	private $port   = 143; // adjust according to server settings

	// connect to the server and get the inbox emails
	function __construct() {

	// close the server connection
	function close() {
		$this->inbox = array();
		$this->msg_cnt = 0;


	// open the server connection
	// the imap_open function parameters will need to be changed for the particular server
	// these are laid out to connect to a Dreamhost IMAP server
	function connect() {
		$this->conn = imap_open('{'.$this->server.'/notls}', $this->user, $this->pass);

	// move the message to a new folder
	function move($msg_index, $folder='INBOX.Processed') {
		// move on server
		imap_mail_move($this->conn, $msg_index, $folder);

		// re-read the inbox

	// get a specific message (1 = first email, 2 = second email, etc.)
	function get($msg_index=NULL) {
		if (count($this->inbox) <= 0) {
			return array();
		elseif ( ! is_null($msg_index) && isset($this->inbox[$msg_index])) {
			return $this->inbox[$msg_index];

		return $this->inbox[0];

	// read the inbox
	function inbox() {
		$this->msg_cnt = imap_num_msg($this->conn);

		$in = array();
		for($i = 1; $i <= $this->msg_cnt; $i++) {
			$in[] = array(
				'index'     => $i,
				'header'    => imap_headerinfo($this->conn, $i),
				'body'      => imap_body($this->conn, $i),
				'structure' => imap_fetchstructure($this->conn, $i)

		$this->inbox = $in;



A fair amount of this is self-explanatory or commented inline, but I will go over the inbox() method because it is the core functionality. The IMAP inbox is much like an array with a numbered key starting at 1. In the inbox() method, I store that index so that the email can be moved, deleted, or read again later.

Next, the header is stored with the function imap_headerinfo(). This pulls down an object from the server containing information like the Subject, From: address, To: address, and text encoding type.

Using imap_body(), the body text of the email is retrieved. What’s returned isn’t overly clean as it’s just the raw body with boundaries included (see: multipart messages). If the received email is in HTML, there will be a plain text and HTML version included. It’s certainly possible to parse through this data like any email client does, but it’s definitely a little bit messy.

Lastly, ‘structure’ is retrieved with the imap_fetchstructure() function. This is very important if you are trying to access attachments as I was with My Slow Low. In my next post, I’ll go further into the details of saving an attachment from an email and share some more about how I implemented the email processor for My Slow Low.

Update: I’ve posted the follow-up to this article on extracting email attachments with PHP.

  • kiran

    Hey thanks,

    It`s replay helpme. Thanks a lot

  • Anil Kumar

    Hi john,
    I am using email reader script its working but there is one issue to moving mail in Processed folder one server .can you recommend me ….

  • Galder S

    The script is really good! Thank you very much.

    Yes Anli Kumar. I had also the same problem. The problem is that when you iterate over $emails, that variable with the inbox messages is not updating the new number of messages once you transfer the imap email to another account.

    So the best is to start iterating with a for instead of a foreach, and start from the last email, the one with the highest index, in order that even if you move and email, the rest will remain with the same ID. Something like:

    $emails = New Email_reader();
    $total = count($emails->inbox);

    for($i=$total-1;$i>=0;$i–) {
    $email = $emails->inbox[$i];

    I hope you find this helpful. Best regards,


  • Damien Black

    There is a small indexing bug where the first email can only be accessed by the last index. This is because the first email gets put in $this->inbox[0], and that is served back only when you provide an index that is 1 too high to the get() function. This can be fixed easily like this:

    In the inbox() function change line 67 to:

    $in[$i] = array(

    Then, change the get function to the much simpler:

    function get($msg_index) {
    if (isset($this->inbox[$msg_index])) {
    return $this->inbox[$msg_index];
    return [];

  • Wow, it’s that easy… Thanks a lot :)

  • jestingandquesting

    Looks interesting. But if I understood any of it, I wouldn’t need help to do it. Looks like a cool article though. I’ll bet you know lots of stuff.

  • Wilman Bhigu

    Hi. Thank you so much. This post very usefull for me.

  • Nicholas Kimuli

    Thank you so much! Now I know where to start.

  • Maria Hayat

    i need help.
    how to Check email with PHP and IMAP ? plz help..

  • atulbhats

    Great Post! Thanks!

  • Hraday Joshi

    Thank you for sharing this code. It works really well but sometimes its showing following error if I use move()function.

    [Notice]: Unknown: The specified message set is invalid. (errflg=2) (Unknown:0)

    Any idea what’s triggering this error?

    I am looping all emails and moving to other folder. It works but sometimes its not able to move like one of the email and throw the above mentioned error.


  • Matias

    Hi, I am not able to make it work for Gmail. Please help

  • Hello . How can I get the email and insert it to MySQL DB ?

  • how do I pass this data into MySQL database ?

  • adlani yassine

    Hello I need tour help
    I want to use your code and tweek a bit so I can extract from names, subjects, to emails from my own hotmail or gmail account, from any folder too
    Do you have any idea how to do that?

  • Saleem Khan

    HI could anyone help me how to use this code?

  • Saleem Khan

    HI could you help me how to use this code?

  • Saleem Khan

    HI could anyone help me how to use this code?

  • Benjamin

    Notice: Unknown: SECURITY PROBLEM: insecure server advertised AUTH=PLAIN (errflg=1) in Unknown on line 0

    help ?