邮件通知Hook:邮件自动化发送

自动化邮件通知发送

一、邮件通知Hook的设计

邮件通知Hook是Claude Code Hooks体系中最常用的通信类Hook之一,其核心作用是在特定事件发生后自动触发邮件发送,将关键信息及时推送到相关人员手中。与轮询式检查不同,邮件Hook采用事件驱动模型,只在真正需要时发送邮件,既避免了信息过载,又确保了重要通知的及时送达。

邮件通知Hook适用于多种场景:构建部署状态变更通知、代码审查请求与结果通知、定时汇总报告(周报/月报)、异常与错误告警、审批流程通知等。通过合理设计邮件模板和触发条件,可以构建一套完整的自动化通知体系。

事件驱动
基于Claude Code Hook系统,在after/before事件触发时自动执行邮件发送脚本
多协议支持
支持SMTP协议直连发送、系统mail命令、sendmail命令等多种发送方式
模板引擎
内置邮件模板管理,支持HTML富文本格式,不同事件类型使用差异化模板
多收件人
支持单发、群发、动态收件人列表,灵活适配团队协作场景

设计原则:邮件通知Hook应遵循"必要、及时、可读"三大原则。必要指只在关键事件发生时发送;及时指邮件应在事件发生后尽快送达;可读指邮件内容结构化、重点突出、方便阅读。

二、邮件发送配置

邮件通知Hook的底层依赖邮件发送通道的配置。Claude Code本身不内置邮件发送功能,而是通过Hook脚本调用系统命令或第三方库来实现。常用的发送方式有三种:SMTP协议直连、系统mail命令、Python smtplib库。

2.1 配置SMTP服务器参数

SMTP(Simple Mail Transfer Protocol)是邮件发送的核心协议。配置SMTP需要准备以下参数:SMTP服务器地址和端口、发件人邮箱地址和授权密码(或API密钥)、SSL/TLS加密方式。常见邮件服务商的SMTP配置如下:

邮件服务商SMTP服务器SSL端口TLS端口
Gmailsmtp.gmail.com465587
QQ邮箱smtp.qq.com465587
163邮箱smtp.163.com465587
Outlooksmtp-mail.outlook.com465587
企业微信邮箱smtp.exmail.qq.com465587

为提高安全性,建议将SMTP配置存入环境变量而非直接写在脚本中:

# 在 ~/.bashrc 或 .env 文件中配置 export SMTP_SERVER="smtp.qq.com" export SMTP_PORT="465" export SMTP_USER="your@email.com" export SMTP_PASS="your-authorization-code" export NOTIFY_TO="team@example.com"

2.2 使用mail/sendmail命令发送

Linux系统自带的mail命令是最轻量的发送方式,适合快速集成。安装方法:

# Ubuntu/Debian sudo apt-get install -y mailutils # CentOS/RHEL sudo yum install -y mailx

配置系统mail发送(/etc/mail.rc 或 ~/.mailrc):

set smtp=smtps://smtp.qq.com:465 set smtp-auth=login set smtp-auth-user=your@email.com set smtp-auth-password=your-authorization-code set ssl-verify=ignore

Hook脚本中使用mail命令发送邮件:

#!/bin/bash # mail-notify.sh - 邮件通知Hook脚本 SUBJECT="[Claude Code] 构建通知 - $(date +'%Y-%m-%d %H:%M')" TO="team@example.com" # 构建邮件正文 BODY="项目构建状态:${BUILD_STATUS} 构建时间:$(date) 构建版本:${VERSION} 提交信息:${COMMIT_MESSAGE} 详情请查看:${BUILD_URL}" # 发送邮件 echo "$BODY" | mail -s "$SUBJECT" "$TO"

2.3 使用Python smtplib发送

Python的smtplib库提供了更灵活的邮件发送能力,支持HTML格式、附件、多收件人等高级功能。

