1. 概述
本方案使用 Python 脚本通过 SMTP 协议发送带有 .ics 日历附件的会议邀请邮件。收件人可在 Outlook、Gmail、Apple Calendar 等客户端中直接点击“接受/拒绝”,自动将事件加入日历。
2. Python 示例代码
安装以下 Python 包:
pip install icalendar pytzimport smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from icalendar import Calendar, Event
from datetime import datetime
import pytz
import uuid
# === 配置区(请用户自行填写)===
SMTP_SERVER = "smtpdm.aliyun.com"
SMTP_PORT = 465 # SSL 端口
SENDER_EMAIL = "your_email@example.com" # 发件人邮箱
SENDER_PASSWORD = "your_app_password" # SMTP 授权码(非登录密码)
RECIPIENT_EMAIL = "recipient@example.com" # 收件人邮箱
# === 创建 iCalendar 事件 ===
cal = Calendar()
cal.add('prodid', '-//Your Organization//Meeting Calendar//EN')
cal.add('version', '2.0')
event = Event()
event.add('summary', "团队周会")
event.add('dtstart', datetime(2026, 3, 11, 15, 0, 0, tzinfo=pytz.timezone('Asia/Shanghai')))
event.add('dtend', datetime(2026, 3, 11, 16, 0, 0, tzinfo=pytz.timezone('Asia/Shanghai')))
event.add('dtstamp', datetime.now(pytz.utc))
event.add('description', "讨论项目进度与下周计划")
event.add('location', "线上会议室 / B301")
event.add('uid', str(uuid.uuid4()) + '@yourdomain.example')
event.add('organizer', f'mailto:{SENDER_EMAIL}')
cal.add_component(event)
ical_data = cal.to_ical()
# === 构建邮件(HTML 正文)===
msg = MIMEMultipart()
msg['From'] = SENDER_EMAIL
msg['To'] = RECIPIENT_EMAIL
msg['Subject'] = '会议邀请:团队周会'
# HTML 格式的邮件正文
html_body = """
<html>
<head></head>
<body>
<h2>会议邀请</h2>
<p>您好!</p>
<p>诚邀您参加以下会议:</p>
<ul>
<li><strong>主题:</strong>团队周会</li>
<li><strong>时间:</strong>2026年3月11日(周二)15:00 - 16:00(北京时间)</li>
<li><strong>地点:</strong>线上会议室 / B301</li>
</ul>
<p>请查收附件中的日历邀请,并点击“接受”以确认出席。</p>
<hr>
<p style="color: #888; font-size: 0.9em;">
此邮件由系统自动发送,请勿直接回复。
</p>
</body>
</html>
"""
# 将 HTML 正文附加到邮件
msg.attach(MIMEText(html_body, 'html')) # ← 关键:使用 'html' 而非 'plain'
# 添加 iCalendar 附件(method=REQUEST 触发日历操作)
part = MIMEApplication(ical_data, _subtype='calendar')
part.add_header('Content-Disposition', 'attachment; filename="meeting_invite.ics"')
part.add_header('Content-Type', 'text/calendar; charset=UTF-8; method=REQUEST')
msg.attach(part)
# === 通过 SSL 发送邮件 ===
try:
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server:
server.set_debuglevel(0) # 生产环境建议关闭调试
server.login(SENDER_EMAIL, SENDER_PASSWORD)
server.sendmail(SENDER_EMAIL, RECIPIENT_EMAIL, msg.as_string())
print("会议邀请(含 HTML 正文)已成功发送!")
except Exception as e:
print(f"发送失败: {e}")
3. 关键配置说明
配置项 | 说明 |
| 邮件服务商的 SMTP 地址 |
| 必须使用 465(SSL),避免明文传输密码 |
| 发件人邮箱(需已在邮件服务商处验证) |
| SMTP 授权码(在邮件控制台生成) |
| 收件人邮箱 |
4. 日历事件字段说明
summary:会议标题dtstart/dtend:开始/结束时间(务必指定时区,推荐Asia/Shanghai)uid:全局唯一 ID(格式:uuid@yourdomain,确保唯一性)organizer:组织者邮箱method=REQUEST:必须设置,否则客户端不会显示操作按钮
5. 效果展示
邮件:

日历:

5. 常见问题
Q1: 收件人看不到“接受/拒绝”按钮?
确保邮件头包含:
Content-Type: text/calendar; method=REQUESTuid必须全局唯一且含域名避免使用别名(如
xxx+tag@example.com)作为 organizer
Q2: SMTP 连接失败?
检查是否使用 465 端口 + SMTP_SSL
确认发信地址已在 阿里云邮件推送控制台 添加并验证
检查授权码是否正确
Q3: 时间显示错误?
所有
datetime对象必须带时区(使用pytz.timezone('Asia/Shanghai'))避免混合使用
datetime.utcnow()和本地时间
该文章对您有帮助吗?