Mailgun 连接器
通过 Tajo 将 Mailgun 连接到 Brevo,统一您的交易和营销邮件数据,同步投递事件和参与指标,将您的邮件基础设施整合到单一客户视图中。
概览
| 属性 | 值 |
|---|---|
| 平台 | Mailgun(Sinch 旗下) |
| 类别 | 邮件营销 |
| 设置复杂度 | 简单 |
| 官方集成 | 否 |
| 同步数据 | 事件、联系人、投递率、营销活动 |
| 认证方式 | API 密钥(HTTP 基本认证) |
功能
- 投递事件同步 - 跟踪已投递、退回、已打开和已点击事件
- 参与指标 - 将打开率和点击率同步到 Brevo 联系人属性
- 退回管理 - 自动在 Brevo 中抑制退回地址
- 投诉处理 - 同步垃圾邮件投诉用于列表清洗
- 域名声誉 - 监控发件域名健康状况和投递率
- 交易邮件跟踪 - 将交易发送与营销数据关联
前提条件
开始之前,请确保您已具备:
- 具有已验证发件域名的 Mailgun 账户
- 来自 Mailgun 仪表板的 Mailgun API 密钥
- 具有 API 访问权限的 Brevo 账户
- 具有连接器权限的 Tajo 账户
认证
API 密钥认证
Mailgun 使用 HTTP 基本认证,以 api 作为用户名,您的 API 密钥作为密码:
# Get your API key from https://app.mailgun.com/settings/api_securityexport MAILGUN_API_KEY=key-your-api-keyexport MAILGUN_DOMAIN=your-domain.comexport TAJO_API_KEY=your_tajo_api_keyexport BREVO_API_KEY=your_brevo_api_key// HTTP Basic Auth formatconst headers = { 'Authorization': `Basic ${Buffer.from( `api:${process.env.MAILGUN_API_KEY}` ).toString('base64')}`};
// Or using curl// curl -s --user 'api:YOUR_API_KEY' ...API 密钥类型
Mailgun 提供域名专属发送密钥和账户级 API 密钥。消息操作使用域名发送密钥,管理操作使用账户 API 密钥。
配置
基础设置
connectors: mailgun: enabled: true api_key: "${MAILGUN_API_KEY}" domain: "${MAILGUN_DOMAIN}" region: "us" # or "eu" for EU region
sync: events: true contacts: true bounces: true complaints: true schedule: "*/15 * * * *" # Every 15 minutes
webhook: signing_key: "${MAILGUN_WEBHOOK_SIGNING_KEY}"
lists: engaged: 30 bounced: 31 complained: 32字段映射
field_mapping: email: email first_name: FIRSTNAME last_name: LASTNAME open_rate: MG_OPEN_RATE click_rate: MG_CLICK_RATE last_delivered: MG_LAST_DELIVERED bounce_type: MG_BOUNCE_TYPE engagement_score: MG_ENGAGEMENT unsubscribed: MG_UNSUBSCRIBEDAPI 端点
| 端点 | 方法 | 描述 |
|---|---|---|
https://api.mailgun.net/v3/{domain}/messages | POST | 发送邮件消息 |
https://api.mailgun.net/v3/{domain}/events | GET | 查询事件日志 |
https://api.mailgun.net/v3/{domain}/bounces | GET | 列出退回记录 |
https://api.mailgun.net/v3/{domain}/complaints | GET | 列出投诉记录 |
https://api.mailgun.net/v3/{domain}/unsubscribes | GET | 列出退订记录 |
https://api.mailgun.net/v3/{domain}/tags | GET | 列出标签 |
https://api.mailgun.net/v3/{domain}/tags/{tag}/stats | GET | 获取标签统计数据 |
https://api.mailgun.net/v3/lists | GET | 列出邮件列表 |
https://api.mailgun.net/v3/domains | GET | 列出域名 |
https://api.mailgun.net/v4/address/validate | POST | 验证邮件地址 |
欧盟区域
对于欧盟区域的 Mailgun 账户,所有 API 端点请使用 https://api.eu.mailgun.net 代替 https://api.mailgun.net。
代码示例
初始化连接器
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('mailgun', { apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN, region: 'us'});通过 Mailgun API 发送消息
// Send an email using Mailgun's Messages APIconst formData = new URLSearchParams();formData.append('from', `Your App <noreply@${domain}>`);formData.append('subject', 'Welcome to our platform');formData.append('html', '<h1>Welcome!</h1><p>Thanks for signing up.</p>');formData.append('o:tag', 'welcome-email');formData.append('o:tracking', 'yes');
const response = await fetch( `https://api.mailgun.net/v3/${domain}/messages`, { method: 'POST', headers: { 'Authorization': `Basic ${Buffer.from(`api:${apiKey}`).toString('base64')}` }, body: formData });
const result = await response.json();// { id: '<[email protected]>', message: 'Queued. Thank you.' }将邮件事件同步到 Brevo
// Query Mailgun events and sync engagement dataconst eventsResponse = await fetch( `https://api.mailgun.net/v3/${domain}/events?` + new URLSearchParams({ begin: lastSyncDate, ascending: 'yes', limit: 300, event: 'delivered OR opened OR clicked' }), { headers: { 'Authorization': `Basic ${Buffer.from(`api:${apiKey}`).toString('base64')}` } });
const { items, paging } = await eventsResponse.json();
for (const event of items) { const email = event.recipient;
switch (event.event) { case 'delivered': await tajo.contacts.update(email, { attributes: { MG_LAST_DELIVERED: event.timestamp } }); break; case 'opened': await tajo.events.track({ email, event: 'email_opened', properties: { subject: event.message.headers.subject } }); break; case 'clicked': await tajo.events.track({ email, event: 'email_clicked', properties: { url: event.url } }); break; }}
// Follow pagination for more eventsif (paging.next) { // Fetch next page using paging.next URL}处理 Mailgun Webhook
const crypto = require('crypto');
app.post('/webhooks/mailgun', async (req, res) => { // Verify webhook signature const { timestamp, token, signature } = req.body.signature; const encodedToken = crypto .createHmac('sha256', process.env.MAILGUN_WEBHOOK_SIGNING_KEY) .update(timestamp.concat(token)) .digest('hex');
if (encodedToken !== signature) { return res.status(401).send('Unauthorized'); }
const eventData = req.body['event-data']; const event = eventData.event; const email = eventData.recipient;
await tajo.connectors.handleWebhook('mailgun', { topic: event, payload: eventData });
// Handle bounce suppression if (event === 'failed' && eventData.severity === 'permanent') { await tajo.contacts.update(email, { attributes: { MG_BOUNCE_TYPE: 'hard_bounce' }, emailBlacklisted: true }); }
res.status(200).send('OK');});同步退回和投诉记录
// Sync bounced addresses for list hygieneconst bouncesResponse = await fetch( `https://api.mailgun.net/v3/${domain}/bounces?limit=100`, { headers: { 'Authorization': `Basic ${Buffer.from(`api:${apiKey}`).toString('base64')}` } });
const { items: bounces } = await bouncesResponse.json();
for (const bounce of bounces) { await tajo.contacts.update(bounce.address, { attributes: { MG_BOUNCE_TYPE: bounce.error.includes('550') ? 'hard_bounce' : 'soft_bounce', MG_BOUNCE_DATE: bounce.created_at }, emailBlacklisted: bounce.error.includes('550') });}速率限制
| 端点 | 限制 | 备注 |
|---|---|---|
| 消息 API | 根据计划而异 | 免费版 100/小时,付费版无限制 |
| 事件 API | 无明确限制 | 使用分页,每页最多 300 条 |
| 验证 API | 根据计划而定 | 按验证次数计费 |
| Webhook | 实时 | 投递无速率限制 |
| 抑制 API | 无明确限制 | 适用标准速率限制 |
发送限制
Mailgun 根据您的计划和域名声誉实施发送限制。新域名起始限制较低,随着发件人声誉提升而增加。在 Mailgun 仪表板中监控您的域名统计数据。
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 401 Unauthorized | API 密钥无效 | 在 Mailgun 仪表板中验证 API 密钥 |
| 域名未验证 | 缺少 DNS 记录 | 添加所需的 TXT、CNAME、MX 记录 |
| 未收到 Webhook | URL 无法访问 | 确保 Webhook URL 可公开访问 |
| 事件缺失 | 时间范围过窄 | 扩展 begin/end 参数 |
| 投递率低 | 域名声誉问题 | 检查域名统计数据和认证配置 |
调试模式
connectors: mailgun: debug: true log_level: verbose log_webhooks: true log_events: true最佳实践
- 验证发件域名 - 完成 DNS 验证以获得最佳投递率
- 使用 Webhook 获取事件 - 实时 Webhook 投递优于轮询事件 API
- 主动处理退回 - 立即在 Brevo 中抑制硬退回地址
- 为消息添加标签 - 使用标签对邮件绩效进行分类和分析
- 监控域名声誉 - 在 Mailgun 仪表板中跟踪投递率指标
- 使用邮箱验证 - 添加到 Brevo 列表前验证地址
安全
- HTTP 基本认证 - 通过 Authorization 请求头传输的 API 密钥
- Webhook 签名 - HMAC-SHA256 签名验证
- 域名验证 - SPF、DKIM 和 DMARC DNS 认证
- IP 白名单 - 专属 IP 计划可用
- TLS 加密 - 所有 API 端点均需要 HTTPS
- 密钥轮换 - 通过 Mailgun 仪表板定期轮换 API 密钥