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

Gmail API无法读取SMTP协议发送的邮件问题咨询

问题描述

通过Python脚本使用SMTP协议发送内容为This is an email test的邮件,在Gmail网页端收件箱中可见,但使用Gmail API读取时无法获取到该邮件;而通过Gmail网页发送相同内容的邮件,API可以正常读取并输出正文。

发送邮件的Python代码

def send_email(subject, body):
            global host, app_password
            msg = MIMEText(body)
            msg['Subject'] = subject
            msg['From'] = host
            msg['To'] = host
            with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp_server:
                smtp_server.login(host, app_password)
                smtp_server.sendmail(host, host, msg.as_string())

读取邮件的Python代码

def get_messages():

    # Verify Credentials and Token 
    creds = None
    if os.path.exists('token.pickle'): 
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)  
    if not creds or not creds.valid: 
        if creds and creds.expired and creds.refresh_token: 
            creds.refresh(Request()) 
        else: 
            flow = InstalledAppFlow.from_client_secrets_file('C:\\my\\path\\to\\credentials\\credentials.json', SCOPES) 
            creds = flow.run_local_server(port=0) 
        with open('token.pickle', 'wb') as token: 
            pickle.dump(creds, token) 
  
    # Connect to the Gmail API 
    service = build('gmail', 'v1', credentials=creds) 
    result = service.users().messages().list(userId='me').execute() 
    messages = result.get('messages') 
  
    # Loop through emails
    try:
        for msg in messages: 
            txt = service.users().messages().get(userId='me', id=msg['id']).execute()  
            payload = txt['payload'] 
            headers = payload['headers']

            # Extract values from data
            for d in headers: 
                if d['name'] == 'Subject': 
                    subject = d['value'] 
                if d['name'] == 'From': 
                    sender = d['value'] 
            parts = payload.get('parts')[0] 
            data = parts['body']['data'] 
            data = data.replace("-","+").replace("_","/") 
            decoded_data = base64.b64decode(data) 
            soup = BeautifulSoup(decoded_data, "lxml") 
            body = soup.body() 

            # Output
            if sender=='Bote <'+host+'>':
                print(subject)
                if subject==code:
                    print(body[4:-5])
        if back==True:
            return
    except:
        pass
问题原因分析
  • 发送者头匹配不匹配:SMTP发送的邮件From头仅为纯邮箱地址(即host变量的值),但读取代码中硬编码判断sender=='Bote <'+host+'>'——只有网页发送的邮件才会附带Bote这个昵称,因此SMTP发送的邮件直接被过滤,无法进入输出逻辑。
  • 邮件结构处理逻辑缺陷:SMTP发送的纯文本邮件(MIMEText构造),Gmail API返回的payload结构中没有parts字段,正文数据直接存储在payload['body']中。但读取代码强行调用payload.get('parts')[0],会触发索引错误,而宽泛的try-except直接跳过了该邮件的处理,没有任何提示。
  • 异常捕获过于宽泛:代码使用try:... except: pass捕获所有异常,导致结构不匹配、变量未定义等错误都被隐藏,无法定位具体问题。
修复方案
  1. 修正发送者判断逻辑
    放弃硬编码昵称,改为匹配邮箱地址本身,示例:

    # 提取sender中的邮箱地址,兼容带昵称和纯邮箱的格式
    import re
    sender_email = re.search(r'<(.+?)>', sender).group(1) if '<' in sender else sender
    if sender_email == host:
        print(subject)
        if subject == code:
            print(body.get_text())  # 改用get_text()获取正文
    

    或者简化判断:

    if host in sender:
        # 后续输出逻辑
    
  2. 兼容不同邮件结构
    处理正文时先判断是否存在parts字段,兼容纯文本和多部件邮件:

    # 读取邮件正文数据
    if 'parts' in payload:
        data = payload['parts'][0]['body']['data']
    else:
        data = payload['body']['data']
    data = data.replace("-","+").replace("_","/")
    decoded_data = base64.b64decode(data)
    soup = BeautifulSoup(decoded_data, "lxml")
    body = soup.get_text()  # 用get_text()替代body(),更稳定获取纯文本内容
    
  3. 优化异常处理
    仅捕获特定异常或打印错误信息,方便调试:

    try:
        # 原有邮件处理逻辑
    except Exception as e:
        print(f"处理邮件ID {msg['id']} 时出错: {str(e)}")
    
  4. 可选:指定收件箱标签
    调用messages().list()时明确指定读取收件箱邮件,避免遗漏:

    result = service.users().messages().list(userId='me', labelIds=['INBOX']).execute()
    

内容的提问来源于stack exchange,提问作者Markas M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:06:17