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

使用Azure Communication Email Python SDK异步发件报错求助

问题分析与解决思路

一、object NoneType can't be used in 'await' expression异常原因

你使用了Azure Communication Email的同步客户端EmailClient,它的begin_send()返回的是同步Poller对象,其wait()方法返回None,而你对None使用了await,因此抛出异常。

二、解决异常并实现真正异步发送的步骤

1. 替换为异步客户端AsyncEmailClient

Azure SDK提供了异步版本的邮件客户端,解决同步Poller的await问题:

  • 导入异步客户端:from azure.communication.aio.email import AsyncEmailClient
  • 使用AsyncEmailClient.from_connection_string()创建客户端,并用异步上下文管理(async with)确保资源正确释放
  • 异步客户端的begin_send()、poller.wait()、poller.result()均为可await方法,不会返回None

2. 修改后的核心代码

from azure.communication.aio.email import AsyncEmailClient
import os
import asyncio

class Email(Configuration):
    def __init__(self):
        super().__init__()
        self.logger_file = 'email_exception.log'

    async def send_mail(self, email_content: dict, email_recipient: str = None):
        print(f" sending email called")
        error = False
        message = "Success"
        recipient_address = email_recipient or os.getenv("RECIPIENT_EMAIL_ADDRESS")

        try:
            content = {
                "senderAddress": sender_address,
                "recipients":  {
                    "to": [{"address": recipient_address}, {"address": recipient_address}],
                    "cc": [{"address": recipient_address}],
                    "bcc": [{"address": recipient_address}]
                },
                "content": email_content
            }
            # 初始化异步客户端并通过async with管理
            async with AsyncEmailClient.from_connection_string(connection_string) as client:
                # 异步触发邮件发送
                poller = await client.begin_send(content)

                time_elapsed = 0
                while not poller.done():
                    await poller.wait(POLLER_WAIT_TIME)
                    time_elapsed += POLLER_WAIT_TIME

                    if time_elapsed > 18 * POLLER_WAIT_TIME:
                        raise RuntimeError("Polling timed out.")

                # 异步获取发送结果
                result = await poller.result()
                if result["status"] == "Succeeded":
                    print(f"Successfully sent the emails (operation id: {result['id']})")
                    return error, message
                else:
                    raise RuntimeError(str(result["error"]))

        except Exception as ex:
            self.logger.error(f"exception was thrown when sending email {str(ex)}")
            error = True
            message = str(ex)
            return error, message

3. 实现真正的异步调用

当前代码修改后,若直接调用await email.send_mail()仍会阻塞主流程。要实现非阻塞的异步发送,需将邮件任务提交到事件循环后台执行:

async def main():
    email = Email()
    email_content = {"subject": "Test", "plainText": "Hello"}
    # 提交后台任务,主流程无需等待发送完成
    asyncio.create_task(email.send_mail(email_content))
    # 执行其他业务逻辑...

asyncio.run(main())

关键注意点

  • 异步客户端必须配合async with使用,避免资源泄漏
  • 多次调用时,用asyncio.create_task可并行执行多个邮件发送任务,大幅提升效率
  • 若需要监听发送结果,可通过asyncio.gather()或任务的result()方法获取,但需注意异常处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:05:33