Downloading Gmail attachments using PHP


Automatically extracting attachments from Gmail can be important for reasons where you need to process the attached files periodically with a CRON job. Also it can be useful for automatically archiving important attachments. Below is a simple proof-of-concept plain PHP code, devoid of any object-oriented features that extracts attachments from your Gmail account. It uses PHPs imap extension to access the inbox.

Before you proceed make sure that imap is enabled in your Gmail settings page. All attachments downloaded in the following code are saved in the current folder, which you can easily change to point to another directory. Downloadable code is given at the end of the post.

<?php
 
 
/**
 *	Gmail attachment extractor.
 *
 *	Downloads attachments from Gmail and saves it to a file.
 *	Uses PHP IMAP extension, so make sure it is enabled in your php.ini,
 *	extension=php_imap.dll
 *
 */
 
 
set_time_limit(3000); 
 
 
/* connect to gmail with your credentials */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'YOUR_GMAIL_USERNAME'; # e.g somebody@gmail.com
$password = 'YOUR_GMAIL_PASSWORD';
 
 
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
 
 
/* get all new emails. If set to 'ALL' instead 
 * of 'NEW' retrieves all the emails, but can be 
 * resource intensive, so the following variable, 
 * $max_emails, puts the limit on the number of emails downloaded.
 * 
 */
$emails = imap_search($inbox,'ALL');
 
/* useful only if the above search is set to 'ALL' */
$max_emails = 16;
 
 
/* if any emails found, iterate through each email */
if($emails) {
 
    $count = 1;
 
    /* put the newest emails on top */
    rsort($emails);
 
    /* for every email... */
    foreach($emails as $email_number) 
    {
 
        /* get information specific to this email */
        $overview = imap_fetch_overview($inbox,$email_number,0);
 
        /* get mail message */
        $message = imap_fetchbody($inbox,$email_number,2);
 
        /* get mail structure */
        $structure = imap_fetchstructure($inbox, $email_number);
 
        $attachments = array();
 
        /* if any attachments found... */
        if(isset($structure->parts) && count($structure->parts)) 
        {
            for($i = 0; $i < count($structure->parts); $i++) 
            {
                $attachments[$i] = array(
                    'is_attachment' => false,
                    'filename' => '',
                    'name' => '',
                    'attachment' => ''
                );
 
                if($structure->parts[$i]->ifdparameters) 
                {
                    foreach($structure->parts[$i]->dparameters as $object) 
                    {
                        if(strtolower($object->attribute) == 'filename') 
                        {
                            $attachments[$i]['is_attachment'] = true;
                            $attachments[$i]['filename'] = $object->value;
                        }
                    }
                }
 
                if($structure->parts[$i]->ifparameters) 
                {
                    foreach($structure->parts[$i]->parameters as $object) 
                    {
                        if(strtolower($object->attribute) == 'name') 
                        {
                            $attachments[$i]['is_attachment'] = true;
                            $attachments[$i]['name'] = $object->value;
                        }
                    }
                }
 
                if($attachments[$i]['is_attachment']) 
                {
                    $attachments[$i]['attachment'] = imap_fetchbody($inbox, $email_number, $i+1);
 
                    /* 4 = QUOTED-PRINTABLE encoding */
                    if($structure->parts[$i]->encoding == 3) 
                    { 
                        $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
                    }
                    /* 3 = BASE64 encoding */
                    elseif($structure->parts[$i]->encoding == 4) 
                    { 
                        $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
                    }
                }
            }
        }
 
        /* iterate through each attachment and save it */
        foreach($attachments as $attachment)
        {
            if($attachment['is_attachment'] == 1)
            {
                $filename = $attachment['name'];
                if(empty($filename)) $filename = $attachment['filename'];
 
                if(empty($filename)) $filename = time() . ".dat";
 
                /* prefix the email number to the filename in case two emails
                 * have the attachment with the same file name.
                 */
                $fp = fopen($email_number . "-" . $filename, "w+");
                fwrite($fp, $attachment['attachment']);
                fclose($fp);
            }
 
        }
 
        if($count++ >= $max_emails) break;
    }
 
} 
 
/* close the connection */
imap_close($inbox);
 
echo "Done";
 
?>
Download Code file
Downloads : 2524 / File size : 1.5 kB

This site is a digital habitat of Sameer Borate, a freelance web developer working in PHP, MySQL and WordPress. I also provide web scraping services, website design and development and integration of various Open Source API's. Contact me at metapix[at]gmail.com for any new project requirements and price quotes.

28 Responses

1

David

May 29th, 2012 at 8:57 am

worked a treat, many thanks :)

2

phphunger

July 8th, 2012 at 10:30 pm

it says “Done”..but my doubt is where the attachments are stored after downloading….

sameer

July 8th, 2012 at 10:46 pm

The attachments are stored in the directory where the source file is located. However you can change the path to a different one by adding the path information to the filename. So to download the attachments to the directory “d:\gmail\attachments”, you can change the following line in the code (line no. 129):

$fp = fopen($email_number . “-” . $filename, “w+”);

to the following:

$fp = fopen(“d:/gmail/attachments/” . $email_number . “-” . $filename, “w+”);

4

phphunger

July 12th, 2012 at 5:51 am

