mailReader.php — Parse E-mail and Save Attachments PHP, Version 3

MailReader is No Longer Being Supported

It has been a fun ride, and many people are still interested in MailReader, but my own interests have moved elsewhere. I haven’t used MailReader for my own projects for nearly 2 years and there has never been any money in it for me or anything like that.

Feel free to continue using it, but it is getting a little long in the tooth. Some functions it uses generate depreciation warnings on newer versions of PHP.

  1. You can still download and use MailReader. Its code will live on GitHub for as long as GitHub is around.
  2. If you have problems, you are encouraged to post them on the MailReader GitHub issue tracker instead of here
  3. MailReader is OpenSource. You can pay (or not) anyone you want (including yourself!) to work on MailReader, the code is out there.
  4. I will accept GitHub pull requests that fix bugs or add features.

Thanks and Good Luck!


mailReader.php version 3 is here!

mailReader.php is a PHP script which handles incoming email messages, saving attachments to disk, and logging emails to a database.

Download it from GitHub now:

E-mail Processing Script Features:

  1. Saves the e-mail sender, subject and body to a database
  2. Saves any attachments as files and creates an entry for those files in the database, associated with the e-mail info in #1
  3. Sends  a response back to the sender telling them what files were received and their file sizes
  4. Checks a list of allowed senders to make sure we only take files from specified addresses.

Improvements in Version 3

mailReader.php is growingup a little bit more. It’s now a class instead of just a script. A new script mailPipe.php uses the mailReader class to achieve the same results the script did previously.

I did some database renaming so that none of the fields are reserved names, and they don’t need to be escaped anymore.

I updated the database connection code from mysql_connect to PDO.

I added support for uuencoded attachments. Uuencoded messages don’t have their mime-type detected, but everything else is the same as mime attachments.


Make sure that your upload directory is out of your webroot. If someone emails you a malicious PHP script (eg. Virus.php) and can access it via the web, they could infect your server or your visitors. Many servers are configured to automatically treat .pl and .cgi as CGI scripts and run them as well. You do not want to create a way for untrusted users to upload files to your webroot!

With the file names in the database you can use Readfile to pass files down to users.

Contribute Back!

I welcome any contributions which others may benefit from, so if you hack on it, consider submitting a pull request on GitHub.

This entry was posted in Computers, GitHub, Programming and tagged , , . Bookmark the permalink.

