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

使用Django与win32库发送邮件时出现延迟/队列问题

问题排查:Django+win32 Outlook邮件发送延迟问题

核心问题分析

这种"滞后一封"的延迟现象,本质是Outlook COM对象在多线程请求环境下资源未正确释放,导致邮件发送操作被缓存到Outlook本地队列,而非立即提交到邮件服务器。结合你的代码,主要问题点如下:

  • COM线程模型适配错误:你在请求内部调用pythoncom.CoInitialize(),但Django是多线程服务,Outlook的COM对象要求单线程单元(STA)模型,普通初始化无法匹配,导致线程上下文混乱,邮件暂存本地。
  • COM资源未显式释放:创建的outlook和mail对象未主动销毁,Outlook进程会持续持有这些资源,延迟提交邮件。
  • 潜在的Outlook客户端设置:如果Outlook开启"延迟发送"或处于脱机状态,也会导致邮件堆积在发件箱,同步时才批量发送。

修复方案

1. 调整COM线程初始化方式

使用pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)替代CoInitialize(),强制适配Outlook要求的STA线程模型。

2. 显式释放COM资源

发送完成后主动销毁mail和outlook对象,配合垃圾回收确保资源完全释放。

3. 修复后代码

class ApiSendMailCreateNewReporter(APIView):
    def get(self, request, id_headerRequest):
        outlook = None
        mail = None
        try:
            # 初始化STA线程模型,适配Outlook COM对象要求
            pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
            
            # 原有业务逻辑保留
            header_request = get_object_or_404(HeaderRequest, id=id_headerRequest)
            serializer_header_request = HeaderRequestSerializer(header_request)
            usuario_id = serializer_header_request.data['id_user_id']
            require_date = serializer_header_request.data['require_date']
            customer = serializer_header_request.data['customer']

            engineer_instance = get_object_or_404(Engineers, role='admin')
            engineer_serializer = EnginnerAdminSerializer(engineer_instance)
            admin_email = engineer_serializer.data['email']

            user_instance = get_object_or_404(Users, id=usuario_id)
            serializer_user = UserAccountsSerializer(user_instance)
            full_name = f"{serializer_user.data['first_Name']} {serializer_user.data['last_Name']}"

            dynamic_link = 'xxxxxxxxxxxxxx'

            # 创建Outlook实例
            outlook = win32.Dispatch('Outlook.Application')
            mail = outlook.CreateItem(0)
            mail.SentOnBehalfOfName = 'example@live.com'
            mail.To = admin_email
            mail.Subject = 'NUEVA SOLICITUD DE PRUEBAS DE LABORATORIO'
            html_body = f"""
                <html>
                    <body>
                        <div>
                            <h1>Nueva solicitud de pruebas de laboratorio de {full_name}</h1>
                            <p>El usuario {full_name} ha creado una nueva solicitud de pruebas de laboratorio para el cliente {customer} con una fecha requerida para el {require_date}</p>
                            <a href="{dynamic_link}">
                                Ir al Sitio
                            </a>
                        </div>
                    </body>
                </html>
            """
            mail.HTMLBody = html_body
            mail.Send()

            return Response({"message": "Correo enviado correctamente"}, status=status.HTTP_200_OK)

        except Exception as e:
            print(f"Error: {e}")
            return Response({"message": "Correo NO enviado correctamente"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        finally:
            # 显式销毁COM对象
            if mail:
                del mail
            if outlook:
                del outlook
            # 强制垃圾回收释放资源
            import gc
            gc.collect()
            # 释放COM线程
            pythoncom.CoUninitialize()

4. 额外排查点

  • 检查Outlook客户端:关闭"延迟发送"功能,确保处于联机状态,查看发件箱是否有未发送的邮件堆积。
  • 权限验证:确认Django运行的系统账户已登录过Outlook,且拥有访问邮箱的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:07:49