hi sameer, i changed it to what ever you said..but still its not working….it says “Done”..i checked my path but no luck…any suggestions…

sameer

July 12th, 2012 at 7:04 am

$emails = imap_search($inbox,’ALL’);

After the above line check if any emails are returned using print_r

print_r($emails);

This should return and array something like the following, no empty array should be returned.

Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4

6

Candy

August 20th, 2012 at 8:56 pm

oh my god it works perfectly, thank you so much!

7

Ravi

September 9th, 2012 at 10:08 pm

Working Great! Thanks a lot.

8

Brett

September 29th, 2012 at 8:27 pm

I would like to use this script to first save a max of 8 attachments to a directory and then write a new row containing the attachment filenames, email body, subject and from address to a mySQL database. Is this possible???

sameer

September 29th, 2012 at 9:57 pm

Yes, it is possible.

10

Josefina

October 8th, 2012 at 3:06 am

Do you have a spam problem on this blog; I also am a blogger, and I was curious about your situation; we have developed some nice
procedures and we are looking to trade strategies with
other folks, why not shoot me an e-mail if interested.

11

Zuber

November 15th, 2012 at 8:03 am

Such a great site, not english likes…

12

Richard

November 22nd, 2012 at 7:44 pm

Nice script, but i have a question. I need it to do 2 things, 1 – get an email from just 1 address and 2 – download the attachment from the email?

13

Mike

December 4th, 2012 at 3:46 pm

How I order the images from by most recent? Showing the most recent first, and the oldest last?

The rsort() function doesn’t seem to work?

14

Ali

December 18th, 2012 at 12:19 am

Hi Sameer,

Thanks a lot for the tutorial. I am having a connection error. I doubt I am doing something wrong. can you please help?

15

Rajendra

January 11th, 2013 at 3:38 am

Thanks buddy….Its really awesome. After searching for 3 days finally your code worked.

Thanks

16

pajko

February 2nd, 2013 at 7:20 am

Great great tutorial! When I use it in non gmail account eg. my own email hosting, the $emails = imap_search($inbox,’NEW’); with NEW paramater must work? Because it is not working..

17

Tim

February 10th, 2013 at 2:24 pm

Can’t seem to get this to work. I get an error log report with the following:

[10-Feb-2013 14:55:29] PHP Warning: imap_open() [function.imap-open]: Couldn’t open stream {imap.gmail.com:993/imap/ssl}INBOX in /home/******/public_html/mywebsite.com/webcam/getimages.php on line 24

sameer

February 10th, 2013 at 8:31 pm

Make sure SSL is enabled on your PHP installation. The OpenSSL extension should be enabled. The IMAP Client library (with SSL) depends on this.

19

Scott

February 19th, 2013 at 3:17 pm

Hey,

Thanks for the script. Works great! Is there a attachement size limit? I can’t seem to save a 2.4mb image, whereas a 1mb saves fine

Scott

20

nagendra

February 27th, 2013 at 1:47 am

Hi,

Thanks for the code it worked like charm. It seems that is also downloading the inline images of mail content(mail body) if any. What if i don’t need any inline images to download and I only need attachments to download.

Please suggest…

Nagendra

21

TNR

April 21st, 2014 at 2:23 pm

Hi,

Great post, works great.

How do i save attachments embedded into the mail body, like images?

Thanks,
TNR

22

Amith

June 19th, 2014 at 9:52 pm

This code doesn’t work fine in Ubuntu.
Issues:
- Saving the attachment in the directory
- Contents of attachment
Please let me know what to do

23

Nitesh

June 25th, 2014 at 7:12 am

Greetings

I am trying to download from other email server not gmail, I did print_r($emails);
It shows 1 2 3 4 5 as you wrote above in one post . I am running the code on ubuntu,
It says done but the attachement is not there in the soucre directory.

Is it exlusively for gmail. I am using it for pop3
mail.somesite.com/pop3/novalidate-cert}INBOX
This doesnt work for pop3 I think?

Any Comments ?

Thanks

24

Nitesh

June 25th, 2014 at 7:21 am

Greetings again

I should have done this before the first comment.

Ok I change pop3 to imap in the server string
{mail.someservre.com/imap/novalidate-cert}INBOX

It gives one Notice after Done

DonePHP Notice: Unknown: rsh to IMAP server timed out (errflg=1) in Unknown on line 0

Thanks

25

Robert Schrenk

June 30th, 2014 at 10:32 pm

Thanks for this snipped of code! That really helped me.

Is it possible you mixed comments when decoding attachments from base64/quoted-printable encoding? It seems to me the comments are in the wrong order to the code itself!

Kind regards

26

Peter

July 9th, 2014 at 5:45 am

Thanks for the code. It works perfectly. Do have a question though:

/* get mail message */
$message = imap_fetchbody($inbox,$email_number,2);

1. Where do I find what 2 stands for? Can not seen to find what specific parts there are.
2. Why is the above line actually in your code example when you don’t use it any further in your code?

27

Martin Cisneros

July 28th, 2014 at 6:21 pm

Thank you very much! super useful code

28

Downloading Gmail attachments in PHP – an update

July 29th, 2014 at 5:45 am

[...] the last few years I’ve received quite some queries regarding the article Downloading Gmail attachments using PHP published here. After procrastinating for some time (a long time actually), I’ve answered [...]

Your thoughts