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

Python发送邮件至Outlook带!前缀通讯组列表失效问题咨询

问题根源

你看到的带!前缀的通讯组地址不是标准SMTP协议支持的合法邮箱地址,这是Outlook客户端对Exchange通讯组做的本地别名展示,仅能在Outlook客户端界面内被解析,SMTP服务器根本识别不了这种带特殊前缀的地址,直接传当然会发送失败。

另外你现有代码本身还有个隐藏bug:

recipients = ['someone@company.com, someonelse@company.com'] 
emaillist = [elem.strip().split(',') for elem in recipients]

这段逻辑生成的emaillist是嵌套列表[['someone@company.com', 'someonelse@company.com']],而smtplib.SMTP.sendmail()要求收件人参数是一维字符串列表,之前发个人邮箱没报错只是巧合,必须先修正这个逻辑。


解决方案

按优先级从高到低试:

方案1:使用通讯组的真实SMTP地址(90%场景可用)

公司IT维护的所有Exchange通讯组,都有一个不带!前缀的标准SMTP投递地址,通常就是你看到的别名去掉开头的!,比如!groupdept@company.com对应的真实地址一般是groupdept@company.com。

  • 验证方法:手动在Outlook里给这个带!的组发一封测试邮件,发完打开已发送文件夹里的这封邮件,查看原始邮件头/收件人字段的真实地址,就能拿到不带!的标准投递地址,直接把这个地址放到收件人列表里即可。

方案2:修正SMTP认证逻辑

如果用真实地址还是发失败,大概率是通讯组开启了发信权限限制,只允许公司域内认证用户发送,你现在用25端口匿名连接的方式会被拒。改成587端口配合STARTTLS加密、用你的公司域账号认证后再发即可,修正后的完整代码参考:

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib

# 配置项
subject = "Group Email"
from_addr = 'me@company.com'
email_pwd = '你的公司邮箱密码'  # 域账号一般直接用域登录密码即可
smtp_server = '你的公司SMTP服务器地址'
smtp_port = 587
# 这里填拿到的真实通讯组地址,不要带!前缀
recipients = ['groupdept@company.com']

msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = from_addr
msg['To'] = ','.join(recipients)  # 邮件头里的收件人字段需要拼接为字符串

html = """\
<html>
<head>
</head>
<body style="font-size:18px;">
{0}
</body>
</html>
""".format(df2.style
       .set_properties(**{'border': '2.5pt solid green', 'color': 'magenta', 'font-size': '15pt'})
       .hide_index()
       .hide_columns()
       .render()
      )
message = MIMEText(html, 'html')
msg.attach(message)

# 带认证的SMTP连接
try:
    server = smtplib.SMTP(smtp_server, smtp_port)
    server.starttls()  # 开启加密传输
    server.login(from_addr, email_pwd)
    server.sendmail(from_addr, recipients, msg.as_string())
    server.quit()
    print("发送成功")
except Exception as e:
    print(f"发送失败: {str(e)}")

方案3:走Exchange原生协议发送

如果你们公司的通讯组没开放SMTP投递权限,就不要用smtplib了,换两种原生支持Exchange的方式:

  • 如果你跑代码的机器装了桌面版Outlook客户端,直接用pywin32库调用本地Outlook的COM接口发信,这种方式和手动在Outlook里发信逻辑完全一致,可以直接识别!开头的通讯组别名。
  • 如果是无界面的服务器场景,用exchangelib库直连公司Exchange EWS接口,用域账号认证后发信,同样支持直接解析Exchange通讯组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:16:20