小白一枚,欢迎大神指点

需求:

写一个python脚本,获取所有未读邮件并将邮件信息打入钉钉群中
增加钉钉文本长度限制处理:电脑客户端和手机客户端发DING,最多可以发送5000以内的字符
新邮件内容文件位置:email_content/年月日/用户/tiamstamp.txt
执行脚本日志文件位置:email_log/用户/年月日.log
附件下载开关:attach_status=True/Fales
附件下载位置(与新邮件内容文件同级目录):email_content/年月日/用户/***
附件命名方式:主题+附件后缀

# -*- coding: utf-8 -*-
"""
function:   IMAP收取邮件
date:       2021-11-10
"""
import email
import email.header
import imaplib
import json
import requests
import os
import datetime, time


class IMAP:
    def __init__(self):
        ## 是否下载附件开关 False/True
        self.attach_status = True
        self.user_id = '邮箱账号'
        self.password = '邮箱密码'
        self.imap_server = 'map.exmail.qq.com'
        self.DD_Webhook = '钉钉接口'
        self.current_date = datetime.datetime.now().strftime("%Y%m%d")
        self.email_path = 'email_content/{}/{}/'.format(self.current_date,self.user_id)
        self.email_log_path = 'email_log/'
        self.check()
        self.get_content(self.login())
        self.loginout(self.login())

    def check(self):
        if not os.path.exists(self.email_path):
            os.makedirs(self.email_path)
        if not os.path.exists(self.email_log_path):
            os.makedirs(self.email_log_path)

    def login(self):
        try:
            serv = imaplib.IMAP4_SSL(self.imap_server, 993)
            print('邮箱服务器连接成功')
        except Exception as e:
            print('邮箱服务器连接失败:', e)
            with open('{}{}.log'.format(self.email_log_path, self.current_date), 'a', encoding='utf-8') as f:
                f.write("[失败]:{}\t{}\t邮箱服务器连接失败\n\n\n".format(time.asctime(time.localtime(time.time())),self.user_id))
                f.close()
            exit(1)

        try:
            serv.login(self.user_id, self.password)
            print('账号登录成功')
            return serv
        except Exception as e:
            print('账号登录失败:', e)
            with open('{}{}.log'.format(self.email_log_path, self.current_date), 'a', encoding='utf-8') as f:
                f.write("[失败]:{}\t{}\t账号登录失败\n".format(time.asctime(time.localtime(time.time())),self.user_id))
                f.close()
            exit(1)

    def loginout(self, conn):
        """
        登出邮件服务器
        :param conn: imap连接
        :return:
        """
        conn.close
        conn.logout()
        print('退出账号登录')

    def get_content(self, conn):
        """
        获取指定邮件,解析内容
        :param conn: imap连接
        :return:
        """
        # 在连接服务器后,搜索之前,需要选择邮箱,默认select(mailbox='INBOX', readonly=False)
        conn.select()
        # 筛选符合条件的邮件,这里不知道怎么过滤复杂条件,只能过滤未读邮件或全部
        ret, data = conn.search(None, 'UNSEEN')  # 未读邮件
        # 邮件列表
        email_list = data[0].split()
        if len(email_list) == 0:
            print('收件箱为空,程序退出')
            with open('{}{}.log'.format(self.email_log_path, self.current_date), 'a', encoding='utf-8') as f:
                f.write("[成功]:{}\t{}\t收件箱为空\n".format(time.asctime(time.localtime(time.time())),self.user_id))
                f.close()
            exit(1)
        # 获取邮件的序号
        for i in range(len(email_list)):
            # 获取邮件内容
            item = email_list[i]
            ret, data = conn.fetch(item, '(RFC822)')
            msg = email.message_from_string(data[0][1].decode('UTF-8'))
            sub = msg.get('subject')
            email_from = msg.get('from')
            email_to = msg.get('to')
            email_Cc = msg.get('Cc')
            email_date = msg.get('Date')[:24]
            sub_text = email.header.decode_header(sub)
            email_from_text = email.header.decode_header(email_from)
            email_to_text = email.header.decode_header(email_to)
            email_date_text = email.header.decode_header(email_date)
            try:
                email_Cc_text = email.header.decode_header(email_Cc)
            except Exception as e:
                pass
            if sub_text[0]:
                sub_detail = self.tuple_to_str(sub_text[0])
            email_from_detail = ''
            for i in range(len(email_from_text)):
                email_from_detail = email_from_detail + self.tuple_to_str(email_from_text[i])
            email_to_detail = ''
            for i in range(len(email_to_text)):
                email_to_detail = email_to_detail + self.tuple_to_str(email_to_text[i])
            for i in range(len(email_date_text)):
                email_date_detail = self.tuple_to_str(email_date_text[i])
            email_Cc_detail = ''
            try:
                for i in range(len(email_Cc_text)):
                    email_Cc_detail = email_Cc_detail + self.tuple_to_str(email_Cc_text[i])
            except Exception as e:
                pass

            print('主题:', sub_detail)
            print('时间:', email_date_detail)
            # print('发件人:', email_from_detail)
            # print('收件人:', email_to_detail)
            # print('抄送人:', email_Cc_detail)
            # 通过walk可以遍历出所有的内容
            file_name = '无'
            cc = ''
            for part in msg.walk():
                # 这里要判断是否是multipart,如果是,数据没用丢弃
                if not part.is_multipart():
                    # 字符集
                    # charset = part.get_charset()
                    # print('charset: ', charset)
                    # 内容类型
                    content_type = part.get_content_type()
                    # print('content-type', content_type)
                    # 如果是附件,这里就会取出附件的文件名,以下两种方式都可以获取
                    # name = part.get_param("name")
                    name = part.get_filename()
                    if self.attach_status:
                        if name:
                            # 附件
                            # 中文名获取到的是=?GBK?Q?=D6=D0=CE=C4=C3=FB.docx?=(中文名.docx)格式,需要将其解码为bytes格式
                            trans_name = email.header.decode_header(name)
                            if trans_name[0][1]:
                                # 将bytes格式转为可读格式
                                file_name = trans_name[0][0].decode(trans_name[0][1])
                            else:
                                file_name = trans_name[0][0]
                            print('开始下载附件:', file_name)
                            attach_data = part.get_payload(decode=True)  # 解码出附件数据,然后存储到文件中
                            try:
                                f = open(
                                    '{}{}.{}'.format(self.email_path, sub_detail, file_name.rsplit('.', maxsplit=1)[1]),
                                    'wb')  # 注意一定要用wb来打开文件,因为附件一般都是二进制文件
                            except Exception as e:
                                print(e)
                                f = open('tmp', 'wb')
                            f.write(attach_data)
                            f.close()
                            print('附件下载成功:', file_name)

                    txt = part.get_payload(decode=True)  # 解码文本内容
                    if content_type == 'text/plain':
                        try:
                            cc = str(txt, 'GBK').replace(' ', ' ').replace('&', '&').replace('<',
                                                                                                      '<').replace(
                                '>', '>').replace('"', '"').replace('&qpos;', "'")
                        except:
                            cc = str(txt, 'UTF-8').replace(' ', ' ').replace('&', '&').replace('<',
                                                                                                        '<').replace(
                                '>', '>').replace('"', '"').replace('&qpos;', "'")

            DD_limit = 4000
            sign = 0
            for num in range((int(len(cc)) // DD_limit) + 1):
                text = cc[sign:DD_limit]
                sign += 4000
                DD_limit += 4000
                print(text)

                msg1 = """主题:    {}
时间:     {}
发件人:    {}
收件人:    {}
抄送人:    {}
附件:     {}
邮件内容如下:
{}""".format(sub_detail, email_date_detail, email_from_detail, email_to_detail, email_Cc_detail, file_name, text)
                HEADERS = {"Content-Type": "application/json;charset=utf-8"}
                url = self.DD_Webhook
                data_info = {
                    "msgtype": "text",
                    "text": {
                        "content": msg1
                    },
                    "isAtAll": True
                }
                # 转化成自己需要的数据格式:转换成python格式的数据
                # value = bytes(json.dumps(data_info,ensure_ascii=False,indent=4),"utf-8")
                value = json.dumps(data_info)
                response = requests.post(url, data=value, headers=HEADERS)
                conn.store(item, '+FLAGS', r'(\Seen)')
                with open('{}tiamstamp.txt'.format(self.email_path), 'a', encoding='utf-8') as f:
                    f.write("%s \n\n\n" % msg1)
                    f.close()
                with open('{}{}.log'.format(self.email_log_path, self.current_date), 'a', encoding='utf-8') as f:
                    f.write("[成功]:{}\t{}\t主题:{}\t附件:{}\n".format(time.asctime(time.localtime(time.time())), self.user_id,sub_detail,
                                                             file_name))
                    f.close()

    def tuple_to_str(self, tuple_):
        """
        元组转为字符串输出
        :param tuple_: 转换前的元组,QQ邮箱格式为(b'\xcd\xf5\xd4\xc6', 'gbk')或者(b' <XXXX@163.com>', None),163邮箱格式为('<XXXX@163.com>', None)
        :return: 转换后的字符串
        """
        if tuple_[1]:
            out_str = tuple_[0].decode(tuple_[1])
        else:
            if isinstance(tuple_[0], bytes):
                out_str = tuple_[0].decode('UTF-8')
            else:
                out_str = tuple_[0]
        return out_str


if __name__ == '__main__':
    IMAP()

执行结果如下:

java 获取钉钉邮箱 钉钉邮箱邮件导出_java 获取钉钉邮箱


java 获取钉钉邮箱 钉钉邮箱邮件导出_服务器_02


java 获取钉钉邮箱 钉钉邮箱邮件导出_json_03


java 获取钉钉邮箱 钉钉邮箱邮件导出_java 获取钉钉邮箱_04