阿里邮箱IMAP场景示例:获取邮件并保存为eml文件

更新时间: 2024-11-11

Python示例代码

场景:获取邮件主题和内容,并保存为eml文件,文件名格式为email_uid_subject.eml。

重要

风险提示:下述代码在Python 3.11.9进行的测试,用于生产环境之前请务必先做好测试。

 

# -*- coding: utf-8 -*-import imaplibimport emailfrom imapclient import imap_utf7def get_folders():    # 获取邮箱文件夹列表
    list_folder = []
    list_folder_org = conn.list()    for i in list_folder_org[1]:
        list_folder.append(imap_utf7.decode(i).split('/" ')[1].replace('"', ''))  # 截取文件夹名称
    print(list_folder)    return list_folder# def get_content(msg):#     # 解码邮件内容#     if msg.is_multipart():#         # 列表#         return get_content(msg.get_payload(0))  # 获取邮件中的文本#     else:#         # 字符串#         return msg.get_payload(None, decode=True)  # 获取邮件中的文本,如果是True将解码base64/quoted-printable等格式编码内容,否则不解码def save_email_as_eml(msg, uid):    # 保存邮件为 .eml 文件
    subject = msg['Subject']    if subject:        try:            # 尝试解码主题
            decoded_subject = email.header.decode_header(subject)[0][0]            if isinstance(decoded_subject, bytes):
                decoded_subject = decoded_subject.decode('utf-8')            # 替换文件名中的非法字符
            safe_subject = "".join([c if c.isalnum() or c in (' ', '.', '_') else '_' for c in decoded_subject])
            eml_filename = f"email_{uid}_{safe_subject}.eml"
        except Exception as e:            print(f"解码主题失败: {e}")
            eml_filename = f"email_{uid}.eml"
    else:
        eml_filename = f"email_{uid}.eml"

    with open(eml_filename, 'w', encoding='utf-8') as f:
        f.write(msg.as_string())    print(f"邮件已保存为 {eml_filename}")# 配置 IMAP 服务器imap_server = 'imap.qiye.aliyun.com'  # IMAP 服务器地址username = 'test@example.com'  # 用户名password = '*********'  # 密码port = 993  # 端口号# 连接服务器,并登录conn = imaplib.IMAP4_SSL(imap_server, port)  # SSL加密连接# 认证登录conn.login(username, password)print('邮箱文件夹列表:')
get_folders()  # 获取邮箱文件夹列表folder_name = imap_utf7.encode('folder1')  # utf-7编码,中文编码conn.select(folder_name)  # 'draft','INBOX'   #选取文件夹v_type, data = conn.search(None, 'UNSEEN SINCE 05-Mar-2024')  # 查询某日期后的未读邮件email_list = data[0].split()if len(email_list) == 0:    print('文件夹为空,退出!')
    exit(1)print('状态=', v_type, '消息队列序号num=', data)print('该文件夹下所有的UID:', conn.uid('search', None, "ALL"))# 获取最后一封邮件的序号item = email_list[len(email_list) - 1]print('最后一封邮件的消息队列序号num:', item)

v_status = conn.status(folder_name, '()')
v_status_1 = (v_status[1][0].decode('utf-8').replace('MESSAGES', '邮箱中的邮件总数:')
              .replace('RECENT', '邮箱中标志为RECENT的邮件数:')
              .replace('UIDNEXT', '可以分配给新邮件的下一个UID:')
              .replace('UIDVALIDITY', '邮箱的UID有效性标志:')
              .replace('UNSEEN', '未读邮件:'))print('邮箱文件夹基本信息:', folder_name, v_status_1)
v_count = 1list_show_yulan = []# 解析邮件for num in email_list:
    v_type, data = conn.fetch(num, '(RFC822)')
    UID = conn.fetch(num, 'UID')[1]
    v_num_uid = UID[0].decode('utf-8').replace('(', '').replace(')', '').split(' ')    print('\n解析第' + str(v_count) + '封邮件,num=', v_num_uid[0], ' UID=', v_num_uid[2],          '===============================================')    print('服务器返回值=', data[0])  # 返回的结果,包含num,UID和邮件原文
    msg = email.message_from_bytes(data[0][1])    print('邮件eml原文:\n', msg)    # 保存邮件为 .eml 文件
    save_email_as_eml(msg, v_num_uid[2])

    v_count = v_count + 1# conn.print_log()  # 打印IMAP日志conn.close()

运行结果

image

image

image