#!/usr/bin/env python3 # smtp_notify.py - Python SMTP邮件发送脚本 import os import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header def send_email(subject, html_body, to_list): smtp_server = os.environ.get('SMTP_SERVER', 'smtp.qq.com') smtp_port = int(os.environ.get('SMTP_PORT', '465')) smtp_user = os.environ.get('SMTP_USER', '') smtp_pass = os.environ.get('SMTP_PASS', '') from_addr = smtp_user msg = MIMEMultipart('alternative') msg['From'] = Header(from_addr) msg['To'] = ', '.join(to_list) msg['Subject'] = Header(subject, 'utf-8') # 纯文本备用内容 text_part = MIMEText('请使用支持HTML的邮件客户端查看', 'plain', 'utf-8') msg.attach(text_part) # HTML正文 html_part = MIMEText(html_body, 'html', 'utf-8') msg.attach(html_part) try: with smtplib.SMTP_SSL(smtp_server, smtp_port) as server: server.login(smtp_user, smtp_pass) server.sendmail(from_addr, to_list, msg.as_string()) print(f"邮件发送成功: {subject}") except Exception as e: print(f"邮件发送失败: {e}") raise if __name__ == '__main__': send_email('测试邮件', '<h1>Hello</h1><p>这是一封测试邮件</p>', ['dev@example.com'])

2.4 支持HTML格式邮件模板

HTML格式邮件可以大幅提升可读性。建议使用简单的内联样式HTML模板,避免依赖外部CSS文件(邮件客户端通常会剥离外部样式)。

HTML_TEMPLATE = ''' <!DOCTYPE html> <html> <head><meta charset="utf-8"></head> <body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background: #f5f5f5;"> <div style="background: white; border-radius: 8px; padding: 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"> <h2 style="color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px;"> {title} </h2> <p style="color: #555; line-height: 1.6;"> {content} </p> <div style="background: #f8f9fa; border-left: 4px solid #3498db; padding: 15px; margin: 15px 0;"> {details} </div> <p style="color: #999; font-size: 12px; text-align: center; margin-top: 20px;"> 本邮件由 Claude Code Hooks 自动发送 </p> </div> </body> </html> '''
提示:使用Python脚本的优势在于可以灵活控制邮件格式、添加附件、嵌入图片(CID方式),以及动态构建复杂邮件内容。推荐将邮件发送逻辑封装为独立的Python模块,在各Hook脚本中复用。

三、构建/部署状态邮件Hook(after)

构建/部署状态邮件是CI/CD流程中最重要的通知类型之一。通过在Claude Code的after事件Hook中插入邮件发送逻辑,可以在每次构建或部署完成后自动通知相关人员。

3.1 构建完成后自动发送状态邮件

在Hook配置中注册after事件,构建脚本执行完毕后触发邮件通知:

{ "hooks": { "after": [ { "match": "build:*", "command": "bash hooks/build-notify.sh" } ] } }
#!/bin/bash # hooks/build-notify.sh - 构建状态通知Hook BUILD_STATUS=$? # 获取上一条命令的退出状态码 PROJECT_NAME=$(basename $(pwd)) BUILD_TIME=$(date '+%Y-%m-%d %H:%M:%S') COMMIT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") if [ $BUILD_STATUS -eq 0 ]; then STATUS_ICON="✅" STATUS_TEXT="成功" COLOR="green" else STATUS_ICON="❌" STATUS_TEXT="失败" COLOR="red" fi SUBJECT="${STATUS_ICON} [${PROJECT_NAME}] 构建${STATUS_TEXT} - ${BRANCH}@${COMMIT_HASH}" # 使用Python脚本发送HTML格式邮件 python3 hooks/send_build_email.py \ --subject "$SUBJECT" \ --project "$PROJECT_NAME" \ --status "$STATUS_TEXT" \ --branch "$BRANCH" \ --commit "$COMMIT_HASH" \ --time "$BUILD_TIME" \ --exit-code $BUILD_STATUS

3.2 包含构建环境和版本信息

