You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python创建Outlook邮件跟踪服务(含Microsoft Graph与本地服务)

解决方案:两类Python邮件跟踪服务实现

咱先搞定第一个基于Microsoft Graph的邮件跟踪服务,这个方案跨平台友好,不需要依赖本地Outlook客户端,只要能访问Graph API就能运行。

方案1:基于Microsoft Graph的邮件跟踪服务

前期准备

  • 去Azure Active Directory注册一个应用,拿到三个核心参数:CLIENT_ID、CLIENT_SECRET、TENANT_ID
  • 给应用添加权限:如果是用户级使用,加Delegated权限Mail.Read和Mail.Send;如果是服务级无人值守场景,加Application权限,记得让管理员授予权限同意
  • 安装依赖包:
pip install msgraph-core python-dotenv requests

完整代码实现

先创建.env文件存配置信息(避免硬编码敏感数据):

CLIENT_ID=你的客户端ID
CLIENT_SECRET=你的客户端密钥
TENANT_ID=你的租户ID
TARGET_SUBJECT=目标邮件主题
FORWARD_TO=要转发的收件人邮箱

然后是Python核心代码:

import os
import time
from dotenv import load_dotenv
from msgraph.core import GraphClient
from azure.identity import ClientSecretCredential

# 加载环境变量
load_dotenv()

# 初始化Graph客户端
credential = ClientSecretCredential(
    tenant_id=os.getenv("TENANT_ID"),
    client_id=os.getenv("CLIENT_ID"),
    client_secret=os.getenv("CLIENT_SECRET")
)
client = GraphClient(credential=credential)

TARGET_SUBJECT = os.getenv("TARGET_SUBJECT")
FORWARD_TO = os.getenv("FORWARD_TO")

def track_and_forward_emails():
    """轮询收件箱,匹配主题后自动转发"""
    # 过滤条件:匹配目标主题+未读邮件,可根据需求调整
    query = f"$filter=subject eq '{TARGET_SUBJECT}' and isRead eq false"
    while True:
        try:
            # 获取符合条件的邮件列表
            response = client.get(f"/me/messages?{query}")
            response.raise_for_status()
            emails = response.json().get("value", [])
            
            for email in emails:
                email_id = email["id"]
                print(f"找到匹配主题的邮件,ID: {email_id}")
                
                # 拉取邮件完整详情(正文、附件等)
                email_details = client.get(f"/me/messages/{email_id}?$select=subject,body,attachments")
                email_details.raise_for_status()
                email_data = email_details.json()
                
                # 构造转发请求
                forward_payload = {
                    "comment": "自动转发:匹配目标主题的邮件",
                    "toRecipients": [{"emailAddress": {"address": FORWARD_TO}}]
                }
                client.post(f"/me/messages/{email_id}/forward", json=forward_payload)
                
                # 标记为已读,避免重复处理
                client.patch(f"/me/messages/{email_id}", json={"isRead": True})
                print(f"邮件已转发给 {FORWARD_TO}")
        
        except Exception as e:
            print(f"处理邮件时出错: {str(e)}")
        
        # 每隔30秒轮询一次,可根据需求调整间隔
        time.sleep(30)

if __name__ == "__main__":
    print("启动Microsoft Graph邮件跟踪服务...")
    track_and_forward_emails()

注意事项

  • 如果是服务级应用(不需要用户登录),要把/me换成/users/{目标用户ID},确保权限配置正确
  • 追求实时性的话,可以用Graph API的订阅功能替代轮询,实现新邮件实时通知,但配置复杂度会高一些

方案2:本地Outlook邮件跟踪服务(Windows专属)

这个方案依赖Windows本地安装的Outlook客户端,适合不需要联网访问Graph API的场景,直接通过COM接口操作本地Outlook。

前期准备

  • 确保Windows上已安装Outlook,并且登录了目标邮箱账号
  • 安装依赖包:
pip install pywin32

完整代码实现

import win32com.client
import pythoncom
import time

# 自定义配置参数
TARGET_SUBJECT = "你的目标邮件主题"
FORWARD_TO = "要转发的收件人邮箱"

class OutlookMailTracker:
    def __init__(self):
        self.outlook = win32com.client.Dispatch("Outlook.Application")
        self.namespace = self.outlook.GetNamespace("MAPI")
        self.inbox = self.namespace.GetDefaultFolder(6)  # 6代表Outlook收件箱
        self.processed_ids = set()  # 记录已处理邮件ID,避免重复转发

    def track_new_emails(self):
        """监听新邮件事件,实时处理匹配的邮件"""
        # 注册NewMailEx事件,有新邮件时触发回调
        self.outlook.NewMailEx += self.on_new_mail
        print("启动本地Outlook邮件跟踪服务...")
        print("等待新邮件(按Ctrl+C停止服务)")
        
        # 保持程序运行,处理Windows消息循环
        while True:
            pythoncom.PumpWaitingMessages()
            time.sleep(1)

    def on_new_mail(self, entry_id_collection):
        """新邮件触发的回调函数"""
        # entry_id_collection可能包含多个邮件ID,用逗号分隔
        for entry_id in entry_id_collection.split(","):
            if entry_id in self.processed_ids:
                continue
            
            try:
                mail = self.namespace.GetItemFromID(entry_id)
                # 模糊匹配主题(忽略大小写),可改成精确匹配
                if TARGET_SUBJECT.lower() in mail.Subject.lower():
                    print(f"找到匹配主题的邮件:{mail.Subject}")
                    
                    # 读取邮件内容
                    plain_body = mail.Body  # 纯文本正文,要HTML内容用mail.HTMLBody
                    attachments = [att.FileName for att in mail.Attachments] if mail.Attachments.Count > 0 else []
                    print(f"邮件正文预览:{plain_body[:200]}...")
                    if attachments:
                        print(f"附件列表:{', '.join(attachments)}")
                    
                    # 转发邮件(自动携带原附件)
                    forward_mail = mail.Forward()
                    forward_mail.To = FORWARD_TO
                    forward_mail.Subject = f"自动转发:{mail.Subject}"
                    forward_mail.Body = f"以下是匹配主题的自动转发邮件\n\n原邮件内容:\n{plain_body}"
                    forward_mail.Send()
                    
                    print(f"邮件已转发给 {FORWARD_TO}")
                    self.processed_ids.add(entry_id)
            
            except Exception as e:
                print(f"处理邮件时出错: {str(e)}")

if __name__ == "__main__":
    try:
        tracker = OutlookMailTracker()
        tracker.track_new_emails()
    except KeyboardInterrupt:
        print("\n服务已停止")

注意事项

  • 第一次运行时,Outlook会弹出权限提示,需要点击“允许”程序访问邮件
  • 如果需要处理历史邮件(不是新收到的),可以遍历self.inbox.Items,循环检查每封邮件的主题
  • 其他文件夹的ID可以参考Outlook COM文档,比如已发送邮件是5,草稿箱是3

内容的提问来源于stack exchange,提问作者Ben Kennadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:45:25