带有Imaplib4的Outlook从Python下载附件从不下载最后一个附件

时间:2019-05-29 23:04:01

标签: python email outlook imaplib

我编写的脚本:1)连接到我的工作Outlook电子邮件。该脚本从文本文件中读取我的用户名和密码,该文件位于变量TextFilePath中。 2)根据我选择的搜索词查找附件,该搜索词将出现在电子邮件的主题中(此处为“ special_search_term_in_email”)。 3)将附件下载到名为“ DownloadFolderPath”的特定文件夹。

此脚本的目标是每天运行并连接到我的电子邮件,并下载每天发送给我的4个附件。问题在于该脚本有时会下载所有4个附件,但有时只会下载4个附件中的3个,甚至都不会终止。感谢帮助。

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 :(得分:0)

我无法找出问题所在,但尝试在此处采用此代码: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