邮件正文应包含充分的上下文信息,方便接收者快速了解构建情况。建议包含以下字段:项目名称、构建版本号、代码分支和提交哈希、构建触发者、构建持续时长、构建环境(测试/预发/生产)、构建产物下载链接(如有)。

def build_status_email(project, status, branch, commit, build_time, duration, trigger, environment, artifacts_url): """构建状态邮件HTML生成""" color = "#27ae60" if status == "成功" else "#e74c3c" icon = "✅" if status == "成功" else "❌" html = f''' <h2 style="color: {color};">{icon} {project} 构建{status}</h2> <table style="width:100%; border-collapse: collapse;"> <tr><td style="padding:8px; font-weight:bold;">版本</td> <td style="padding:8px;">{commit}</td></tr> <tr><td style="padding:8px; font-weight:bold;">分支</td> <td style="padding:8px;">{branch}</td></tr> <tr><td style="padding:8px; font-weight:bold;">构建时间</td> <td style="padding:8px;">{build_time}</td></tr> <tr><td style="padding:8px; font-weight:bold;">耗时</td> <td style="padding:8px;">{duration}s</td></tr> <tr><td style="padding:8px; font-weight:bold;">触发者</td> <td style="padding:8px;">{trigger}</td></tr> <tr><td style="padding:8px; font-weight:bold;">环境</td> <td style="padding:8px;">{environment}</td></tr> </table> <p><a href="{artifacts_url}" style="background: #3498db; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;"> 查看构建详情 &rarr;</a></p> ''' return html

3.3 添加构建日志链接

构建日志链接是故障排查的关键入口。建议在邮件中同时提供构建日志URL和构建产物下载链接。如果使用Jenkins、GitLab CI或GitHub Actions,可以直接集成其API获取构建详情页地址。

注意:构建失败邮件应包含错误日志的关键片段(如编译错误的前10行),帮助开发者快速定位问题,不必登录CI系统即可了解大致原因。但要注意避免在邮件中泄露敏感信息(如密码、Token等)。

3.4 成功/失败的不同邮件模板

构建成功和失败的邮件应当使用差异化的模板,突出各自关注的重点信息:

成功模板
绿色主题,突出版本号、产物链接、部署说明,鼓励团队成员更新使用
失败模板
红色主题,突出错误摘要、失败步骤、日志链接、建议操作,推动快速修复

四、代码审查请求邮件Hook

代码审查(Code Review)是保证代码质量的重要环节。通过邮件通知Hook,可以在PR/MR创建时自动发送审查请求邮件,并跟踪审查进度。

4.1 PR/MR创建时自动发送审查请求邮件

在Git平台Webhook或Claude Code的特定事件中注册Hook,当PR/MR创建时自动触发:

#!/bin/bash # review-request.sh - 代码审查请求通知Hook # 从环境变量或参数获取PR信息 PR_TITLE="${1}" PR_URL="${2}" PR_AUTHOR="${3}" PR_DESCRIPTION="${4}" CHANGED_FILES="${5}" REVIEWERS="${6}" SUBJECT="[Code Review] ${PR_TITLE} - 来自 ${PR_AUTHOR}" python3 hooks/send_review_email.py \ --subject "$SUBJECT" \ --title "$PR_TITLE" \ --url "$PR_URL" \ --author "$PR_AUTHOR" \ --description "$PR_DESCRIPTION" \ --files "$CHANGED_FILES" \ --reviewers "$REVIEWERS" \ --deadline "$(date -d '+2 days' '+%Y-%m-%d')"

4.2 包含变更摘要和文件列表

审查请求邮件应包含足够的上下文信息,帮助审查者快速了解变更范围:

