0

The script I wrote:1) connects to my work Outlook email. The script reads my username and password from a text file which is found in the variable TextFilePath. 2) Looks for attachments based upon a searchterm I choose that would be in the Subject of the email (here, it's "special_search_term_in_email"). 3) Downloads the attachments to a specific folder titled 'DownloadFolderPath'.

The goal for this script is to run everyday and connect to my email and download 4 attachments that will be sent to me everyday. The issue is that the script will sometimes download all 4 attachments, but then sometimes will only download 3 of 4 attachments and then won't even terminate. Appreciate the help.

import email
import imaplib
import os
import datetime
import csv

# these 3 variables you need to set to run the code
mail_server = "imap-mail.outlook.com"
TextFilePath = "C:/Users/FakeName/PycharmProjects/imaplib_script/unpw.txt"
LogFilePath = 'C:/Users/FakeName/PycharmProjects/imaplib_script/downloaded_attachments/logfile.csv'
DownloadFolderPath = 'C:/Users/FakeName/PycharmProjects/imaplib_script/downloaded_attachments/'
# below read_input_return_list function reads input from a text file and returns a list

def read_input_return_list():
    textunpw = open(TextFilePath, "r")
    lines = textunpw.readlines()
    username = lines[0].strip('\n')
    password = lines[1]
    textunpw.close()
    return [username, password]


read_input_variable = read_input_return_list()


username = read_input_variable[0]
password = read_input_variable[1]
script_ran_time=datetime.datetime.today().strftime('%c')

mail = imaplib.IMAP4_SSL(mail_server)
mail.login(username, password)
print("{0} Connecting to mailbox via IMAP...".format(datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")))
mail.select()

type, data = mail.search(None, '(SUBJECT "special_search_term_in_email")')

total_count = 0
with open(LogFilePath,newline='', encoding='utf-8', mode='a') as csv_file:
    writer = csv.writer(csv_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    for num in data[0].split():
        type, data = mail.fetch(num, '(RFC822)')
        raw_email = data[0][1]
        raw_email_string = raw_email.decode('utf-8')
        email_message = email.message_from_string(raw_email_string)

        for part in email_message.walk():
            if part.get_content_maintype() == 'multipart':
                for part1 in part.walk():
                    c_type = part.get_content_type()
                    c_disp0 = str(part.get('Content-Disposition'))

                    # skip any text/plain (txt) attachments
                    if c_type == 'text/plain' and 'attachment' not in c_disp0:
                        body = part1.get_payload(decode=True)
                        break
            attachment = part.get_filename()
            if bool(attachment):
                filePath = os.path.join(DownloadFolderPath, attachment)
                if os.path.isfile(filePath):
                    filename, file_extension = os.path.splitext(filePath)
                    FileDownloadAndWriteTime = '__' + datetime.datetime.today().strftime('%m_%d_%Y %H_%M_%S')
                    new_fname = "{}_{}{}".format(filename, FileDownloadAndWriteTime, file_extension)
                    while os.path.exists(new_fname):
                        new_fname = "{}_{}{}".format(filename, FileDownloadAndWriteTime, file_extension)
                    filePath = new_fname
                filepathopen = open(filePath, 'wb')
                filepathopen.write(part.get_payload(decode=True))
                FileDownloadAndWriteTime = datetime.datetime.today().strftime('%m_%d_%Y %H_%M_%S')
                total_count += 1
                writer.writerow([filePath,FileDownloadAndWriteTime, script_ran_time])
                filepathopen.close()

                print('Download file attachment name: ', attachment)

print("Total count of downloaded documents: ", total_count)
mail.close()
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
BrianBeing
  • 431
  • 2
  • 4
  • 12
  • "sometimes will only download 3 of 4 attachments and then won't even terminate" - this sounds like a network/connectivity issue. – snakecharmerb Jun 02 '19 at 08:18

1 Answers1

0

I can't pinpoint what's wrong but try adopting this code here: https://gist.github.com/cdunklau/9001357

It worked for me.

I updated the find_attachments method like this:

def find_attachments(message):
    """
    Return a tuple of parsed content-disposition dict, message object
    for each attachment found.
    """
    found = []
    for part in message.walk():
        if 'content-disposition' not in part:
            continue
        cdisp = part['content-disposition'].split(';')
        cdisp = [x.strip() for x in cdisp]
        if cdisp[0].lower() != 'attachment':
            continue
        parsed = {}
        for kv in cdisp[1:]:
            try:
                key, val = kv.split('=')
                if val.startswith('"'):
                    val = val.strip('"')
                elif val.startswith("'"):
                    val = val.strip("'")
                parsed[key] = val
            except Exception as e:
                parsed['filename']=kv.replace('filename=','')
        found+=list(parsed.values())
    return found
kalidurge
  • 279
  • 2
  • 11