关于 NotifyHub — Unified Notification MCP Server
NotifyHub 是供 Java 和 Spring Boot 应用使用的统一通知库。其流式 API 支持多种渠道,并提供回退、重试、定时发送和跟踪等投递控制。
主要功能
- 01统一 API 支持文档列出的 23 种渠道
- 02回退链与多渠道发送
- 03异步投递、重试和定时发送
- 04Mustache 模板与语言环境解析
- 05速率限制、去重和投递跟踪
- 06管理面板与死信队列
适用场景
- 01通过首选渠道发送订单更新,并在失败时回退
- 02定时发送提醒并跟踪投递回执
- 03通过死信队列管理失败通知
MCP 相关
项目包含面向 AI Agent 的 MCP 服务;README 提到此集成,但未说明其提供的工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e NOTIFY_CHANNELS_EMAIL_HOST -e NOTIFY_CHANNELS_EMAIL_PORT -e NOTIFY_CHANNELS_EMAIL_USERNAME -e NOTIFY_CHANNELS_EMAIL_PASSWORD -e NOTIFY_CHANNELS_EMAIL_FROM -e NOTIFY_CHANNELS_SMS_ACCOUNTSID -e NOTIFY_CHANNELS_SMS_AUTHTOKEN -e NOTIFY_CHANNELS_SMS_FROMNUMBER -e NOTIFY_CHANNELS_SLACK_WEBHOOKURL -e NOTIFY_CHANNELS_TELEGRAM_BOTTOKEN -e NOTIFY_CHANNELS_TELEGRAM_CHATID -e NOTIFY_CHANNELS_DISCORD_WEBHOOKURL -e NOTIFY_CHANNELS_TEAMS_WEBHOOKURL -e NOTIFY_CHANNELS_GOOGLECHAT_WEBHOOKURL -e NOTIFY_CHANNELS_TWITTER_APIKEY -e NOTIFY_CHANNELS_TWITTER_APISECRET -e NOTIFY_CHANNELS_TWITTER_ACCESSTOKEN -e NOTIFY_CHANNELS_TWITTER_ACCESSTOKENSECRET -e NOTIFY_CHANNELS_LINKEDIN_ACCESSTOKEN -e NOTIFY_CHANNELS_LINKEDIN_ORGANIZATIONID -e NOTIFY_CHANNELS_WHATSAPP_ACCOUNTSID -e NOTIFY_CHANNELS_WHATSAPP_AUTHTOKEN -e NOTIFY_CHANNELS_WHATSAPP_FROMNUMBER -e NOTIFY_CHANNELS_PUSH_FIREBASECREDENTIALS -e NOTIFY_CHANNELS_NOTION_APIKEY -e NOTIFY_CHANNELS_NOTION_DATABASEID -e NOTIFY_CHANNELS_TWITCH_CLIENTID -e NOTIFY_CHANNELS_TWITCH_CLIENTSECRET -e NOTIFY_CHANNELS_TWITCH_BROADCASTERID -e NOTIFY_CHANNELS_YOUTUBE_CLIENTID -e NOTIFY_CHANNELS_YOUTUBE_CLIENTSECRET -e NOTIFY_CHANNELS_YOUTUBE_REFRESHTOKEN -e NOTIFY_CHANNELS_YOUTUBE_LIVECHATID -e NOTIFY_CHANNELS_INSTAGRAM_ACCESSTOKEN -e NOTIFY_CHANNELS_INSTAGRAM_USERID -e NOTIFY_CHANNELS_SENDGRID_APIKEY -e NOTIFY_CHANNELS_SENDGRID_FROMEMAIL -e NOTIFY_CHANNELS_TIKTOKSHOP_APPKEY -e NOTIFY_CHANNELS_TIKTOKSHOP_APPSECRET -e NOTIFY_CHANNELS_TIKTOKSHOP_ACCESSTOKEN -e NOTIFY_CHANNELS_TIKTOKSHOP_SHOPID -e NOTIFY_CHANNELS_FACEBOOK_PAGEACCESSTOKEN -e NOTIFY_CHANNELS_FACEBOOK_PAGEID -e NOTIFY_CHANNELS_AWSSNS_ACCESSKEYID -e NOTIFY_CHANNELS_AWSSNS_SECRETACCESSKEY -e NOTIFY_CHANNELS_AWSSNS_REGION -e NOTIFY_CHANNELS_MAILGUN_APIKEY -e NOTIFY_CHANNELS_MAILGUN_DOMAIN -e NOTIFY_CHANNELS_MAILGUN_FROMEMAIL -e NOTIFY_CHANNELS_PAGERDUTY_APIKEY ghcr.io/gabrielbbaldez/notify-hub:1.1.0NOTIFY_CHANNELS_EMAIL_HOSTSMTP server host for email notificationsNOTIFY_CHANNELS_EMAIL_PORTSMTP server portNOTIFY_CHANNELS_EMAIL_USERNAME密钥SMTP authentication usernameNOTIFY_CHANNELS_EMAIL_PASSWORD密钥SMTP authentication passwordNOTIFY_CHANNELS_EMAIL_FROMDefault sender email addressNOTIFY_CHANNELS_SMS_ACCOUNTSID密钥Twilio Account SID for SMSNOTIFY_CHANNELS_SMS_AUTHTOKEN密钥Twilio Auth Token for SMSNOTIFY_CHANNELS_SMS_FROMNUMBERTwilio sender phone numberNOTIFY_CHANNELS_SLACK_WEBHOOKURL密钥Slack incoming webhook URLNOTIFY_CHANNELS_TELEGRAM_BOTTOKEN密钥Telegram Bot API tokenNOTIFY_CHANNELS_TELEGRAM_CHATIDTelegram chat/group IDNOTIFY_CHANNELS_DISCORD_WEBHOOKURL密钥Discord webhook URLNOTIFY_CHANNELS_TEAMS_WEBHOOKURL密钥Microsoft Teams webhook URLNOTIFY_CHANNELS_GOOGLECHAT_WEBHOOKURL密钥Google Chat webhook URLNOTIFY_CHANNELS_TWITTER_APIKEY密钥Twitter/X API keyNOTIFY_CHANNELS_TWITTER_APISECRET密钥Twitter/X API secretNOTIFY_CHANNELS_TWITTER_ACCESSTOKEN密钥Twitter/X access tokenNOTIFY_CHANNELS_TWITTER_ACCESSTOKENSECRET密钥Twitter/X access token secretNOTIFY_CHANNELS_LINKEDIN_ACCESSTOKEN密钥LinkedIn OAuth2 access tokenNOTIFY_CHANNELS_LINKEDIN_ORGANIZATIONIDLinkedIn organization/company IDNOTIFY_CHANNELS_WHATSAPP_ACCOUNTSID密钥Twilio Account SID for WhatsAppNOTIFY_CHANNELS_WHATSAPP_AUTHTOKEN密钥Twilio Auth Token for WhatsAppNOTIFY_CHANNELS_WHATSAPP_FROMNUMBERWhatsApp sender number (with whatsapp: prefix)NOTIFY_CHANNELS_PUSH_FIREBASECREDENTIALS密钥Firebase Cloud Messaging credentials JSON (base64 or path)NOTIFY_CHANNELS_NOTION_APIKEY密钥Notion integration API keyNOTIFY_CHANNELS_NOTION_DATABASEIDNotion database IDNOTIFY_CHANNELS_TWITCH_CLIENTID密钥Twitch application client IDNOTIFY_CHANNELS_TWITCH_CLIENTSECRET密钥Twitch application client secretNOTIFY_CHANNELS_TWITCH_BROADCASTERIDTwitch broadcaster/channel IDNOTIFY_CHANNELS_YOUTUBE_CLIENTID密钥YouTube/Google OAuth2 client IDNOTIFY_CHANNELS_YOUTUBE_CLIENTSECRET密钥YouTube/Google OAuth2 client secretNOTIFY_CHANNELS_YOUTUBE_REFRESHTOKEN密钥YouTube/Google OAuth2 refresh tokenNOTIFY_CHANNELS_YOUTUBE_LIVECHATIDYouTube Live Chat IDNOTIFY_CHANNELS_INSTAGRAM_ACCESSTOKEN密钥Instagram Graph API access tokenNOTIFY_CHANNELS_INSTAGRAM_USERIDInstagram Business account user IDNOTIFY_CHANNELS_SENDGRID_APIKEY密钥SendGrid API key for email delivery with trackingNOTIFY_CHANNELS_SENDGRID_FROMEMAILSendGrid sender email addressNOTIFY_CHANNELS_TIKTOKSHOP_APPKEY密钥TikTok Shop application keyNOTIFY_CHANNELS_TIKTOKSHOP_APPSECRET密钥TikTok Shop application secretNOTIFY_CHANNELS_TIKTOKSHOP_ACCESSTOKEN密钥TikTok Shop access tokenNOTIFY_CHANNELS_TIKTOKSHOP_SHOPIDTikTok Shop IDNOTIFY_CHANNELS_FACEBOOK_PAGEACCESSTOKEN密钥Facebook Page access tokenNOTIFY_CHANNELS_FACEBOOK_PAGEIDFacebook Page IDNOTIFY_CHANNELS_AWSSNS_ACCESSKEYID密钥AWS access key ID for SNSNOTIFY_CHANNELS_AWSSNS_SECRETACCESSKEY密钥AWS secret access key for SNSNOTIFY_CHANNELS_AWSSNS_REGIONAWS region for SNS (e.g., us-east-1)NOTIFY_CHANNELS_MAILGUN_APIKEY密钥Mailgun API keyNOTIFY_CHANNELS_MAILGUN_DOMAINMailgun sending domainNOTIFY_CHANNELS_MAILGUN_FROMEMAILMailgun sender email addressNOTIFY_CHANNELS_PAGERDUTY_APIKEY密钥PagerDuty Events API v2 integration key本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/gabrielbbaldez/notify-hub:1.1.0stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
NotifyHub
一个 API,覆盖所有渠道。
适用于 Java 和 Spring Boot 的统一通知库。
别再为每个通知渠道编写不同的代码。NotifyHub 为你提供统一、流畅的 API,可通过 Email、SMS、WhatsApp、Slack、Telegram、Discord、Microsoft Teams、Firebase Push、Webhooks、WebSocket、Google Chat、Twitter/X、LinkedIn、Notion、Twitch、YouTube、Instagram、SendGrid、TikTok Shop、Facebook、AWS SNS、Mailgun、PagerDuty、Kick 或你创建的任何自定义渠道发送通知。
notify.to(user)
.via(EMAIL)
.fallback(SMS)
.priority(Priority.HIGH)
.subject("Order confirmed")
.template("order-confirmed")
.param("orderId", order.getId())
.attach(invoicePdf)
.send();
为什么选择 NotifyHub?
| 问题 | 不使用 NotifyHub | 使用 NotifyHub | |
|---|---|---|---|
| 电子邮件 | 配置 JavaMail、MIME 类型、Session…… | .via(EMAIL) | |
| 📱 | 短信 | Twilio SDK,完全不同的 API | .via(SMS) |
| 另一套 Twilio 配置、前缀逻辑 | .via(WHATSAPP) | ||
| Slack | Webhook HTTP、JSON 负载 | .via(SLACK) | |
| Telegram | Bot API、HTTP 客户端配置 | .via(TELEGRAM) | |
| Discord | Webhook HTTP、JSON 负载 | .via(DISCORD) | |
| 👥 | Teams | Incoming Webhook、MessageCard JSON | .via(TEAMS) |
| 推送 | Firebase Admin SDK、凭据…… | .via(PUSH) | |
| 🔗 | Webhook | 自定义 HTTP、负载模板 | .via(Channel.custom("pagerduty")) |
| WebSocket | Java WebSocket API、重连逻辑 | .via(WEBSOCKET) | |
| Google Chat | Webhook HTTP、JSON 负载 | .via(GOOGLE_CHAT) | |
| Twitter/X | OAuth 1.0a、API v2 配置 | .via(TWITTER) | |
| 💼 | OAuth 2.0、REST API 配置 | .via(LINKEDIN) | |
| Notion | Integration Token、API 配置 | .via(NOTION) | |
| Twitch | OAuth 2.0、Twitch API 配置 | .via(TWITCH) | |
| YouTube | YouTube Data API v3 配置 | .via(YOUTUBE) | |
| Meta Graph API 配置 | .via(INSTAGRAM) | ||
| 📧 | SendGrid | SendGrid API、Webhook 跟踪 | .via(Channel.custom("sendgrid")) |
| TikTok Shop | HMAC-SHA256、Shop API | .via(TIKTOK_SHOP) | |
| Graph API、页面令牌 | .via(FACEBOOK) | ||
| ☁️ | AWS SNS | AWS SDK、凭据、ARN | .via(Channel.custom("aws-sns")) |
| Mailgun | Mailgun API、域名配置 | .via(Channel.custom("mailgun")) | |
| PagerDuty | Events API v2、路由密钥 | .via(Channel.custom("pagerduty")) | |
| Kick | 公共 API、OAuth 2.1 | .via(KICK) | |
| 多个渠道 | 每个渠道的代码都完全不同 | 相同的流畅 API | |
| 回退 | 手动编写 try/catch 链 | .fallback(SMS) | |
| 重试 | 自行实现 | 内置指数退避 | |
| 异步 | 线程池、CompletableFuture | .sendAsync() | |
| 调度 | ScheduledExecutor、计时器逻辑 | .schedule(Duration.ofMinutes(30)) | |
| 模板 | 每个渠道都有自己的引擎 | 一个模板适用于所有渠道 | |
| i18n | 手动解析区域设置 | .locale(Locale.PT_BR) | |
| 速率限制 | 从头实现令牌桶 | 由配置驱动,按渠道设置 | |
| 跟踪 | 自行构建投递日志 | 内置回执 + JPA | |
| 死信 | 消息消失无踪 | 自动捕获到 DLQ | |
| 去重 | 自行跟踪已发送的消息 | 内置内容哈希 / 显式键 | |
| 模板版本 | 手动管理文件 | .templateVersion("v2") + A/B 测试 | |
| 批量处理 | 循环发送,祈祷成功 | .toAll(users).send() | |
| 监控 | 自行接入 Micrometer | 自动配置计数器 | |
| 健康检查 | 编写 Actuator 指示器 | 自动配置 | |
| 管理界面 | 自行构建仪表板 | 内置 /notify-admin | |
| 熔断器 | 为每个渠道自行实现 | 内置按渠道设置的熔断器 | |
| 编排 | 手动编写升级逻辑 | .orchestrate().first(EMAIL).ifNoOpen(24h).then(PUSH) | |
| A/B 测试 | 外部服务 + 胶水代码 | 内置 .abTest("exp").variant(...).split(50,50) | |
| 测试 | 模拟一切 | TestNotifyHub 捕获所有发送操作 | |
| 新渠道 | 从头构建 | 实现一个接口 |
目录
- 快速开始
- 功能
- 支持的渠道
- 管理仪表板
- Spring Boot 集成
- 配置参考
- 不使用 Spring Boot
- MCP 服务(AI Agents)
- 运行演示
- 架构
- Maven Central
- 路线图
- 许可证
快速开始
1. 添加依赖
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
需要额外的渠道? 添加可选模块:
<dependency> <groupId>io.github.gabrielbbaldez</groupId> <artifactId>notify-sms</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>io.github.gabrielbbaldez</groupId> <artifactId>notify-slack</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>io.github.gabrielbbaldez</groupId> <artifactId>notify-websocket</artifactId> <version>1.0.0</version> </dependency>
2. 在 application.yml 中配置
notify:
channels:
email:
host: smtp.gmail.com
port: 587
username: ${GMAIL_USER}
password: ${GMAIL_PASS}
from: [email protected]
from-name: MyApp
tls: true
retry:
max-attempts: 3
strategy: exponential
tracking:
enabled: true
3. 注入并使用
@Service
public class OrderService {
private final NotifyHub notify;
public OrderService(NotifyHub notify) {
this.notify = notify;
}
public void confirmOrder(Order order) {
notify.to(order.getCustomer())
.via(Channel.EMAIL)
.subject("Order confirmed!")
.template("order-confirmed")
.param("customerName", order.getCustomer().getName())
.param("orderId", order.getId())
.param("total", order.getTotal())
.send();
}
}
就这么简单,只需三步。
功能
故障回退链
如果主要渠道失败,则自动尝试下一个渠道:
notify.to(user)
.via(Channel.WHATSAPP)
.fallback(Channel.SMS)
.fallback(Channel.EMAIL)
.template("payment-reminder")
.param("amount", "R$ 150,00")
.send();
// Tries WhatsApp -> SMS -> Email
多渠道发送
同时通过所有渠道发送:
notify.to(user)
.via(Channel.EMAIL)
.via(Channel.SLACK)
.via(Channel.TEAMS)
.subject("Security Alert")
.content("Login from a new device detected")
.sendAll();
异步发送
发送通知时不会阻塞:
// Fire and forget
notify.to(user)
.via(Channel.EMAIL)
.template("welcome")
.sendAsync();
// Or wait for result
CompletableFuture<Void> future = notify.to(user)
.via(Channel.EMAIL)
.via(Channel.SLACK)
.content("Deploy complete!")
.sendAllAsync();
future.thenRun(() -> log.info("All notifications sent!"));
带退避的重试
使用指数或固定退避策略自动重试:
# application.yml (global)
notify:
retry:
max-attempts: 3
strategy: exponential # waits 1s, 2s, 4s...
// Or per-notification
notify.to(user)
.via(Channel.EMAIL)
.retry(3)
.template("invoice")
.send();
模板(Mustache)
在 src/main/resources/templates/notify/ 中创建模板:
order-confirmed.html(自动用于电子邮件):
<h1>Hello, {{customerName}}!</h1>
<p>Your order <strong>#{{orderId}}</strong> has been confirmed.</p>
<p>Total: <strong>{{total}}</strong></p>
order-confirmed.txt(自动用于 SMS/WhatsApp/Slack/Telegram/Discord/Teams):
Hello {{customerName}}, your order #{{orderId}} is confirmed. Total: {{total}}
该库会自动为电子邮件选择 .html,为其他渠道选择 .txt。
i18n(国际化)
模板支持基于区域设置的解析,并会自动回退:
// User with locale
notify.to(user)
.via(Channel.EMAIL)
.locale(Locale.forLanguageTag("pt-BR"))
.template("welcome")
.param("name", user.getName())
.send();
模板解析顺序:welcome_pt_BR.html -> welcome_pt.html -> welcome.html
你的 Notifiable 也可以返回区域设置:
public class User implements Notifiable {
@Override
public Locale getLocale() {
return Locale.forLanguageTag("pt-BR");
}
}
附件
为电子邮件通知添加文件附件:
notify.to(user)
.via(Channel.EMAIL)
.subject("Your Invoice")
.template("invoice")
.attach("invoice.pdf", pdfBytes, "application/pdf")
.attach(new File("/reports/monthly.xlsx"))
.attach(Attachment.fromFile(contractFile))
.send();
优先级
设置通知优先级。URGENT 通知不受速率限制:
notify.to(user)
.via(Channel.EMAIL)
.priority(Priority.URGENT)
.subject("SERVER DOWN!")
.content("Production server is unresponsive")
.send();
可用优先级:URGENT(不受速率限制)、HIGH、NORMAL(默认)、LOW。
速率限制
控制每个渠道的通知吞吐量:
notify:
rate-limit:
enabled: true
max-requests: 100
window: 1m
channels:
email:
max-requests: 50
window: 1m
sms:
max-requests: 10
window: 1m
速率限制使用令牌桶算法。URGENT 优先级的通知始终不受速率限制。
死信队列(DLQ)
所有重试均失败后的通知会自动保存到死信队列:
notify:
tracking:
enabled: true
dlq-enabled: true
可通过 /notify-admin/dlq 处的管理仪表板查看和管理死信,也可以通过编程方式操作:
DeadLetterQueue dlq = hub.getDeadLetterQueue();
List<DeadLetter> failed = dlq.findAll();
dlq.remove(deadLetterId); // after manual reprocessing
批量发送
一次向多个收件人发送通知:
// By email addresses
notify.toAll(List.of("[email protected]", "[email protected]", "[email protected]"))
.via(Channel.EMAIL)
.subject("System Maintenance")
.template("maintenance-notice")
.param("date", "2025-03-01")
.send();
// By Notifiable entities
notify.toAllNotifiable(users)
.via(Channel.EMAIL)
.template("newsletter")
.send();
// Async batch
notify.toAll(recipients)
.via(Channel.EMAIL)
.template("promo")
.sendAsync();
投递跟踪
使用投递回执跟踪每条通知:
notify:
tracking:
enabled: true
type: memory # or "jpa" for database persistence
// Send and get a receipt
DeliveryReceipt receipt = notify.to(user)
.via(Channel.EMAIL)
.content("Hello!")
.sendTracked();
System.out.println(receipt.getStatus()); // SENT
System.out.println(receipt.getId()); // uuid
System.out.println(receipt.getTimestamp()); // 2025-01-15T10:30:00Z
如需将数据持久化到数据库,请添加 JPA 跟踪器模块:
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-tracker-jpa</artifactId>
<version>1.0.0</version>
</dependency>
notify:
tracking:
enabled: true
type: jpa
定时通知
安排在未来某个时间投递通知:
ScheduledNotification scheduled = notify.to(user)
.via(Channel.EMAIL)
.subject("Reminder")
.content("Don't forget your appointment tomorrow!")
.schedule(Duration.ofHours(24));
// Check status
scheduled.getStatus(); // SCHEDULED, SENT, FAILED, CANCELLED
scheduled.getRemainingDelay(); // PT23H59M...
// Cancel if needed
scheduled.cancel();
通知路由
根据用户偏好自动路由通知:
public class User implements Notifiable {
@Override
public List<Channel> getPreferredChannels() {
return List.of(Channel.WHATSAPP, Channel.SMS, Channel.EMAIL);
}
}
// Auto-routes: WhatsApp (primary) -> SMS (fallback) -> Email (fallback)
notify.notify(user)
.template("order-update")
.param("orderId", "12345")
.send();
使用规则进行条件路由:
NotificationRouter router = NotificationRouter.builder()
.rule(RoutingRule.timeBasedRule(
LocalTime.of(9, 0), LocalTime.of(18, 0),
Channel.SLACK, Channel.EMAIL)) // Slack during business hours, email after
.build();
Notifiable 接口
让你的 User 实体成为通知收件人:
@Entity
public class User implements Notifiable {
private String name;
private String email;
private String phone;
@Override
public String getNotifyEmail() { return email; }
@Override
public String getNotifyPhone() { return phone; }
@Override
public String getNotifyName() { return name; }
@Override
public Locale getLocale() { return Locale.forLanguageTag("pt-BR"); }
@Override
public List<Channel> getPreferredChannels() {
return List.of(Channel.EMAIL, Channel.SMS);
}
}
然后只需传入用户对象:
notify.to(user) // resolves email/phone automatically
.via(Channel.EMAIL)
.template("welcome")
.send();
或者使用原始地址:
notify.to("[email protected]").via(Channel.EMAIL).content("Hello!").send();
notify.toPhone("+5511999999999").via(Channel.SMS).content("Code: 1234").send();
消息去重
通过内容哈希或显式键自动避免重复通知:
notify:
deduplication:
enabled: true
ttl: 24h
strategy: content-hash # content-hash | explicit-key | both
// Auto-dedup by content hash (same recipient + channel + content = skipped)
notify.to(user).via(EMAIL).content("Order confirmed").send();
notify.to(user).via(EMAIL).content("Order confirmed").send(); // skipped!
// Dedup by explicit key
notify.to(user).via(EMAIL)
.deduplicationKey("order-" + orderId)
.template("order-confirmed")
.send();
策略:
content-hash— 对收件人、渠道、主题和内容计算 SHA-256 哈希explicit-key— 使用通过.deduplicationKey("...")提供的键both— 如果提供了显式键则使用该键,否则回退到内容哈希
不使用 Spring Boot 时:
NotifyHub notify = NotifyHub.builder()
.deduplicationStore(new InMemoryDeduplicationStore(Duration.ofHours(12)))
.channel(emailChannel)
.build();
模板版本控制
管理模板的多个版本,以进行 A/B 测试或渐进式发布:
templates/notify/
├── order-confirmed.html ← default version
├── [email protected] ← version v1
├── [email protected] ← version v2
├── [email protected] ← v2 with i18n
└── order-confirmed.txt ← text default
// Use a specific version
notify.to(user).via(EMAIL)
.template("order-confirmed")
.templateVersion("v2")
.param("orderId", "123")
.send();
// No version = default template (backward compatible)
notify.to(user).via(EMAIL)
.template("order-confirmed")
.send();
// A/B testing
String version = abTestService.getVariant(user, "email-template");
notify.to(user).via(EMAIL)
.template("welcome")
.templateVersion(version) // "v1" or "v2"
.send();
解析顺序:{name}@{version}_{locale}.{variant} → {name}@{version}.{variant} → {name}_{locale}.{variant} → {name}.{variant}
自定义渠道
只需实现一个接口即可创建自己的渠道:
@Component
public class PushChannel implements NotificationChannel {
@Override
public String getName() { return "push"; }
@Override
public void send(Notification notification) {
firebaseClient.send(notification.getRecipient(), notification.getRenderedContent());
}
@Override
public boolean isAvailable() { return true; }
}
使用方式:
notify.to(user)
.via(Channel.custom("push"))
.template("new-message")
.send();
Spring Boot 会自动发现任何 NotificationChannel Bean。无需额外配置。
事件监听器 + Spring 事件
通过监听器接口监控通知结果:
@Component
public class NotifyMonitor implements NotificationListener {
@Override
public void onSuccess(String channel, String template) {
metrics.increment("notifications.sent." + channel);
}
@Override
public void onFailure(String channel, String template, Exception error) {
log.error("Failed on {}: {}", channel, error.getMessage());
alertService.warn("Channel " + channel + " is failing");
}
@Override
public void onScheduled(String channel, String recipient, Duration delay) {
log.info("Scheduled for {} in {}", recipient, delay);
}
}
或者使用 Spring 应用事件(自动配置):
@Component
public class NotificationEventHandler {
@EventListener
public void onSent(NotificationSentEvent event) {
log.info("Sent via {} to {}", event.getChannel(), event.getRecipient());
}
@EventListener
public void onFailed(NotificationFailedEvent event) {
log.error("Failed: {}", event.getError().getMessage());
}
}
命名收件人
使用命名别名,通过每个渠道向多个目标发送通知。无需将 Webhook URL 或聊天 ID 硬编码为单个值,可按需配置任意数量:
在 application.yml 中配置:
notify:
channels:
discord:
webhook-url: ${DISCORD_DEFAULT} # default destination
username: NotifyHub
avatar-url: https://example.com/logo.png
recipients:
alerts: https://discord.com/api/webhooks/111/aaa
devops: https://discord.com/api/webhooks/222/bbb
general: https://discord.com/api/webhooks/333/ccc
slack:
webhook-url: ${SLACK_DEFAULT}
recipients:
engineering: https://hooks.slack.com/services/XXX/YYY/ZZZ
marketing: https://hooks.slack.com/services/AAA/BBB/CCC
telegram:
bot-token: ${TELEGRAM_BOT_TOKEN}
chat-id: ${TELEGRAM_DEFAULT_CHAT}
recipients:
alerts: "-1001234567890"
devops: "-1009876543210"
通过 Java API 使用:
// Send to a named alias
notify.to("alerts").via(DISCORD).content("Server is down!").send();
notify.to("engineering").via(SLACK).content("Deploy complete").send();
notify.to("devops").via(TELEGRAM).content("CPU at 95%").send();
// Send to default (no alias)
notify.to("user").via(DISCORD).content("Hello!").send();
// Pass a raw URL directly (no alias needed)
notify.to("https://discord.com/api/webhooks/444/ddd").via(DISCORD).content("Direct!").send();
通过 MCP 服务(AI Agent)使用:
send_discord(recipient="alerts", body="Server is down!")
send_slack(recipient="engineering", body="Deploy complete")
send_telegram(recipient="devops", body="CPU at 95%")
MCP/Docker 环境变量:
# Default webhook
NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/111/aaa
# Named recipients (RECIPIENTS_<NAME>)
NOTIFY_CHANNELS_DISCORD_RECIPIENTS_ALERTS=https://discord.com/api/webhooks/222/bbb
NOTIFY_CHANNELS_DISCORD_RECIPIENTS_DEVOPS=https://discord.com/api/webhooks/333/ccc
# Same pattern for all channels
NOTIFY_CHANNELS_SLACK_RECIPIENTS_ENGINEERING=https://hooks.slack.com/services/XXX
NOTIFY_CHANNELS_TELEGRAM_RECIPIENTS_ALERTS=-1001234567890
NOTIFY_CHANNELS_TEAMS_RECIPIENTS_GENERAL=https://outlook.office.com/webhook/XXX
NOTIFY_CHANNELS_GOOGLE_CHAT_RECIPIENTS_TEAM=https://chat.googleapis.com/v1/spaces/XXX
**解析顺序:**收件人映射中的别名匹配 > 原始 URL/值直通 > 配置中的默认值。
支持:Discord、Slack、Telegram、Teams、Google Chat。
消息队列(RabbitMQ / Kafka)
通过异步消息队列解耦通知发送。NotifyHub 提供两个模块:
RabbitMQ
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-queue-rabbitmq</artifactId>
<version>1.0.0</version>
</dependency>
spring.rabbitmq.host: localhost
spring.rabbitmq.port: 5672
notify.queue.rabbitmq:
enabled: true
queue-name: notifyhub-notifications
exchange-name: notifyhub-exchange
routing-key: notification
consumer:
enabled: true
concurrency: 1
max-concurrency: 5
@Autowired RabbitNotificationProducer producer;
// Enqueue for async delivery
producer.enqueue(QueuedNotification.builder()
.recipient("[email protected]")
.channelName("email")
.subject("Welcome!")
.templateName("welcome")
.params(Map.of("name", "Gabriel"))
.build());
// Consumer picks it up and sends via NotifyHub automatically
Apache Kafka
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-queue-kafka</artifactId>
<version>1.0.0</version>
</dependency>
spring.kafka.bootstrap-servers: localhost:9092
notify.queue.kafka:
enabled: true
topic: notifyhub-notifications
consumer:
enabled: true
group-id: notifyhub-group
concurrency: 1
@Autowired KafkaNotificationProducer producer;
// Same API as RabbitMQ — just different transport
producer.enqueue(QueuedNotification.builder()
.recipient("+5548999999999")
.channelName("sms")
.rawContent("Your code is 1234")
.priority("URGENT")
.build());
两个模块均支持:模板、优先级、去重键、投递跟踪,以及用于 SMS/WhatsApp 的电话号码路由。
熔断器
每个渠道都配有熔断器,以防止故障级联。如果某个渠道反复失败,熔断器便会打开并短路后续尝试:
// Without Spring Boot
NotifyHub notify = NotifyHub.builder()
.channel(emailChannel)
.circuitBreaker(CircuitBreakerConfig.defaults()) // 5 failures → open for 30s
.build();
// Custom thresholds
NotifyHub notify = NotifyHub.builder()
.channel(emailChannel)
.circuitBreaker(CircuitBreakerConfig.custom()
.failureThreshold(3)
.openDuration(Duration.ofMinutes(1))
.windowSize(Duration.ofSeconds(30))
.build())
.build();
# Spring Boot
notify:
circuit-breaker:
enabled: true
failure-threshold: 5
open-duration: 30s
window-size: 60s
状态:CLOSED(正常)→ OPEN(拒绝请求)→ HALF_OPEN(测试恢复情况)。健康检查端点会显示每个渠道的熔断器状态。
舱壁(并发隔离)
限制每个渠道的并发发送数,以防止资源耗尽:
NotifyHub notify = NotifyHub.builder()
.channel(emailChannel)
.bulkhead(BulkheadConfig.defaults()) // 10 concurrent per channel
.bulkhead(BulkheadConfig.perChannel(5)) // or custom limit
.build();
多渠道编排
构建升级工作流:如果用户没有响应,就逐步切换到其他渠道:
notify.to(user)
.orchestrate()
.first(Channel.EMAIL)
.template("order-update")
.ifNoOpen(Duration.ofHours(24))
.then(Channel.PUSH)
.content("You have an unread order update")
.ifNoOpen(Duration.ofHours(48))
.then(Channel.SMS)
.content("Order update waiting — check your email")
.execute();
每个步骤都会等待指定时长,然后升级到下一个渠道。
A/B 测试
内置通知确定性 A/B 测试。变体分配基于哈希(SHA-256)——同一收件人始终会收到相同的变体:
notify.to(user)
.via(Channel.EMAIL)
.subject("Welcome!")
.abTest("welcome-experiment")
.variant("control", b -> b.template("welcome-v1"))
.variant("new-design", b -> b.template("welcome-v2"))
.split(50, 50);
支持任意数量的变体,并可按权重分配。确定性哈希可确保每次发送的体验保持一致。
Cron 调度
使用 cron 表达式安排定期通知:
ScheduledNotification job = notify.to(user)
.via(Channel.EMAIL)
.template("weekly-digest")
.cron("0 9 * * MON"); // Every Monday at 9 AM
支持标准的 5 字段 cron 语法:分钟、小时、日、月、星期。包含范围、列表、步长,以及命名的星期和月份。
免打扰时段
遵循用户的通知时间偏好:
public class User implements Notifiable {
@Override
public QuietHours getQuietHours() {
return QuietHours.between(
LocalTime.of(22, 0), // 10 PM
LocalTime.of(8, 0), // 8 AM
ZoneId.of("America/Sao_Paulo")
);
}
@Override
public Set<Channel> getOptedOutChannels() {
return Set.of(Channel.SMS); // User opted out of SMS
}
}
在免打扰时段内发送的通知会延迟到下一个允许的时段。已选择退出的渠道会被静默跳过。
测试工具
TestNotifyHub 提供了一个便于测试的包装器,其中包含适用于所有内置渠道类型的捕获渠道:
@Test
void shouldSendWelcomeEmail() {
TestNotifyHub test = TestNotifyHub.create();
test.to("[email protected]")
.via(Channel.EMAIL)
.subject("Welcome")
.content("Hello!")
.send();
assertThat(test.sent()).hasSize(1);
assertThat(test.sent("email").get(0).subject()).isEqualTo("Welcome");
}
无需模拟——TestNotifyHub 会在内存中捕获所有通知,供断言使用。在测试之间调用 test.reset()。
支持的渠道
| 渠道 | 提供方 | 模块 | |
|---|---|---|---|
| 电子邮件 | SMTP(Gmail、SES、Outlook 等) | notify-email | |
| 📱 | 短信 | Twilio | notify-sms |
| Twilio | notify-sms | ||
| Slack | 传入 Webhook | notify-slack | |
| Telegram | Bot API | notify-telegram | |
| Discord | Webhook | notify-discord | |
| 👥 | Microsoft Teams | 传入 Webhook | notify-teams |
| 推送(FCM) | Firebase Cloud Messaging | notify-push-firebase | |
| 🔗 | Webhook | 任意 HTTP 端点 | notify-webhook |
| WebSocket | JDK WebSocket(java.net.http) | notify-websocket | |
| Google Chat | Webhook | notify-google-chat | |
| Twitter/X | API v2(OAuth 1.0a) | notify-twitter | |
| 💼 | REST API(OAuth 2.0) | notify-linkedin | |
| Notion | API(集成令牌) | notify-notion | |
| Twitch | Helix API(OAuth 2.0 自动刷新) | notify-twitch | |
| YouTube | Data API v3(OAuth 自动刷新) | notify-youtube | |
| Meta Graph API | notify-instagram | ||
| 📧 | SendGrid | SendGrid API(投递跟踪) | notify-sendgrid |
| TikTok Shop | TikTok Shop API(HMAC-SHA256) | notify-tiktok-shop | |
| Graph API(主页 + Messenger) | notify-facebook | ||
| WhatsApp Cloud | Meta Cloud API(直连,无需 Twilio) | notify-whatsapp | |
| ☁️ | AWS SNS | AWS SDK v2 | notify-aws-sns |
| Mailgun | Mailgun REST API | notify-mailgun | |
| PagerDuty | Events API v2 | notify-pagerduty | |
| Kick | 公共 API | notify-kick | |
| ➕ | 自定义 | 任意——实现一个接口 | notify-core |
管理控制面板
NotifyHub 内置了管理控制面板,可用于监控通知系统。
notify:
admin:
enabled: true
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-admin</artifactId>
<version>1.0.0</version>
</dependency>
访问 /notify-admin 查看:
- 控制面板 — 指标卡片(已发送/失败/待处理/DLQ/渠道/联系人)、近期活动动态、系统状态网格、已注册渠道
- 分析 — 使用 Chart.js 绘制的图表,展示发送量、渠道分布、成功率、小时热力图
- 跟踪 — 投递回执,支持按渠道筛选并显示状态徽标
- 死信队列 — 失败通知及错误详情,并提供移除操作
- 渠道 — 各已注册渠道的状态及健康指标
- 审计日志 — 所有通知事件的完整历史记录,支持按事件类型筛选
- 受众 — 管理联系人和受众细分,支持按标签筛选
- 状态 Webhook — 实时 HTTP 回调配置及投递历史
支持深色/浅色主题切换,并通过 localStorage 在各页面间保留设置。
Spring Boot 集成
Micrometer 指标
当 Micrometer 位于类路径中时自动配置:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
通过统一的 EventBus 暴露计数器和仪表:
notifyhub.notifications.sent(标签:channel)notifyhub.notifications.failed(标签:channel)notifyhub.notifications.retried(标签:channel)notifyhub.notifications.rate_limited(标签:channel)notifyhub.notifications.deduped(标签:channel)notifyhub.notifications.circuit_opened(标签:channel)notifyhub.notifications.circuit_closed(标签:channel)notifyhub.notifications.send_duration(计时器,标签:channel)
Actuator 健康检查
当 Spring Boot Actuator 位于类路径中时自动配置:
GET /actuator/health/notifyhub
{
"status": "UP",
"details": {
"email": { "status": "UP", "circuitBreaker": "CLOSED" },
"slack": { "status": "UP", "circuitBreaker": "CLOSED" },
"totalChannels": 2,
"availableChannels": 2
}
}
状态:UP(所有渠道均可用)、DEGRADED(部分渠道不可用)、DOWN(所有渠道均不可用)。配置断路器后,每个渠道还会报告其断路器状态。
Actuator 信息
GET /actuator/info
{
"notifyhub": {
"version": "1.0.0",
"channels": ["email", "slack", "teams"],
"tracking.enabled": true,
"dlq.enabled": true
}
}
OpenTelemetry 跟踪
当 Micrometer Observation 和 OTel 桥接库位于类路径中时自动配置。 添加以下依赖项,通过 OTLP 导出分布式跟踪:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
在 application.yml 中配置 OTLP 端点:
management:
tracing:
sampling:
probability: 1.0 # 100% sampling (adjust for production)
otlp:
tracing:
endpoint: http://localhost:4318/v1/traces
创建以下观测(跨度):
notifyhub.send(标签:channel、template、outcome)notifyhub.schedule(标签:channel、outcome)
兼容 Jaeger、Zipkin、Grafana Tempo、Datadog 以及任何兼容 OTLP 的收集器。
Webhook HMAC 签名
状态 Webhook 监听器支持 HMAC-SHA256 请求签名,以增强安全性。配置后,每个 Webhook POST 请求都会包含 X-NotifyHub-Signature 标头,供你的服务器验证请求是否来自 NotifyHub。
notify:
status-webhook:
url: https://your-server.com/webhook
signing-secret: ${WEBHOOK_SECRET} # any secret string
每个请求都包含以下标头:
X-NotifyHub-Signature: sha256=<hex-encoded HMAC-SHA256 of request body>
在服务器中验证:
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(), "HmacSHA256"));
String expected = "sha256=" + HexFormat.of().formatHex(mac.doFinal(body.getBytes()));
boolean valid = MessageDigest.isEqual(expected.getBytes(), signature.getBytes());
配置参考
包含所有选项的完整 application.yml:
notify:
channels:
email:
host: smtp.gmail.com
port: 587
username: ${GMAIL_USER}
password: ${GMAIL_PASS}
from: [email protected]
from-name: MyApp
tls: true
ssl: false
sms:
account-sid: ${TWILIO_SID}
auth-token: ${TWILIO_TOKEN}
from-number: "+1234567890"
whatsapp:
account-sid: ${TWILIO_SID}
auth-token: ${TWILIO_TOKEN}
from-number: "+14155238886"
slack:
webhook-url: ${SLACK_WEBHOOK}
recipients: # named aliases (optional)
engineering: https://hooks.slack.com/services/XXX
marketing: https://hooks.slack.com/services/YYY
telegram:
bot-token: ${TELEGRAM_BOT_TOKEN}
chat-id: ${TELEGRAM_CHAT_ID}
recipients: # named aliases (optional)
alerts: "-1001234567890"
devops: "-1009876543210"
discord:
webhook-url: ${DISCORD_WEBHOOK}
username: NotifyHub
avatar-url: https://example.com/logo.png
recipients: # named aliases (optional)
alerts: https://discord.com/api/webhooks/111/aaa
devops: https://discord.com/api/webhooks/222/bbb
teams:
webhook-url: ${TEAMS_WEBHOOK}
recipients: # named aliases (optional)
general: https://outlook.office.com/webhook/XXX
push:
credentials-path: ${FIREBASE_CREDENTIALS}
project-id: ${FIREBASE_PROJECT_ID}
webhooks:
- name: pagerduty
url: https://events.pagerduty.com/v2/enqueue
headers:
Authorization: "Token ${PAGERDUTY_TOKEN}"
payload-template: '{"summary":"{{content}}"}'
websocket:
uri: wss://echo.example.com/ws
timeout-ms: 10000
reconnect-enabled: true
reconnect-delay-ms: 5000
max-reconnect-attempts: 3
headers:
Authorization: "Bearer ${WS_TOKEN}"
message-format: '{"type":"notification","content":"{{content}}"}'
google-chat:
webhook-url: ${GOOGLE_CHAT_WEBHOOK}
timeout-ms: 10000
recipients: # named aliases (optional)
team-a: https://chat.googleapis.com/v1/spaces/XXX/messages?key=YYY
team-b: https://chat.googleapis.com/v1/spaces/ZZZ/messages?key=WWW
retry:
max-attempts: 3
strategy: exponential
rate-limit:
enabled: true
max-requests: 100
window: 1m
channels:
email:
max-requests: 50
window: 1m
tracking:
enabled: true
type: memory # memory | jpa
dlq-enabled: true
deduplication:
enabled: true
ttl: 24h
strategy: content-hash # content-hash | explicit-key | both
admin:
enabled: true
不使用 Spring Boot
NotifyHub 无需 Spring 即可运行 — 直接使用构建器:
NotifyHub notify = NotifyHub.builder()
.templateEngine(new MustacheTemplateEngine())
.channel(new SmtpEmailChannel(
SmtpConfig.builder()
.host("smtp.gmail.com").port(587)
.username("[email protected]").password("app-password")
.from("[email protected]").tls(true)
.build()
))
.channel(new SlackChannel(
SlackConfig.builder()
.webhookUrl("https://hooks.slack.com/services/XXX/YYY/ZZZ")
.recipients(Map.of("engineering", "https://hooks.slack.com/services/AAA/BBB/CCC"))
.build()
))
.channel(new TeamsChannel(
TeamsConfig.builder()
.webhookUrl("https://outlook.office.com/webhook/XXX/YYY/ZZZ")
.build()
))
.channel(new WebhookChannel(
WebhookConfig.builder()
.name("pagerduty")
.url("https://events.pagerduty.com/v2/enqueue")
.payloadTemplate("{\"summary\":\"{{content}}\"}")
.build()
))
.channel(new WebSocketChannel(
WebSocketConfig.builder()
.uri("wss://echo.example.com/ws")
.messageFormat("{\"text\":\"{{content}}\"}")
.build()
))
.channel(new GoogleChatChannel(
GoogleChatConfig.builder()
.webhookUrl("https://chat.googleapis.com/v1/spaces/XXX/messages?key=YYY")
.build()
))
.deduplicationStore(new InMemoryDeduplicationStore(Duration.ofHours(24)))
.defaultRetryPolicy(RetryPolicy.exponential(3))
.rateLimiter(new TokenBucketRateLimiter(
RateLimitConfig.perMinute(100)))
.deadLetterQueue(new InMemoryDeadLetterQueue())
.tracker(new InMemoryNotificationTracker())
.circuitBreaker(CircuitBreakerConfig.defaults())
.bulkhead(BulkheadConfig.defaults())
.build();
// Sync
notify.to("[email protected]")
.via(Channel.EMAIL)
.subject("Hello!")
.content("Welcome to the app!")
.send();
// Async
notify.to("#general")
.via(Channel.SLACK)
.content("Deploy complete!")
.sendAsync();
// Tracked
DeliveryReceipt receipt = notify.to(user)
.via(Channel.EMAIL)
.content("Invoice attached")
.sendTracked();
// Scheduled
notify.to(user)
.via(Channel.EMAIL)
.content("Reminder!")
.schedule(Duration.ofMinutes(30));
// Batch
notify.toAll(List.of("[email protected]", "[email protected]"))
.via(Channel.EMAIL)
.template("announcement")
.send();
只需使用 notify-core 和渠道模块。无需依赖 Spring。
MCP 服务(AI Agent)
NotifyHub 内置了一个 MCP(Model Context Protocol)服务,可将所有通知渠道作为工具提供给 Claude Desktop、Claude Code、Cursor 等 AI Agent,以及任何兼容 MCP 的客户端。
工作原理
notify-mcp 模块是一个独立的 Java 应用程序,通过 STDIO 使用 JSON-RPC 协议进行通信。AI Agent 可发现可用工具,并通过任何已配置的渠道发送通知。
设置
1. 构建 MCP 服务:
mvn clean package -pl notify-mcp -am -DskipTests
2. 在 Claude Desktop 中配置(claude_desktop_config.json):
{
"mcpServers": {
"notify-hub": {
"command": "java",
"args": ["-jar", "path/to/notify-mcp-1.0.0.jar"],
"env": {
"NOTIFY_CHANNELS_EMAIL_HOST": "smtp.gmail.com",
"NOTIFY_CHANNELS_EMAIL_PORT": "587",
"NOTIFY_CHANNELS_EMAIL_USERNAME": "[email protected]",
"NOTIFY_CHANNELS_EMAIL_PASSWORD": "app-password",
"NOTIFY_CHANNELS_SLACK_WEBHOOK_URL": "https://hooks.slack.com/...",
"NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL": "https://discord.com/api/webhooks/..."
}
}
}
}
或者,在 Claude Code 中配置(项目根目录下的 .mcp.json):
{
"mcpServers": {
"notify-hub": {
"command": "java",
"args": ["-jar", "path/to/notify-mcp-1.0.0.jar"],
"env": {
"NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL": "https://discord.com/api/webhooks/..."
}
}
}
}
可用的 MCP 工具
| 工具 | 描述 | 必需参数 |
|---|---|---|
send_notification | 通过任意渠道发送(通用) | channel、recipient、body 或 template |
send_email | 发送电子邮件 | to、body 或 template |
send_sms | 通过 Twilio 发送 SMS | phone、body 或 template |
send_slack | 发送到 Slack 频道 | recipient、body 或 template |
send_telegram | 通过 Telegram Bot 发送 | recipient、body 或 template |
send_discord | 发送到 Discord 频道 | recipient、body 或 template |
send_whatsapp | 通过 Twilio 发送 WhatsApp 消息 | phone、body 或 template |
send_teams | 发送到 Microsoft Teams | recipient、body 或 template |
send_google_chat | 发送到 Google Chat | recipient、body 或 template |
send_push | 通过 Firebase 发送推送通知 | push_token、body |
send_twitter | 在 Twitter/X 上发布推文 | body 或 template |
send_linkedin | 在 LinkedIn 上发布帖子 | body 或 template |
send_notion | 在 Notion 中创建页面 | recipient、body 或 template |
send_twitch | 发送 Twitch 聊天消息和投票 | recipient、body 或 template |
send_youtube | 发送 YouTube 直播聊天消息 | recipient、body 或 template |
send_instagram | 发送 Instagram 私信或动态帖子 | recipient、body 或 template |
send_multi_channel | 发送到多个渠道 | channels[]、recipient、body 或 template |
send_batch | 一次发送给多个收件人 | recipients[]、channel、body 或 template |
send_to_audience | 发送给指定受众 | audience、channel、body 或 template |
list_channels | 列出已配置的渠道 | (无) |
list_delivery_receipts | 查询投递历史记录 | (无) |
list_dead_letters | 查看发送失败的通知(DLQ) | (无) |
create_contact | 创建带标签的联系人 | name |
list_contacts | 列出联系人(按标签筛选) | (无) |
create_audience | 使用标签筛选条件创建受众 | name、tags[] |
list_audiences | 列出受众及其联系人数量 | (无) |
get_analytics | 按渠道/状态统计投递数据 | (无) |
send_tiktok_shop | 发送 TikTok Shop 通知 | recipient、body 或 template |
send_facebook | 发布 Facebook 专页帖子或发送 Messenger 私信 | recipient、body 或 template |
check_email_status | 检查 SendGrid 电子邮件投递状态 | message_id |
schedule_notification | 定时发送通知 | channel、recipient、body、send_at |
list_scheduled_notifications | 列出所有定时通知 | (无) |
cancel_scheduled_notification | 取消待发送的定时通知 | notification_id |
所有发送工具均可选接受:subject、template、params、priority。
使用示例(来自 AI Agent)
配置完成后,你只需向 AI Agent 提出请求:
“向 #alerts 发送一条 Discord 消息,说明部署已完成”
Agent 将使用适当的参数调用 send_discord 工具。
Docker
无需安装 Java 即可运行 MCP 服务——只需 Docker:
# Build
docker build -t notifyhub-mcp .
# Run with Discord
docker run -i --rm \
-e NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..." \
-e NOTIFY_CHANNELS_DISCORD_USERNAME="NotifyHub" \
gabrielbbal10/notifyhub-mcp
# Run with multiple Discord channels + Email
docker run -i --rm \
-e NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..." \
-e NOTIFY_CHANNELS_DISCORD_USERNAME="NotifyHub" \
-e NOTIFY_CHANNELS_DISCORD_RECIPIENTS_ALERTS="https://discord.com/api/webhooks/111/aaa" \
-e NOTIFY_CHANNELS_DISCORD_RECIPIENTS_DEVOPS="https://discord.com/api/webhooks/222/bbb" \
-e NOTIFY_CHANNELS_EMAIL_HOST="smtp.gmail.com" \
-e NOTIFY_CHANNELS_EMAIL_PORT="587" \
-e NOTIFY_CHANNELS_EMAIL_USERNAME="[email protected]" \
-e NOTIFY_CHANNELS_EMAIL_PASSWORD="app-password" \
-e NOTIFY_CHANNELS_EMAIL_FROM="[email protected]" \
gabrielbbal10/notifyhub-mcp
在 Claude Code 中配置(.mcp.json):
{
"mcpServers": {
"notify-hub": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-e", "NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...",
"-e", "NOTIFY_CHANNELS_DISCORD_USERNAME=NotifyHub",
"-e", "NOTIFY_CHANNELS_DISCORD_RECIPIENTS_ALERTS=https://discord.com/api/webhooks/111/aaa",
"gabrielbbal10/notifyhub-mcp"
]
}
}
}
Docker REST API
运行完整的 REST API 并使用 Swagger UI——无需 Java,只需 Docker:
docker run -d -p 8080:8080 \
-e [email protected] \
-e NOTIFY_CHANNELS_EMAIL_PASSWORD=your-app-password \
-e [email protected] \
gabrielbbal10/notifyhub-api:latest
打开 http://localhost:8080/swagger-ui.html 查看交互式 API 文档。
环境变量——MCP 和 API 镜像相同,只添加所需渠道:
| 渠道 | 变量 | 必填 | 示例 |
|---|---|---|---|
NOTIFY_CHANNELS_EMAIL_HOST | 否(默认:smtp.gmail.com) | smtp.gmail.com | |
NOTIFY_CHANNELS_EMAIL_PORT | 否(默认:587) | 587 | |
NOTIFY_CHANNELS_EMAIL_USERNAME | 是(用于电子邮件) | [email protected] | |
NOTIFY_CHANNELS_EMAIL_PASSWORD | 是(用于电子邮件) | abcd efgh ijkl mnop(应用专用密码) | |
NOTIFY_CHANNELS_EMAIL_FROM | 是(用于电子邮件) | [email protected] | |
| Discord | NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL | 是(用于 discord) | https://discord.com/api/webhooks/... |
NOTIFY_CHANNELS_DISCORD_USERNAME | 否 | NotifyHub | |
NOTIFY_CHANNELS_DISCORD_AVATAR_URL | 否 | https://example.com/avatar.png | |
NOTIFY_CHANNELS_DISCORD_RECIPIENTS_<NAME> | 否 | 命名别名的 webhook URL | |
| Slack | NOTIFY_CHANNELS_SLACK_WEBHOOK_URL | 是(用于 slack) | https://hooks.slack.com/services/... |
NOTIFY_CHANNELS_SLACK_RECIPIENTS_<NAME> | 否 | 命名别名的 webhook URL | |
| Telegram | NOTIFY_CHANNELS_TELEGRAM_BOT_TOKEN | 是(用于 telegram) | 123456:ABC-DEF... |
NOTIFY_CHANNELS_TELEGRAM_CHAT_ID | 是(用于 telegram) | 123456789 | |
NOTIFY_CHANNELS_TELEGRAM_RECIPIENTS_<NAME> | 否 | 命名别名的聊天 ID | |
| Google Chat | NOTIFY_CHANNELS_GOOGLE_CHAT_WEBHOOK_URL | 是(用于 gchat) | https://chat.googleapis.com/v1/spaces/... |
NOTIFY_CHANNELS_GOOGLE_CHAT_RECIPIENTS_<NAME> | 否 | 命名别名的 webhook URL | |
| Teams | NOTIFY_CHANNELS_TEAMS_WEBHOOK_URL | 是(用于 teams) | https://outlook.office.com/webhook/... |
NOTIFY_CHANNELS_TEAMS_RECIPIENTS_<NAME> | 否 | 命名别名的 webhook URL | |
| 短信 | NOTIFY_CHANNELS_SMS_ACCOUNT_SID | 是(用于 sms) | Twilio 账户 SID |
NOTIFY_CHANNELS_SMS_AUTH_TOKEN | 是(用于 sms) | Twilio 身份验证令牌 | |
NOTIFY_CHANNELS_SMS_FROM_NUMBER | 是(用于 sms) | +12025551234 | |
NOTIFY_CHANNELS_WHATSAPP_ACCOUNT_SID | 是(用于 whatsapp) | Twilio 账户 SID | |
NOTIFY_CHANNELS_WHATSAPP_AUTH_TOKEN | 是(用于 whatsapp) | Twilio 身份验证令牌 | |
NOTIFY_CHANNELS_WHATSAPP_FROM_NUMBER | 是(用于 whatsapp) | +14155238886 |
配置多个渠道的示例:
docker run -d -p 8080:8080 \
-e [email protected] \
-e NOTIFY_CHANNELS_EMAIL_PASSWORD=your-app-password \
-e [email protected] \
-e NOTIFY_CHANNELS_DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..." \
-e NOTIFY_CHANNELS_DISCORD_USERNAME="NotifyHub" \
-e NOTIFY_CHANNELS_TELEGRAM_BOT_TOKEN="123456:ABC-DEF..." \
-e NOTIFY_CHANNELS_TELEGRAM_CHAT_ID="123456789" \
-e NOTIFY_CHANNELS_GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/..." \
gabrielbbal10/notifyhub-api:latest
从任何语言中使用:
# Send email
curl -X POST "http://localhost:8080/send/[email protected]&subject=Hello&body=Hi!"
# Send Discord
curl -X POST "http://localhost:8080/send/discord?message=Deploy done!"
# Send Telegram
curl -X POST "http://localhost:8080/send/telegram?chatId=123456789&message=Alert!"
# Send Google Chat
curl -X POST "http://localhost:8080/send/google-chat?message=Build passed!"
Docker Hub: gabrielbbal10/notifyhub-api
运行演示
演示应用通过内置 SMTP 服务器展示所有功能——无需任何外部配置。
git clone https://github.com/GabrielBBaldez/notify-hub.git
cd notify-hub
mvn clean install -DskipTests
# Run the demo
mvn -pl notify-demo spring-boot:run
然后打开:
- http://localhost:8080 — API 端点
- http://localhost:8080/notify-admin — 管理面板
演示端点
| 方法 | 端点 | 描述 |
|---|---|---|
GET | / | 首页 — 列出所有端点 |
POST | /send/email | 发送简单邮件 |
POST | /send/template | 使用 Mustache 模板发送邮件 |
POST | /send/notifiable | 发送给 Notifiable 实体 |
POST | /send/sms | 发送 SMS(需要 Twilio) |
POST | /send/whatsapp | 发送 WhatsApp 消息(需要 Twilio) |
POST | /send/telegram | 通过 Bot 发送到 Telegram |
POST | /send/discord | 通过 Webhook 发送到 Discord |
POST | /send/slack | 发送到 Slack 频道 |
POST | /send/teams | 通过 Webhook 发送到 Microsoft Teams |
POST | /send/google-chat | 通过 Webhook 发送到 Google Chat |
POST | /send/push | 通过 Firebase 发送推送通知 |
POST | /send/websocket | 通过 WebSocket 发送消息 |
POST | /send/multi | 同时发送到邮件和 Slack |
POST | /send/fallback | 测试回退(邮件发送失败 -> Slack) |
POST | /send/tracked | 发送并跟踪投递情况 |
POST | /send/scheduled | 安排在未来发送通知 |
GET | /tracking | 投递跟踪历史 |
GET | /notify-admin | 管理员仪表板 |
GET | /inbox | 查看已捕获的邮件 |
DELETE | /inbox | 清空所有收件箱 |
架构
notify-hub/
├── notify-core/ # Zero Spring dependency
│ ├── NotifyHub # Thin facade — delegates to executor/scheduler/eventbus
│ ├── NotificationExecutor # Channel resolution, send logic, fallback chains
│ ├── NotificationScheduler # Scheduling with delay/cancel/list
│ ├── NotificationBuilder # Fluent builder (send/async/tracked/scheduled)
│ ├── BatchNotificationBuilder # Batch send to multiple recipients
│ ├── Notification # Immutable notification object
│ ├── Channel / ChannelRef # Built-in + custom channel refs
│ ├── Priority # URGENT, HIGH, NORMAL, LOW
│ ├── Notifiable # Recipient interface (i18n + routing + quiet hours)
│ ├── NotificationChannel # Channel SPI (implement this!)
│ ├── QuietHours # Per-recipient quiet time windows
│ ├── pipeline/ # Resilience handler chain
│ │ ├── SendPipeline # Assembles: Dedup → RateLimit → CircuitBreaker → Template → Retry
│ │ ├── SendHandler # Handler chain interface
│ │ ├── SendContext # Per-send state (channel, builder, notification)
│ │ ├── DeduplicationHandler # Skip duplicates
│ │ ├── RateLimitHandler # Enforce per-channel limits
│ │ ├── CircuitBreakerHandler # Short-circuit failing channels
│ │ ├── TemplateHandler # Build + render notification
│ │ └── RetrySendHandler # Terminal: retry with backoff → DLQ
│ ├── resilience/ # Resilience primitives
│ │ ├── ChannelCircuitBreaker # Per-channel circuit breaker (sliding window)
│ │ ├── CircuitBreakerConfig # Thresholds + durations
│ │ ├── CircuitState # CLOSED, OPEN, HALF_OPEN
│ │ └── BulkheadConfig # Per-channel concurrency limits
│ ├── event/ # Unified event system
│ │ ├── NotificationEventBus # Publish events to listeners
│ │ ├── NotificationEvent # Immutable event record
│ │ ├── EventType # SENT, FAILED, RETRIED, RATE_LIMITED, DEDUPED, CIRCUIT_*
│ │ ├── NotificationEventListener # Listener interface
│ │ └── LegacyListenerAdapter # Bridge: old NotificationListener → EventBus
│ ├── orchestration/ # Multi-step notification workflows
│ │ ├── OrchestrationBuilder # first(EMAIL).ifNoOpen(24h).then(PUSH)
│ │ └── OrchestrationStep # Individual step record
│ ├── abtest/ # A/B testing
│ │ └── AbTestBuilder # Deterministic SHA-256 variant selection
│ ├── schedule/ # Cron support
│ │ └── CronExpression # Lightweight 5-field cron parser
│ ├── attachment/ # File attachments
│ │ └── Attachment # Email file attachments
│ ├── testing/ # Test utilities
│ │ ├── TestNotifyHub # Test wrapper with capturing channels
│ │ └── SentNotification # Captured notification record
│ ├── RateLimiter / TokenBucket # Rate limiting
│ ├── NotificationRouter / RoutingRule # Conditional routing
│ ├── MustacheTemplateEngine # Template engine (i18n-aware + versioning)
│ ├── DeduplicationStore # Dedup interface (in-memory impl)
│ └── RetryPolicy # Retry + backoff strategies
│
├── notify-channels/
│ ├── notify-email/ # SMTP email (Jakarta Mail + attachments)
│ ├── notify-sms/ # Twilio SMS + WhatsApp
│ ├── notify-slack/ # Slack webhooks (JDK HttpClient)
│ ├── notify-telegram/ # Telegram Bot API (JDK HttpClient)
│ ├── notify-discord/ # Discord webhooks (JDK HttpClient)
│ ├── notify-teams/ # Microsoft Teams webhooks (JDK HttpClient)
│ ├── notify-push-firebase/ # Firebase Cloud Messaging (FCM)
│ ├── notify-webhook/ # Generic webhook (configurable)
│ ├── notify-websocket/ # WebSocket (JDK java.net.http)
│ ├── notify-google-chat/ # Google Chat webhooks (JDK HttpClient)
│ ├── notify-twitch/ # Twitch chat + polls via Helix API (JDK HttpClient)
│ ├── notify-youtube/ # YouTube live chat via Data API v3 (JDK HttpClient)
│ ├── notify-instagram/ # Instagram DM + feed via Meta Graph API (JDK HttpClient)
│ ├── notify-sendgrid/ # SendGrid email with delivery tracking (JDK HttpClient)
│ ├── notify-tiktok-shop/ # TikTok Shop API (HMAC-SHA256, JDK HttpClient)
│ ├── notify-facebook/ # Facebook Graph API (Page + Messenger)
│ ├── notify-whatsapp/ # WhatsApp Cloud API (Meta Graph API, no Twilio)
│ ├── notify-aws-sns/ # AWS SNS (AWS SDK v2)
│ ├── notify-mailgun/ # Mailgun transactional email (JDK HttpClient)
│ ├── notify-pagerduty/ # PagerDuty Events API v2 (JDK HttpClient)
│ └── notify-kick/ # Kick Public API (JDK HttpClient)
│ └── notify-channel-template/ # Template/archetype for creating new channels
│
├── notify-tracker-jpa/ # JPA-backed delivery tracker
├── notify-audit-jpa/ # JPA-backed audit logging
│
├── notify-spring-boot-starter/ # Auto-config for Spring Boot
│ ├── NotifyAutoConfiguration # Auto-discovers all channels + event listeners
│ ├── MetricsEventListener # Micrometer metrics via EventBus
│ ├── TracingNotificationListener # OpenTelemetry tracing (Observation API)
│ ├── NotifyHubHealthIndicator # Actuator health (+ circuit breaker status)
│ ├── NotifyHubInfoContributor # Actuator info endpoint
│ ├── SpringEventNotificationListener # Spring ApplicationEvents
│ └── NotifyProperties # application.yml binding
│
├── notify-admin/ # Admin dashboard (Thymeleaf)
│ └── NotifyAdminController # /notify-admin/*
│
├── notify-mcp/ # MCP Server for AI agents
│ ├── NotifyMcpServer # Spring Boot headless main
│ ├── McpServerRunner # STDIO MCP server bootstrap
│ └── tools/ # 36 MCP tools (send, batch, audiences, DLQ, analytics)
│
├── notify-queue-rabbitmq/ # RabbitMQ integration
├── notify-queue-kafka/ # Kafka integration
│
└── notify-demo/ # Demo app (run it!)
弹性管道
每条通知在到达渠道之前都会经过一系列处理器:
Deduplication → Rate Limit → Circuit Breaker → Template Rendering → Retry + Send → DLQ
每个处理器都可以提前终止流程(例如,去重处理器会跳过重复项,熔断器会在开启时拒绝请求)。该管道完全可选 — 当依赖项为 null 时,会跳过相应的处理器。
设计原则
notify-core不依赖 Spring — 可在任何 Java 项目中使用- 渠道可插拔 — 实现
NotificationChannel,并将其注册为 Spring bean - Slack、Telegram、Discord、Teams、WebSocket、Google Chat 不使用任何外部 SDK — 仅使用 JDK
java.net.http.HttpClient - 模板引擎可替换 — 实现
TemplateEngine接口 - Spring Boot starter 自动配置所有内容 — 只需添加依赖
- 异步支持 — 使用
CompletableFuture实现sendAsync()和sendAllAsync() - 条件自动配置 — 仅当模块位于类路径中时,才会加载相应的渠道 bean
- 统一事件系统 —
NotificationEventBus取代分散的监听器调用,并通过LegacyListenerAdapter保持向后兼容
Maven Central
NotifyHub 已发布到 Maven Central。无需添加其他仓库。
在 Maven Central 上搜索:io.github.gabrielbbaldez
可用模块
下方列出了所有模块、其用途、适用场景以及添加方式。
notify-spring-boot-starter — 主要依赖
用途: 在 Spring Boot 应用中自动配置 NotifyHub。自动发现渠道 bean,配置重试策略、跟踪、速率限制、DLQ、Micrometer 指标、OpenTelemetry 跟踪、Actuator 健康检查和 Spring 事件。还会传递引入 notify-core 和 notify-email。
适用场景: 你正在构建 Spring Boot 应用,并希望自动完成设置。对于大多数项目,这是唯一必需的依赖。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
notify-core — 核心 API(无 Spring)
用途: 包含完整的流式 API(NotifyHub、NotificationBuilder、Channel、Notification、Priority、Attachment、RetryPolicy),以及渠道、模板、跟踪、DLQ、速率限制和路由相关接口。不依赖 Spring — 仅使用 SLF4J 和 Mustache。
适用场景: 你希望在不使用 Spring Boot 的纯 Java 项目中使用 NotifyHub,或基于它构建库/框架。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-core</artifactId>
<version>1.0.0</version>
</dependency>
notify-email — SMTP 邮件渠道
功能: 通过任意 SMTP 服务器(Gmail、Outlook、Amazon SES、Mailtrap 等)发送电子邮件。支持 HTML 和纯文本、文件附件、TLS/SSL 以及自定义发件人名称。内部使用 Jakarta Mail。
适用场景: 需要发送电子邮件通知。notify-spring-boot-starter 已包含此功能。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-email</artifactId>
<version>1.0.0</version>
</dependency>
notify-sms — Twilio SMS + WhatsApp 渠道
功能: 通过 Twilio API 发送 SMS 和 WhatsApp 消息。自动处理电话号码格式(E.164)和 whatsapp: 前缀。
适用场景: 需要发送 SMS 或 WhatsApp 消息。需要 Twilio 账号、Account SID、Auth Token 和电话号码。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-sms</artifactId>
<version>1.0.0</version>
</dependency>
notify-slack — Slack Webhook 渠道
功能: 通过 Incoming Webhooks 向 Slack 频道发送消息。使用 JDK HttpClient,无需外部 SDK。
适用场景: 需要向 Slack 发布通知。需要 Slack Incoming Webhook URL(在 api.slack.com/apps 创建)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-slack</artifactId>
<version>1.0.0</version>
</dependency>
notify-telegram — Telegram Bot 渠道
功能: 通过 Bot API 向 Telegram 聊天、群组和频道发送消息。支持默认聊天 ID 和按通知指定目标。使用 JDK HttpClient。
适用场景: 需要发送 Telegram 消息。需要从 @BotFather 获取 Bot Token。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-telegram</artifactId>
<version>1.0.0</version>
</dependency>
notify-discord — Discord Webhook 渠道
功能: 通过 Webhook 向 Discord 频道发送消息。支持自定义 Bot 用户名和头像。使用 JDK HttpClient。
适用场景: 需要向 Discord 发布通知。需要 Discord Webhook URL(频道设置 > 集成 > Webhook)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-discord</artifactId>
<version>1.0.0</version>
</dependency>
notify-teams — Microsoft Teams 渠道
功能: 通过 Incoming Webhooks 向 Teams 频道发送 MessageCard 通知。使用 JDK HttpClient。
适用场景: 需要向 Microsoft Teams 发布通知。需要 Teams Incoming Webhook URL(频道 > 连接器 > Incoming Webhook)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-teams</artifactId>
<version>1.0.0</version>
</dependency>
notify-push-firebase — Firebase Cloud Messaging (FCM)
功能: 通过 Firebase Cloud Messaging 向移动设备(Android/iOS)和 Web 应用发送推送通知。使用 Firebase Admin SDK 和服务账号凭据。
适用场景: 需要向移动应用发送推送通知。需要包含服务账号 JSON 凭据文件的 Firebase 项目。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-push-firebase</artifactId>
<version>1.0.0</version>
</dependency>
notify-webhook — 通用 Webhook 渠道
功能: 向任意 HTTP 端点(REST API、PagerDuty、Datadog、自定义服务)发送通知。支持可配置的负载模板,其中包含 {{recipient}}、{{subject}}、{{content}} 占位符,以及自定义标头、PUT/POST 方法和超时设置。
适用场景: 需要与任何提供 HTTP API 的外部服务集成,或创建自定义 Webhook 集成。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-webhook</artifactId>
<version>1.0.0</version>
</dependency>
notify-websocket — WebSocket 渠道
功能: 使用 JDK java.net.http.WebSocket API 通过 WebSocket 连接发送通知。支持可配置的消息格式,其中包含 {{recipient}}、{{subject}}、{{content}} 占位符,以及自定义标头、自动重连与退避机制和连接超时。零外部依赖。
适用场景: 需要通过 WebSocket 向服务端发送实时通知(例如实时仪表板、聊天系统或自定义 WebSocket 消费端)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-websocket</artifactId>
<version>1.0.0</version>
</dependency>
notify-google-chat — Google Chat 渠道
功能: 通过 Incoming Webhooks 向 Google Chat 空间发送消息。使用 JDK HttpClient 发送 JSON 负载,无需外部 SDK。
适用场景: 需要向 Google Chat 空间发送通知。需要 Google Chat Webhook URL(空间设置 > 应用和集成 > Webhook)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-google-chat</artifactId>
<version>1.0.0</version>
</dependency>
notify-twitch — Twitch 频道
**功能:**通过 Helix API 向 Twitch 频道发送聊天消息和投票。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你想向 Twitch 聊天室发送通知或创建投票。需要 Twitch API OAuth 2.0 凭据(Client ID + OAuth 令牌)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-twitch</artifactId>
<version>1.0.0</version>
</dependency>
notify-youtube — YouTube 频道
**功能:**通过 YouTube Data API v3 向 YouTube 直播发送聊天消息。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你想向 YouTube 直播聊天室发送通知。需要 Google API 密钥,或启用了 YouTube Data API v3 的 OAuth 2.0 凭据。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-youtube</artifactId>
<version>1.0.0</version>
</dependency>
notify-instagram — Instagram 频道
**功能:**通过 Meta Graph API(Instagram Graph API)发送私信和动态帖子。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你想通过 Instagram 发送通知。需要拥有 Instagram Graph API 访问权限的 Facebook Developer 账户。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-instagram</artifactId>
<version>1.0.0</version>
</dependency>
notify-sendgrid — SendGrid 邮件频道
**功能:**通过 SendGrid API 发送事务性邮件,并内置投递事件跟踪(已送达、已打开、已点击、退信)。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你需要超越基本 SMTP 的邮件投递跟踪,或者已经使用 SendGrid 作为邮件服务提供商。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-sendgrid</artifactId>
<version>1.0.0</version>
</dependency>
notify-tiktok-shop — TikTok Shop 频道
**功能:**通过 TikTok Shop API 向 TikTok Shop 卖家发送消息。自动处理 HMAC-SHA256 请求签名。使用 JDK HttpClient。
**适用场景:**你想向 TikTok Shop 卖家发送通知(订单更新、客户消息)。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-tiktok-shop</artifactId>
<version>1.0.0</version>
</dependency>
notify-facebook — Facebook 频道
**功能:**通过 Graph API 发布 Facebook 专页帖子并发送 Messenger 消息。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你想在 Facebook 专页发布内容或发送 Messenger 消息。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-facebook</artifactId>
<version>1.0.0</version>
</dependency>
notify-whatsapp — WhatsApp Cloud API 频道
**功能:**直接通过 Meta 的 Cloud API 发送 WhatsApp 消息(无需 Twilio)。使用 JDK HttpClient,没有任何外部依赖。
**适用场景:**你想使用 Meta 官方 Cloud API,而不是 Twilio,来发送 WhatsApp 消息。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-whatsapp</artifactId>
<version>1.0.0</version>
</dependency>
notify-aws-sns — AWS SNS 频道
**功能:**向 AWS SNS 主题发布消息,或通过 AWS Simple Notification Service 直接发送 SMS。使用 AWS SDK v2。
**适用场景:**你已在使用 AWS 生态,并想使用 SNS 发送通知。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-aws-sns</artifactId>
<version>1.0.0</version>
</dependency>
notify-mailgun — Mailgun 频道
**功能:**通过 Mailgun REST API 发送事务性邮件。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你使用 Mailgun 作为邮件服务提供商。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-mailgun</artifactId>
<version>1.0.0</version>
</dependency>
notify-pagerduty — PagerDuty 频道
**功能:**通过 Events API v2 创建 PagerDuty 事件。使用 JDK HttpClient,无需外部 SDK。
**适用场景:**你想从通知流水线触发 PagerDuty 警报/事件。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-pagerduty</artifactId>
<version>1.0.0</version>
</dependency>
notify-kick — Kick 频道
**功能:**通过 Kick Public API 向 Kick 频道发送聊天消息。支持使用 OAuth 2.1 身份验证和令牌刷新功能的机器人及用户消息类型。
**适用场景:**你想从通知流水线向 Kick 直播频道发送聊天消息。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-kick</artifactId>
<version>1.0.0</version>
</dependency>
notify-tracker-jpa — JPA 投递跟踪器
**功能:**使用 Spring Data JPA 将投递回执持久化到关系型数据库(MySQL、PostgreSQL、H2 等)。存储通知 ID、频道、收件人、状态、时间戳和错误消息。提供用于筛选和计数的查询方法。
**适用场景:**你希望投递跟踪数据在重启后仍然保留(而不是使用默认的内存跟踪器)。需要类路径中包含 Spring Data JPA 和数据库。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-tracker-jpa</artifactId>
<version>1.0.0</version>
</dependency>
notify-admin — 管理仪表板
功能: 在 /notify-admin 提供内置 Web UI,包含 4 个页面:仪表板(概览指标)、跟踪(送达回执)、DLQ(发送失败的通知)和渠道(状态)。使用 Thymeleaf 构建,采用深色主题,完全支持响应式布局。
适用场景: 你想要一个可视化管理面板来监控通知系统,而不必从头构建。需要在配置中设置 notify.admin.enabled=true。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-admin</artifactId>
<version>1.0.0</version>
</dependency>
notify-queue-rabbitmq — RabbitMQ 消息队列
功能: 通过 RabbitMQ 添加异步通知处理。包含生产者(将通知加入队列)、消费者(从队列读取通知并通过 NotifyHub 发送),以及带有交换机、队列和绑定设置的 Spring Boot 自动配置。
适用场景: 你需要将通知发送与主应用程序流程解耦,或者你的系统采用微服务架构,由一个服务将通知加入队列,另一个服务负责发送。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-queue-rabbitmq</artifactId>
<version>1.0.0</version>
</dependency>
notify-queue-kafka — Apache Kafka 消息队列
功能: 与 RabbitMQ 模块相同,但使用 Apache Kafka 作为消息代理。将通知发送到 Kafka 主题,并使用 channel:recipient 作为消息键来保证分区顺序。
适用场景: 你的基础设施已在使用 Kafka,或者你需要大规模、高吞吐量地处理通知。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-queue-kafka</artifactId>
<version>1.0.0</version>
</dependency>
notify-mcp — 面向 AI Agent 的 MCP 服务
功能: 将 NotifyHub 的所有渠道作为 MCP(Model Context Protocol)工具公开,让 AI Agent(Claude Desktop、Claude Code、Cursor)能够通过自然语言命令发送通知。它以无头 Spring Boot 应用的形式运行,通过 STDIO JSON-RPC 进行通信。提供 27 个工具:通过任意渠道发送、批量发送、受众管理、DLQ 监控和送达分析。
适用场景: 你希望 AI Agent 代表你发送通知。在 MCP 客户端的配置文件中设置 JAR 路径,Agent 会自动发现所有可用工具。
<dependency>
<groupId>io.github.gabrielbbaldez</groupId>
<artifactId>notify-mcp</artifactId>
<version>1.0.0</version>
</dependency>
我需要什么?
| 我想要…… | 添加这些依赖 |
|---|---|
| 从 Spring Boot 发送邮件 | notify-spring-boot-starter(已包含邮件功能) |
| 发送 SMS 或 WhatsApp 消息 | notify-spring-boot-starter + notify-sms |
| 发送到 Slack | notify-spring-boot-starter + notify-slack |
| 发送到 Telegram | notify-spring-boot-starter + notify-telegram |
| 发送到 Discord | notify-spring-boot-starter + notify-discord |
| 发送到 Microsoft Teams | notify-spring-boot-starter + notify-teams |
| 发送移动推送通知(FCM) | notify-spring-boot-starter + notify-push-firebase |
| 发送到任意 HTTP API | notify-spring-boot-starter + notify-webhook |
| 通过 WebSocket 发送 | notify-spring-boot-starter + notify-websocket |
| 发送到 Google Chat | notify-spring-boot-starter + notify-google-chat |
| 发送到 Twitch 聊天 | notify-spring-boot-starter + notify-twitch |
| 发送到 YouTube 直播聊天 | notify-spring-boot-starter + notify-youtube |
| 发送到 Instagram | notify-spring-boot-starter + notify-instagram |
| 通过 SendGrid 发送(含跟踪) | notify-spring-boot-starter + notify-sendgrid |
| 发送到 TikTok Shop | notify-spring-boot-starter + notify-tiktok-shop |
| 发送到 Facebook Page/Messenger | notify-spring-boot-starter + notify-facebook |
| 通过 Cloud API 发送 WhatsApp 消息 | notify-spring-boot-starter + notify-whatsapp |
| 通过 AWS SNS 发送 | notify-spring-boot-starter + notify-aws-sns |
| 通过 Mailgun 发送 | notify-spring-boot-starter + notify-mailgun |
| 创建 PagerDuty 事件 | notify-spring-boot-starter + notify-pagerduty |
| 发送 Kick 聊天消息 | notify-spring-boot-starter + notify-kick |
| 防止重复发送 | notify-spring-boot-starter(内置,由配置驱动) |
| 对模板进行 A/B 测试 | notify-spring-boot-starter(内置,使用 .templateVersion()) |
| 将跟踪数据持久化到数据库 | notify-spring-boot-starter + notify-tracker-jpa |
| 管理面板 UI | notify-spring-boot-starter + notify-admin |
| 不使用 Spring Boot | notify-core + 所需的渠道模块 |
| 通过 RabbitMQ 进行异步处理 | notify-spring-boot-starter + notify-queue-rabbitmq |
| 通过 Kafka 进行异步处理 | notify-spring-boot-starter + notify-queue-kafka |
| 让 AI Agent 发送通知 | notify-mcp(独立 JAR) |
| 一次性获取全部功能 | notify-spring-boot-starter + 上述所有渠道模块 |
路线图
- v0.1.0 — 核心 API、电子邮件、短信、WhatsApp、Mustache 模板、Spring Boot starter
- v0.2.0 — Slack、Telegram、Discord、异步发送、定时发送、投递跟踪
- v0.3.0 — Teams、Firebase Push、Webhook、附件、优先级、速率限制、DLQ、国际化、批量发送、JPA 跟踪器、Micrometer 指标、Actuator 健康检查、Spring 事件、条件路由、管理仪表盘(80+ 项测试)
- v0.4.0 — WebSocket 通道、Google Chat 通道、消息去重、模板版本控制(105+ 项测试,16 个模块)
- v0.5.0 — MCP 服务模块:13 个 AI Agent 工具,可通过 Claude Desktop、Claude Code、Cursor 发送通知(130+ 项测试,17 个模块)
- v0.6.0 — 命名收件人、Docker 镜像(MCP + REST API)、Swagger UI、RabbitMQ + Kafka 消息队列模块、GitHub Pages 着陆页
- v0.7.0 — Twitter/X、LinkedIn、Notion 通道(14 个通道、16 个 MCP 工具、22 个模块)
- v0.8.0 — Twitch、YouTube 通道、管理仪表盘重新设计(16 个通道、18 个 MCP 工具、24 个模块)
- v0.9.0 — MCP 高级工具:受众、联系人、批量发送、DLQ、分析(16 个通道、26 个 MCP 工具)
- v0.10.0 — Instagram 通道:通过 Meta Graph API 发送私信和信息流帖子(17 个通道、27 个 MCP 工具、25 个模块)
- v1.0.0 — SendGrid、TikTok Shop、Facebook、WhatsApp Cloud API、AWS SNS、Mailgun、PagerDuty 通道,定时通知 MCP 工具,JaCoCo 覆盖率(25 个通道、37 个 MCP 工具、28 个模块)
- v1.1.0 — 架构改进:弹性处理管道(断路器、舱壁、处理器链)、统一事件系统(NotificationEventBus、EventType、MetricsEventListener)、上帝对象重构(从 NotifyHub 中提取 NotificationExecutor、NotificationScheduler)、多通道编排、内置 A/B 测试、Cron 定时、静默时段、TestNotifyHub 测试工具、通道模板模块、Levenshtein 错误建议、增强型健康指示器(含断路器状态)
要求
- Java 17+
- Spring Boot 3.x(用于 starter,可选;核心功能可独立运行)
- Maven 3.8+(用于构建)
许可证
MIT 许可证 — 详情请参阅 LICENSE。
由 Gabriel Baldez 构建
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。