50 Responses to mailReader.php — Parse E-mail and Save Attachments PHP, Version 3

  1. Pingback: mailReader.php — Parse E-mail and Save Attachments PHP, Version 2 »

  2. Josh says:

    Hey stuporglue, thank you so much for this script, it has really helped me!
    I have been trying to use it to receive emails sent from an iphone with an attached image. The script seems to store the image and any text under it including the signature (“Sent from my iPhone”) fine. The problem is though, any text that gets placed above the image doesn’t get saved in the DB.

    Any ideas on how this can be fixed?
    Thank you very much!

  3. Harry says:

    I really really appreciate the time you have put into this.

    Would it be possible for you to head me in the correct direction, all of my emails have a csv file attachment.
    Does your program put the entire csv file in the files field? It appears it does and if that is true is it possible to get them back out of mysql as the original csv file looked in the original email that it parsed?

    • stuporglue says:


      In mailReader.php on line 160 is the start of a switch statement that checks the file’s mime type. I’m not positive which mime type a CSV file would have, but it’s probably text/csv. If that’s the case you’ll need to add text/csv as a supported mime type.

      • stuporglue says:


        I just updated mailReader.php so it should be easier to add custom mime types now.

        After creating a mailReader object (eg, in mailPipe.php) push any additional mime types into the allowed_mime_types array.

        $mr = new mailReader($save_directory,$allowed_senders,$pdo);
        $mr->allowed_mime_types[] = ‘text/csv’;

  4. Ryan Blackmer says:

    Thank you so much for your continued support of this great script!

    No sure if I found a bug or it’s my setup but I’ve tested several ways and am getting the same results with v3. The file insertion into the files table only works when sending one file attachment. If multiple are send within the same email, only one is inserted into the files table. The debug and reply email display all associated files but the database only displays one of the files.

    If it’s not a bug, any ideas?

    • stuporglue says:

      That’s a bug. I think I just fixed it. Please let me know how it works now.

      • Nicolas says:

        Works great!
        Thank you.

      • Ryan says:

        Tested and works. Database now records multiple attachments.

        I plan to do further testing later this week. iOS seems to send email two different ways depending on whether it’s within the Mail app or initiated from the Photo app… but that’s another issue for another day.

        Thanks again for the fix and speed reply!

      • stuporglue says:

        Yes, I think it does. I think one way sends the photos inline and the other sends it as regular attachments.

        If you find that one of the ways isn’t working please send me a sample that I can test with.


  5. Nicolas says:

    How can I add an array that would “Allowed_Emails”, means that pipe is only replying to registered emails boxes and rejecting others?

    Thank you,

    • stuporglue says:

      See the sample script here: for how to set up allowed senders.

      Since the script currently uses die() I suppose it will respond to anyone who sends an email to it (if just to say “not an allowed sender”). It should probably fixed so that it sends that message with error_log, exits with an error code and doesn’t print anything out.

      • Nicolas says:

        Thank you for the fast answer and sorry for my unprecise question.
        I understand about “Allowed_Senders”, but my point is about “Allowed_Emails” boxes on the email server.

        For example, my server is “” and I would like some people (Allowed_Senders) to send messages to some email address on my server (Allowed_Emails) like, All other messages are rejected by the pipe script and not stored on the server.

        These Allowed_Emails could be in an array, but also in a database for example.
        Thank you for your advice,

      • stuporglue says:

        Ah, I think I understand. That sounds like it’s outside of the scope of mailReader, and should be handled with other mail handling rules by the mail server. Despite the simple Allowed_Senders abilities, mailReader is really just about taking incoming attachments/messages and saving them.

  6. Nicolas says:

    Hi again,

    I discovered that emails bodies are stored in a way that URL links > 72 characters are broken.
    Do i missed something?

    Thank you for your help,

  7. Nicolas says:

    Hi again,

    I try to detect URL and URL title in body’s email before the body is saved into the db.
    Goal for me is to put them in a separate section in the db.
    How can I do that?
    Thank you,

    • stuporglue says:

      I’m afraid that the script isn’t quite smart enough to do that sort of sorting work. That’s probably outside the scope of this script.

      I’d probably recommend using mailreader.php to get things into the database, then writing a post-processing script to sort messages once they’re in the db.

      Either that, or fork mailreader.php and customize it to meet your needs.

  8. Nicolas says:

    Hi again,

    Seems that the script is not working with email address being in CC:
    Is it my system ? Do I have to do something special ?

    Thank you,

    • stuporglue says:

      This is a missing feature and should be implemented. I won’t be able to get to it for a bit, but if you implement it I’d be happy to accept a pull request on GitHub.

  9. Mark Jansen says:

    Thanks for this great script.

    I noticed that the script currently only saves the plain text body of the email. Could it also be possible to save both the plain text body and the HTML body of the message? What changes would be required to do so? Thanks!

    • stuporglue says:

      Sorry for the late delay.

      You’d need to modify the code near:
      } else if($mimeType == 'text/plain'){
      to also look for text/html instead of text/plain.

  10. Pingback: How to insert incoming e-mail message into mySQL database? - PHP Solutions - Developers Q & A

  11. Brian says:

    Hi, this sounds like what I need, but I want to control what to do with the email. Is it possible to use your code just to retrieve each part of the email? I can then choose what I do with each part?



    • stuporglue says:

      Not as such. My code is open source, so you could grab the pieces you need and use them.

      What might be more simple though would be to use Pear’s MimeDecode, which is what my script uses to retrieve different pieces of the email anyways. If you needed it you could use my script as a reference to see how to use it.

  12. Hi stuporglue. Thanks very much for all your efffort putting these latest scripts together. It all works well for me, even for emails sent from Apple Mail. Had a wee niggle with wrong path to mimeDecode. For me it needs to be..

  13. Fiona Fenton says:

    I am having problems with getting this to work with emails sent from a Mac. I can’t seem to find a way to attach, rather than embed, images to an email sent from a Mac.
    The script sees the email as having no attachments.
    Is there a way to either attach images to Mac emails or have the script recognise embedded images?

  14. Tom says:

    Wow, great script! Exactly what I was looking for and works great. Thanks a lot for publishing this.

  15. teddy87 says:

    Hi, i have a little Problem.
    your Script works not so perfect for me.
    Image files upload perfect but the filename change to XX_name_png instead of XX_name.png
    and all PDF upload are blank.
    E-mail body saved in DB but no files are stored in db or folder. single and multiple.

    Thank you.
    Teddy87 from Germany

    • stuporglue says:

      Files are renamed with a timestamp _ name _ extension for two reasons. 1) Uploading two files with the same name would cause the first file to be overwritten and 2) So that someone can’t upload bad_virus.exe and then use your server to serve viruses to people.

      The blank PDF thing sounds like a possible bug, but I’m not sure what would cause it.

      Files themselves aren’t stored in the database, but a reference to the file name should be.

      I’m not sure what you mean by “single and multiple”

      • teddy87 says:

        Rename: okay, is change the ending in my further processing back. Thanks ;)

        Blank pdf: i now it, the Filenames stored in the DB, but that does not happen.
        The Mail body stored in email Table an the File Table found no entry.
        Back mail:
        Thanks! I just uploaded the following files to your storage:

        Filename — Size

        I hope everything looks right. If not,please send me an e-mail!
        Single, mutiple:
        Attachments. One PDF as Attachments an more then one pdf in one E-mail.

        i can send you an test PDF.
        my Server: Debian Root server.
        Apache 2, php5, Pear last version, mimeDecode (unknown)

  16. teddy87 says:

    Okay, if i send mail with pdf Attachments over Outlook (2013) works perfect,
    at this moment looks like a Problem with Thunderbird (24.2.0).
    same PDF, from Apple Mail ( account

  17. teddy87 says:

    i found the Problem,
    Thunderbird sends PDF as docum/pdf mime

    Content-Type: docum/pdf;
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment;

    after adding in allowed_mime_types, is works Perfectly.

    Thanks for this nice script ;)

  18. mahender says:

    Hi am getting the following error pls help me: Fatal error: Uncaught exception ‘PDOException’ with message ‘could not find driver’

  19. freshDev says:

    Great script, it was a great starting point for me. When I send an email with attachments to a mobile phone the attachments disappear when opening the message in the mail app. The attachments work perfect when opening on PC just not on mobile. Any idea what would be causing this?

    • stuporglue says:

      I haven’t seen this before and I’m afraid I don’t quite understand. The emails this script sends don’t have attachments, they’re just plain text.

  20. daniel says:

    just wanted to say: great script!
    it works for receiving (multiple) attachments when sent from iphone. when sending images from thunderbird, it seems to fail. but it does not matter for my use case :)
    we use it for a party :) thanks for all the effort you put into this

    • daniel says:

      no issues with thunderbird, I re-tested and it works.
      if anybody is interested in some “send email with photo attachment and show photos as a slideshow (adding new ones ad hoc)” script (perfect for parties), let me know.

  21. Jack says:

    Hi… I want to setup in a way in the following fashion.

    1) Sender sends an email.
    2) Php file should automatically recognize that email has been received.
    3) PHP mail reader gets triggered and saves the attachment.
    4) response back to the sender.

    I guess, how do I have the Step-2 done ? I don’t want to run the php file manually. how would this PHP file should be setup so I can sit and relax and PHP reader does the rest?
    (please email to

  22. Jack says:

    Okay.. It’s working fine for MIME type…but doesn’t work for Audio files (mp3 and m4a)…
    can someone let me know the correct syntax I should use ? Here is the code which doesn’t work. all other extensions work though.

    Image works like a charm but m4a files doesn’t work.

    —-code starts —-
    case ‘image’:
    case ‘jpeg’: // Save these image types
    case ‘png’:
    case ‘gif’:
    $body = $body_part->body;
    case ‘audio/mp4’:
    $body = $body_part->body;
    case ‘m4a’:saveFile($filename,$body_part->body,$mimeType);

    —–code ends here—-

  23. Hi,
    Great scripts! I just use them to bulk existing email from an account. But in this case I need the email date instead of use current date, I use date from email header (mimeDecode) and add it to the Insert query. I can post the code adjustments I did and the script for the bulk email. I must adjust the db.sql too. I think it is to few changes to fork the code, but could help somebody else. Diego

Comments are closed.