Python获取微软Microsoft Exchange邮件信息

目前我们公司使用的是微软的exchange企业邮箱

最近有个临时任务是写个获取邮件信息的模块

百度了一下, 没有发现目前还可以使用的代码

下面贴出我写的模块, 亲测可用

 

import datetime
from exchangelib import (
    Credentials,
    Account,
    DELEGATE,
    Configuration,
    FileAttachment,
    EWSDateTime,
    EWSTimeZone,
)
from exchangelib.protocol import CachingProtocol


class EmailLoader:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.account = self.connect_to_mailbox()

    def connect_to_mailbox(self):
        cred = Credentials(self.username, self.password)
        config = Configuration(server="outlook.office365.com", credentials=cred,)
        account = Account(
            primary_smtp_address=self.username,
            config=config,
            autodiscover=False,
            access_type=DELEGATE,
        )
        print("--------Connected--------")
        return account

    def get_email_list(self, send_time_gte, subject_like=None, sender=None):
        """

        :param send_time_gte: must be specified
        :param subject_like: if None, it means no restrictions
        :param sender: if None, it means no restrictions
        :return: list type
        """
        tz = EWSTimeZone.timezone("Asia/Shanghai")
        email_list = []
        send_time_gte = datetime.datetime.strptime(send_time_gte, "%Y-%m-%d")
        inbox = self.account.inbox.filter(
            datetime_sent__gte=tz.localize(
                EWSDateTime(send_time_gte.year, send_time_gte.month, send_time_gte.day)
            )
        )

        for item in inbox.all().order_by("-datetime_sent"):
            subject = item.subject
            if not item.sender:
                continue
            sender_name = item.sender.name
            send_time = (item.datetime_sent + datetime.timedelta(hours=8)).strftime(
                "%Y-%m-%d %H:%M:%S"
            )
            b1 = (
                True
                if not subject_like or subject_like.lower() in subject.lower()
                else False
            )
            b2 = True if not sender or sender.lower() in sender_name.lower() else False

            if b1 and b2:
                email_list.append([subject, sender_name, send_time])
        print("get {} email(s) in total".format(len(email_list)))
        return email_list

    def download_email(self, subject, sender, send_time):
        """
        all three parameters must be specified
        only download one email each time
        :param subject:
        :param sender:
        :param send_time:
        :return: dict type
        """
        tz = EWSTimeZone.timezone("UTC")
        _dict = {}
        send_time = datetime.datetime.strptime(
            send_time, "%Y-%m-%d %H:%M:%S"
        ) - datetime.timedelta(hours=8)
        send_time = tz.localize(
            EWSDateTime(
                send_time.year,
                send_time.month,
                send_time.day,
                send_time.hour,
                send_time.minute,
                send_time.second,
            )
        )
        inbox = (
            self.account.inbox.filter(datetime_sent__gte=send_time,)
            .filter(datetime_sent__lte=send_time)
            .filter(subject__icontains=subject)
        )

        for item in inbox.all().order_by("-datetime_sent"):
            if sender.lower() in item.sender.name.lower():
                _dict["content"] = item.text_body
                _dict["attachments"] = [
                    {"name": attachment.name, "content": attachment.content}
                    for attachment in item.attachments
                    if isinstance(attachment, FileAttachment)
                ]
                if _dict:
                    print('one mail meets conditions')
                return _dict
            return

    @staticmethod
    def close_connections():
        CachingProtocol.clear_cache()


emailLoader = EmailLoader(username="***@***.com", password="***")
email_list = emailLoader.get_email_list(send_time_gte="2020-03-10")
print(email_list[0][2])  # latest mail sent-time
print(email_list[-1][2])  # oldest mail sent-time
latest_mail = emailLoader.download_email(
    email_list[0][0], email_list[0][1], email_list[0][2]
)
oldest_mail = emailLoader.download_email(
    email_list[-1][0], email_list[-1][1], email_list[-1][2]
)
emailLoader.close_connections()

需要注意的点有:

1.时区问题, 默认获取到的邮件发送时间是UTC时间, 跟北京时间相差8个小时, 按照实际需求需要转化一下

2.self.account.inbox.filter似乎不能传入可以筛选邮件发送人名字sender.name的参数, 导致代码复杂了一些

后续我的boss没有提出什么修改意见了,  我也没有过多使用和优化细节

Thanks !

posted @ 2020-03-15 22:46  布里塔  阅读(2774)  评论(1编辑  收藏  举报