Приложение Python для загрузки из Outlook с Imaplib4 Никогда не загружает последнее вложение - PullRequest
0 голосов
/ 30 мая 2019

Сценарий, который я написал: 1) подключается к моей рабочей электронной почте Outlook. Сценарий считывает мое имя пользователя и пароль из текстового файла, который находится в переменной TextFilePath. 2) Ищет вложения, основанные на выбранном мной поисковом запросе, который будет в теме письма (здесь это «special_search_term_in_email»). 3) Загружает вложения в определенную папку с названием «DownloadFolderPath».

Цель этого сценария - запускать каждый день, подключаться к моей электронной почте и загружать 4 вложения, которые будут отправляться мне каждый день. Проблема в том, что сценарий иногда загружает все 4 вложения, но иногда загружает только 3 из 4 вложений и даже не завершает работу. Ценю помощь.

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()

1 Ответ

0 голосов
/ 13 июня 2019

Я не могу точно определить, что не так, но попробуйте принять этот код здесь: https://gist.github.com/cdunklau/9001357

Это сработало для меня.

Я обновил метод find_attachments следующим образом:

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
...