def review_request_email(title, url, author, description, files, additions, deletions): """审查请求邮件HTML生成""" file_rows = ''.join( f'<tr><td>{f["name"]}</td>' f'<td style="color:#27ae60;">+{f["additions"]}</td>' f'<td style="color:#e74c3c;">-{f["deletions"]}</td></tr>' for f in files ) html = f''' <h2>📝 代码审查请求</h2> <h3>{title}</h3> <p>作者:{author} &nbsp;|&nbsp; 变更:+{additions}/-{deletions} 行</p> <hr> <h4>变更描述</h4> <p>{description}</p> <h4>变更文件({len(files)} 个)</h4> <table style="width:100%; border-collapse: collapse;"> <tr style="background:#f0f0f0;"> <th>文件名</th><th>新增</th><th>删除</th> </tr> {file_rows} </table> <p style="margin-top:20px;"> <a href="{url}" style="background:#3498db; color:white; padding:10px 20px; text-decoration:none; border-radius:5px;"> 前往审查 &rarr; </a> </p> ''' return html

4.3 设置审查截止日期

为审查设置合理的截止日期有助于推动审查流程。建议在邮件中明确标注截止时间,并在截止时间前发送提醒邮件。提醒逻辑可通过定时任务(cron)配合Claude Code Hook实现。

最佳实践:小型变更(<100行)的审查截止时间建议为1个工作日内;中型变更(100-500行)为2个工作日内;大型变更(>500行)建议拆分审查,每个部分的截止时间为2个工作日内。

4.4 Review完成后发送确认邮件

代码审查完成后(approve或merge),应通知相关方。对PR作者而言,确认变更已合并;对其他团队成员而言,了解代码库的最新变更。

#!/bin/bash # review-complete.sh - 审查完成通知Hook REVIEW_ACTION="${1}" # approved / changes-requested / merged PR_TITLE="${2}" PR_AUTHOR="${3}" REVIEWER="${4}" PR_URL="${5}" case "$REVIEW_ACTION" in "approved") SUBJECT="✅ [已批准] ${PR_TITLE}" ;; "changes-requested") SUBJECT="🔄 [需修改] ${PR_TITLE}" ;; "merged") SUBJECT="🎉 [已合并] ${PR_TITLE}" ;; esac python3 hooks/send_review_complete.py \ --subject "$SUBJECT" \ --action "$REVIEW_ACTION" \ --pr-title "$PR_TITLE" \ --author "$PR_AUTHOR" \ --reviewer "$REVIEWER" \ --url "$PR_URL"

五、定时报告邮件Hook

定时报告(周报/月报)是团队管理和项目进度跟踪的重要手段。结合Claude Code Hook与系统定时任务(cron),可以自动汇总开发数据并生成结构化报告邮件。

5.1 自动汇总周/月工作成果

通过cron定时触发Hook脚本,自动收集指定时间范围内的开发数据:

# crontab - 定时触发报告生成 # 每周一上午9点发送上周周报 0 9 * * 1 cd /path/to/project && bash hooks/weekly-report.sh # 每月1日上午10点发送上月月报 0 10 1 * * cd /path/to/project && bash hooks/monthly-report.sh
#!/bin/bash # weekly-report.sh - 周报生成与发送Hook REPORT_TYPE="${1:-weekly}" DATE_RANGE="${2:-last-week}" echo "正在生成${REPORT_TYPE}报告..." # 执行Python报告生成脚本 python3 hooks/generate_report.py \ --type "$REPORT_TYPE" \ --range "$DATE_RANGE" \ --output /tmp/report.html # 发送邮件 python3 hooks/send_report_email.py \ --subject "[周报] 项目进度报告 - $(date +'%Y-%m-%d')" \ --html /tmp/report.html \ --to-list "manager@example.com,team@example.com"

5.2 包含Git统计和Issue进度

报告邮件应包含以下核心数据维度:

