-1

I'm using Python to download image attachments from gmail using the following script:

#!/usr/bin/env python3
# read emails and detach attachment in attachments directory
 
import email
import getpass, imaplib
import os
import sys
import time
 
detach_dir = '.'
if 'attachments' not in os.listdir(detach_dir):
    os.mkdir('/var/www/html/attachments')
 
userName = 'enter-your-gmail-account-name-here'
passwd = 'enter-your-password-here'
 
try:
    imapSession = imaplib.IMAP4_SSL('imap.gmail.com',993)
    typ, accountDetails = imapSession.login(userName, passwd)
    if typ != 'OK':
        print ('Not able to sign in!')
        raise Exception
 
    imapSession.select('Inbox')
    typ, data = imapSession.search(None, 'SUBJECT', '"DASHBOARD"')
    if typ != 'OK':
        print ('Error searching Inbox.')
        raise Exception
 
    # Iterating over all emails
    for msgId in data[0].split():
        typ, messageParts = imapSession.fetch(msgId, '(RFC822)')
 
        if typ != 'OK':
            print ('Error fetching mail.')
            raise Exception
 
        emailBody = messageParts[0][1] 
        mail = email.message_from_bytes(emailBody) 
 
        for part in mail.walk():
 
            if part.get_content_maintype() == 'multipart':
 
                continue
            if part.get('Content-Disposition') is None:
 
                continue
 
            fileName = part.get_filename()
 
            if bool(fileName): 
                filePath = os.path.join(detach_dir, '/var/www/html/attachments', fileName)
                if not os.path.isfile(filePath) : 
                    print (fileName)
                    print (filePath)
                    fp = open(filePath, 'wb')
                    fp.write(part.get_payload(decode=True))
                    fp.close()
 
    #MOVING EMAILS TO PROCESSED PART BEGINS HERE
    imapSession.select(mailbox='inbox', readonly=False)
    resp, items = imapSession.search(None, 'All')
    email_ids = items[0].split()
    for email in email_ids:
        latest_email_id = email
 
        #move to processed
        result = imapSession.store(latest_email_id, '+X-GM-LABELS', 'Processed')
 
        if result[0] == 'OK':
            #delete from inbox
            imapSession.store(latest_email_id, '+FLAGS', '\\Deleted')
 
    #END OF MOVING EMAILS TO PROCESSED
 
    imapSession.close()
    imapSession.logout()
 
except :
    print ('No attachments were downloaded')

I'm getting the following error:

Traceback (most recent call last):
  File "/home/jenns/get_images_from_emails.py", line 12, in <module>
    os.mkdir('/var/www/html/attachments')
FileExistsError: [Errno 17] File exists: '/var/www/html/attachments'

I've noticed that python3 is not in #!/usr/bin/env python3 and changed it to #!/usr/bin python3 which didn't produce different results.

I know the gmail side is working because the attachment is moving to the Processed Folder and the email is deleted from my inbox.

I've also used sudo chmod 775 '/var/www/html/attachments' and that didn't resolve the problem. Any ideas as to why the files aren't downloading using the script, get_images_from_emails.py ?

1
  • os.mkdir: "Create a directory named path with numeric mode mode. If the directory already exists, FileExistsError is raised". You can try the more modern Path.mkdir with exists_ok=True. Commented May 28, 2023 at 17:15

2 Answers 2

1

The error message tells you, that the folder you're trying to create already exists, not a file. A file would be overwritten.

This likely happens due to not providing the full path for your "detach_dir" when checking for its existence, but then providing a full path for creating it.

Something like this should work:

attach_dir =  '/var/www/html/attachments'
if not os.path.exists(attach_dir):
    os.makedirs(attach_dir)

Edit:

And I'm not sure about your directory structure, but this looks like it could be an error ...

filePath = os.path.join(detach_dir, '/var/www/html/attachments', fileName)

... as the above suggests that your "detach_dir" would be /var/www/html, thus the filepath would be: /var/www/html/var/www/html/attachments/filename (a directory that likely doesn't exist)

Sign up to request clarification or add additional context in comments.

1 Comment

@sm Thanks so much for your help. Now I'm having an issue where files with the same name don't get overwritten. Any idea why?
1

Thanks to @sm this was the resulting script that works!

#!/usr/bin/env python3
# read emails and detach attachment in attachments directory
 
import email
import getpass, imaplib
import os
import sys
import time
 
detach_dir =  '/var/www/html/attachments'
if not os.path.exists(detach_dir):
    os.makedirs(detach_dir)
 
userName = 'enter-your-gmail-account-name-here'
passwd = 'enter-your-password-here'
 
try:
    imapSession = imaplib.IMAP4_SSL('imap.gmail.com',993)
    typ, accountDetails = imapSession.login(userName, passwd)
    if typ != 'OK':
        print ('Not able to sign in!')
        raise Exception
 
    imapSession.select('Inbox')
    typ, data = imapSession.search(None, 'SUBJECT', '"DASHBOARD"')
    if typ != 'OK':
        print ('Error searching Inbox.')
        raise Exception
 
    # Iterating over all emails
    for msgId in data[0].split():
        typ, messageParts = imapSession.fetch(msgId, '(RFC822)')
 
        if typ != 'OK':
            print ('Error fetching mail.')
            raise Exception
 
        emailBody = messageParts[0][1] 
        mail = email.message_from_bytes(emailBody) 
 
        for part in mail.walk():
 
            if part.get_content_maintype() == 'multipart':
 
                continue
            if part.get('Content-Disposition') is None:
 
                continue
 
            fileName = part.get_filename()
 
            if bool(fileName): 
                filePath = os.path.join(detach_dir, fileName)
                if not os.path.isfile(filePath) : 
                    print (fileName)
                    print (filePath)
                    fp = open(filePath, 'wb')
                    fp.write(part.get_payload(decode=True))
                    fp.close()
 
    #MOVING EMAILS TO PROCESSED PART BEGINS HERE
    imapSession.select(mailbox='inbox', readonly=False)
    resp, items = imapSession.search(None, 'All')
    email_ids = items[0].split()
    for email in email_ids:
        latest_email_id = email
 
        #move to processed
        result = imapSession.store(latest_email_id, '+X-GM-LABELS', 'Processed')
 
        if result[0] == 'OK':
            #delete from inbox
            imapSession.store(latest_email_id, '+FLAGS', '\\Deleted')
 
    #END OF MOVING EMAILS TO PROCESSED
 
    imapSession.close()
    imapSession.logout()
 
except :
    print ('No attachments were downloaded')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.