Python|解析eml文件,批量下载邮件附件

目前在做文职工作,所以必须得找点方法让自己保持思考。

其中一项工作是要管理邮箱,经常需要和四五六七八十个单位发送和接收邮件并下载附件。

之前就是一个一个点开,然后点击复制,然后把它们从下载挪到邮箱里。

然后有一天发现菜单栏有一个打包下载功能。

于是试了一下,但是下载出来的文件是eml格式

用Python可以对eml文件进行解析 

  • 获取解析邮件内容

  • # 获取邮件内容
    def get_message(eml_file):
        # 解析 eml 文件
        with open(eml_file, 'rb') as eml_file:
            eml_content = eml_file.read()
    
        # 解析EML文件内容
        msg = email.message_from_bytes(eml_content)
        return msg
  • 获取发件人
    # 获取发件人
    def get_sender(message):
        # sender = decode_and_extract(message['From'])
        sender=message.get("From")
        return decode_and_extract(sender)
    

    decode方法是因为因为获取的From长这样,所以需要进行解码

  • From: =?UTF-8?B?一串Base64编码的UTF-8字符串?= <邮箱地址>

    解码方法:

    def decode_and_extract(input_str):
        # 使用正则表达式匹配编码的UTF-8字符串和邮箱地址
        match = re.match(r'=\?UTF-8\?B\?(.*?)\?= <(.*?)>', input_str)
        if match:
            encoded_part = match.group(1)
            email = match.group(2)
    
            # 解码Base64编码的UTF-8字符串
            decoded_bytes = base64.b64decode(encoded_part)
            decoded_str = decoded_bytes.decode('utf-8')
    
            return decoded_str, email
    
        else:
            # 如果没有匹配到,则返回None
            return None, None

    解码后返回收件人和邮箱。

  • 获取收件人
  • 返回的收件人是一个string(可以用type()函数查看),但是收件人当不止一个,需要将其转化为数组。

    使用split函数将其分割,然后解码,将单个对象加入新的数组,返回收件人数组。

    =?UTF-8?B?收件人1==?= <邮箱1>,

    =?UTF-8?B?收件人2==?= <邮箱2>

    # 获取收件人
    def get_recipient(message):
        res=[]
        recipients = message.get("To").split(",")
        for rec in recipients:
            res.append(decode_and_extract(rec.strip()))
        return res
    
  • 获取邮件主题
  • Subject: =?UTF-8?B?乱码1==?=

     =?UTF-8?B?乱码2?=

     =?UTF-8?B?乱码3?=

    邮件主题返回的也是string,前面的方法和收件人一样,因为这里没有邮件地址,所以解码方法里也不需要匹配邮件地址

    def get_subject(message):
        res = []
        str= message.get("Subject")
        recipients = str.split("\n")
        for rec in recipients:
            res.append(decode_rfc2047(rec.strip()))
        decoded_text = ''.join(res)
        return decoded_text
    def decode_rfc2047(encoded_str):
        # 使用正则表达式匹配RFC 2047编码的字符串
        match = re.match(r'=\?UTF-8\?B\?(.*?)\?=', encoded_str)
        if match:
            encoded_part = match.group(1)
            decoded_bytes = base64.b64decode(encoded_part)
            decoded_str = decoded_bytes.decode('utf-8')
    
            return decoded_str
        else:
            # 如果没有匹配到,则返回None
            return None

    然后得到一个类似这样的数组,所以也需要使用join()方法把数组内容连接起来

    ["我是",“邮件”,“主题”]

  • 下载附件
  • # 下载附件
    def get_and_download_attachment(msg,save_dir):
    
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
    
        # 遍历邮件的各个部分
        for part in msg.walk():
            # 判断是否为multipart类型,如果是则跳过
            if part.get_content_maintype() == 'multipart':
                continue
    
            # 判断是否有Content-Disposition头部,且其值为attachment,表示该部分为附件
            content_disposition = part.get('Content-Disposition')
            if content_disposition and 'attachment' in content_disposition:
                # 获取附件的文件名
                res=[]
                f = part.get_filename().split("\n")
                for i in f:
                    res.append(decode_rfc2047(i.strip()))
                filename = ''.join(res)
                print(filename)
                if filename:
                    # 保存附件到本地文件系统
                    filepath = os.path.join(save_dir, filename)
                    with open(filepath, 'wb') as f:
                        f.write(part.get_payload(decode=True))
                        print("附件已保存: "+filepath)
    
  • 遍历文件夹下载附件
  • 从邮箱打包下载相关邮件之后就可以遍历文件夹对附件进行下载了。

    def traverse_and_download_attachment(root_folder,save_dir):
        for subdir in os.listdir(root_folder):
            subdir_path = os.path.join(root_folder, subdir)
            msg=get_message(subdir_path)
            get_and_download_attachment(msg,save_dir)
    

    作者:NuageL

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python|解析eml文件,批量下载邮件附件

    发表回复