def generate_git_stats(repo_path, since_date): """获取指定时间范围内的Git统计数据""" import subprocess from datetime import datetime, timedelta # 获取提交数量 result = subprocess.run( ['git', 'log', f'--since={since_date}', '--oneline', '--no-merges'], capture_output=True, text=True, cwd=repo_path ) commits = result.stdout.strip().split('\n') commit_count = len([c for c in commits if c]) # 获取代码变更行数 result = subprocess.run( ['git', 'log', f'--since={since_date}', '--stat', '--no-merges'], capture_output=True, text=True, cwd=repo_path ) additions = 0 deletions = 0 for line in result.stdout.split('\n'): if 'insertion' in line or 'additions' in line: parts = line.split(',') for part in parts: if 'insertion' in part or 'additions' in part: additions += int(part.strip().split()[0]) elif 'deletion' in part or 'deletions' in part: deletions += int(part.strip().split()[0]) # 获取参与人数 result = subprocess.run( ['git', 'log', f'--since={since_date}', '--format=%aE', '--no-merges'], capture_output=True, text=True, cwd=repo_path ) authors = set(result.stdout.strip().split('\n')) return { 'commit_count': commit_count, 'author_count': len(authors), 'additions': additions, 'deletions': deletions, }

5.3 支持多收件人分发

报告邮件通常需要发送给多个收件人或邮件组。支持灵活的收件人配置方式:

# config/email_recipients.yaml - 收件人配置 # 周报收件人 weekly: to: - "manager@example.com" - "team-leads@example.com" cc: - "team@example.com" bcc: - "archive@example.com" # 月报收件人(包含管理层) monthly: to: - "manager@example.com" - "vp@example.com" cc: - "team@example.com" bcc: - "archive@example.com" - "stakeholders@example.com" # 构建通知(动态收件人) build_notify: to: "{{trigger_author}}@example.com" cc: "devops@example.com"

在Python脚本中读取YAML配置并发送:

import yaml import os def load_recipients(report_type='weekly'): config_path = os.path.join( os.path.dirname(__file__), 'config', 'email_recipients.yaml' ) with open(config_path, 'r') as f: config = yaml.safe_load(f) return config.get(report_type, {}) def send_report(subject, html_body, report_type='weekly'): recipients = load_recipients(report_type) to_list = recipients.get('to', []) cc_list = recipients.get('cc', []) bcc_list = recipients.get('bcc', []) # 构建邮件 msg = MIMEMultipart('mixed') msg['To'] = ', '.join(to_list) msg['Cc'] = ', '.join(cc_list) msg['Subject'] = Header(subject, 'utf-8') html_part = MIMEText(html_body, 'html', 'utf-8') msg.attach(html_part) # 发送(包括CC和BCC) all_recipients = to_list + cc_list + bcc_list with smtplib.SMTP_SSL(smtp_server, smtp_port) as server: server.login(smtp_user, smtp_pass) server.sendmail(from_addr, all_recipients, msg.as_string())

5.4 邮件模板可定制化

为不同类型的报告设计独立的HTML模板,支持通过配置文件切换:

# config/email_templates.yaml - 邮件模板配置 templates: weekly: subject: "[周报] {{project}} 进度报告 {{date}}" header_color: "#3498db" sections: - name: git_stats title: "Git提交统计" enabled: true - name: issue_progress title: "Issue进度" enabled: true - name: review_status title: "代码审查状态" enabled: true - name: build_status title: "构建/部署状态" enabled: false monthly: subject: "[月报] {{project}} 月度总结 {{date}}" header_color: "#9b59b6" sections: - name: git_stats title: "Git提交统计" enabled: true - name: issue_progress title: "Issue进度" enabled: true - name: review_status title: "代码审查状态" enabled: true - name: build_status title: "构建/部署状态" enabled: true - name: performance title: "性能指标" enabled: true - name: team_health title: "团队健康度" enabled: false

核心要点总结:邮件通知Hook是Claude Code Hooks体系中的关键组件,通过合理配置SMTP参数、设计差异化邮件模板、灵活支持多收件人分发,可以实现构建状态通知、代码审查请求、定时报告邮件等场景的全面自动化。邮件发送的核心在于可靠性,建议同时配置主备邮件通道,并加入发送失败的重试机制和告警通知,确保关键信息不丢失。