Mailgun: 托管式事务邮件集成 - Openclaw Skills
作者:互联网
2026-03-29
什么是 Mailgun?
Mailgun 技能提供了一种通过托管网关与 Mailgun API 交互的简便方式。通过利用 Openclaw Skills,开发人员可以绕过复杂的跳转式 OAuth 处理和区域端点配置。此集成允许对电子邮件基础设施进行稳健管理,包括域名验证、路由创建以及大规模邮件列表的管理。
该技能专为可靠性和安全性而设计,默认将请求代理到 Mailgun 美国区域,并自动注入必要的凭据。它提供了一个开发人员友好的界面来处理整个电子邮件生命周期——从使用 Handlebars 模板撰写邮件到通过 Webhooks 和统计端点监控投递事件。
下载入口:https://github.com/openclaw/skills/tree/main/skills/byungkyu/mailgun-api
安装与下载
1. ClawHub CLI
从源直接安装技能的最快方式。
npx clawhub@latest install mailgun-api
2. 手动安装
将技能文件夹复制到以下位置之一
全局模式~/.openclaw/skills/
工作区
/skills/
优先级:工作区 > 本地 > 内置
3. 提示词安装
将此提示词复制到 OpenClaw 即可自动安装。
请帮我使用 Clawhub 安装 mailgun-api。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
Mailgun 应用场景
- 自动发送事务性通知,如欢迎邮件和密码重置。
- 以编程方式管理用于发送电子邮件的 DNS 域名和 SMTP 凭据。
- 通过自动成员订阅逻辑创建和维护邮件列表。
- 通过 Webhooks 实时追踪电子邮件参与度指标,如打开、点击和退信。
- 实施复杂的电子邮件路由规则以转发或存储传入邮件。
- 用户通过请求头中的 Bearer 令牌使用 Maton API 密钥进行身份验证。
- 通过控制平面初始化连接,通过 OAuth 关联特定的 Mailgun 账户。
- 该技能通过处理令牌注入和区域代理的托管网关路由 API 调用。
- 用户使用表单编码数据与域名、消息和路由等标准 Mailgun 资源进行交互。
- 网关处理响应(包括基于游标的分页链接)并将其返回给客户端。
Mailgun 配置指南
要初始化该技能,请在环境中设置 API 密钥并创建活动连接。
# 设置您的 API 密钥
export MATON_API_KEY="YOUR_API_KEY"
# 创建 Mailgun 连接
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'mailgun'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
在浏览器中打开 JSON 响应中提供的 URL 以授权连接。
Mailgun 数据架构与分类体系
该技能围绕标准 Mailgun 实体组织数据。对于列表资源,响应通常遵循分页结构。
| 资源 | 主要数据组件 |
|---|---|
| 域名 (Domains) | 名称、状态、SMTP 凭据和区域设置。 |
| 消息 (Messages) | 发件人详细信息、收件人列表、正文内容 (Text/HTML) 和模板 ID。 |
| 路由 (Routes) | 优先级、过滤表达式和转发动作。 |
| 事件 (Events) | 事件类型(已投递、已打开等)、时间戳和收件人元数据。 |
| 邮件列表 (Mailing Lists) | 列表地址、访问权限级别和成员数量。 |
| 抑制 (Suppressions) | 退信代码、退订标签和投诉地址。 |
name: mailgun
description: |
Mailgun API integration with managed OAuth. Transactional email service for sending, receiving, and tracking emails.
Use this skill when users want to send emails, manage domains, routes, templates, mailing lists, or suppressions in Mailgun.
For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
compatibility: Requires network access and valid Maton API key
metadata:
author: maton
version: "1.0"
clawdbot:
emoji: ??
homepage: "https://maton.ai"
requires:
env:
- MATON_API_KEY
Mailgun
Access the Mailgun API with managed OAuth authentication. Send transactional emails, manage domains, routes, templates, mailing lists, suppressions, and webhooks.
Quick Start
# List domains
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/mailgun/v3/domains')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://gateway.maton.ai/mailgun/v3/{resource}
Replace {resource} with the actual Mailgun API endpoint path. The gateway proxies requests to api.mailgun.net/v3 (US region) and automatically injects your OAuth token.
Regional Note: Mailgun has US and EU regions. The gateway defaults to US region (api.mailgun.net).
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Mailgun OAuth connections at https://ctrl.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=mailgun&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'mailgun'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "78b5a036-c621-40c2-b74b-276195735af2",
"status": "ACTIVE",
"creation_time": "2026-02-12T02:24:16.551210Z",
"last_updated_time": "2026-02-12T02:25:03.542838Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "mailgun",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Mailgun connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/mailgun/v3/domains')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '78b5a036-c621-40c2-b74b-276195735af2')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If omitted, the gateway uses the default (oldest) active connection.
API Reference
Important: Mailgun API uses application/x-www-form-urlencoded for POST/PUT requests, not JSON.
Domains
List Domains
GET /mailgun/v3/domains
Returns all domains for the account.
Get Domain
GET /mailgun/v3/domains/{domain_name}
Create Domain
POST /mailgun/v3/domains
Content-Type: application/x-www-form-urlencoded
name=example.com&smtp_password=supersecret
Delete Domain
DELETE /mailgun/v3/domains/{domain_name}
Messages
Send Message
POST /mailgun/v3/{domain_name}/messages
Content-Type: application/x-www-form-urlencoded
from=sender@example.com&to=recipient@example.com&subject=Hello&text=Hello World
Parameters:
from(required) - Sender email addressto(required) - Recipient(s), comma-separatedcc- CC recipientsbcc- BCC recipientssubject(required) - Email subjecttext- Plain text bodyhtml- HTML bodytemplate- Name of stored template to useo:tag- Tag for trackingo:tracking- Enable/disable tracking (yes/no)o:tracking-clicks- Enable click trackingo:tracking-opens- Enable open trackingh:X-Custom-Header- Custom headers (prefix with h:)v:custom-var- Custom variables for templates (prefix with v:)
Send MIME Message
POST /mailgun/v3/{domain_name}/messages.mime
Content-Type: multipart/form-data
to=recipient@example.com&message=
Events
List Events
GET /mailgun/v3/{domain_name}/events
Query parameters:
begin- Start time (RFC 2822 or Unix timestamp)end- End timeascending- Sort order (yes/no)limit- Results per page (max 300)event- Filter by event type (accepted, delivered, failed, opened, clicked, unsubscribed, complained, stored)from- Filter by senderto- Filter by recipienttags- Filter by tags
Routes
Routes are defined globally per account, not per domain.
List Routes
GET /mailgun/v3/routes
Query parameters:
skip- Number of records to skiplimit- Number of records to return
Create Route
POST /mailgun/v3/routes
Content-Type: application/x-www-form-urlencoded
priority=0&description=My Route&expression=match_recipient(".*@example.com")&action=forward("https://example.com/webhook")
Parameters:
priority- Route priority (lower = higher priority)description- Route descriptionexpression- Filter expression (match_recipient, match_header, catch_all)action- Action(s) to take (forward, store, stop)
Get Route
GET /mailgun/v3/routes/{route_id}
Update Route
PUT /mailgun/v3/routes/{route_id}
Content-Type: application/x-www-form-urlencoded
priority=1&description=Updated Route
Delete Route
DELETE /mailgun/v3/routes/{route_id}
Webhooks
List Webhooks
GET /mailgun/v3/domains/{domain_name}/webhooks
Create Webhook
POST /mailgun/v3/domains/{domain_name}/webhooks
Content-Type: application/x-www-form-urlencoded
id=delivered&url=https://example.com/webhook
Webhook types: accepted, delivered, opened, clicked, unsubscribed, complained, permanent_fail, temporary_fail
Get Webhook
GET /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
Update Webhook
PUT /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
Content-Type: application/x-www-form-urlencoded
url=https://example.com/new-webhook
Delete Webhook
DELETE /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
Templates
List Templates
GET /mailgun/v3/{domain_name}/templates
Create Template
POST /mailgun/v3/{domain_name}/templates
Content-Type: application/x-www-form-urlencoded
name=my-template&description=Welcome email&template=Hello {{name}}
Get Template
GET /mailgun/v3/{domain_name}/templates/{template_name}
Delete Template
DELETE /mailgun/v3/{domain_name}/templates/{template_name}
Mailing Lists
List Mailing Lists
GET /mailgun/v3/lists/pages
Create Mailing List
POST /mailgun/v3/lists
Content-Type: application/x-www-form-urlencoded
address=newsletter@example.com&name=Newsletter&description=Monthly newsletter&access_level=readonly
Access levels: readonly, members, everyone
Get Mailing List
GET /mailgun/v3/lists/{list_address}
Update Mailing List
PUT /mailgun/v3/lists/{list_address}
Content-Type: application/x-www-form-urlencoded
name=Updated Newsletter
Delete Mailing List
DELETE /mailgun/v3/lists/{list_address}
Mailing List Members
List Members
GET /mailgun/v3/lists/{list_address}/members/pages
Add Member
POST /mailgun/v3/lists/{list_address}/members
Content-Type: application/x-www-form-urlencoded
address=member@example.com&name=John Doe&subscribed=yes
Get Member
GET /mailgun/v3/lists/{list_address}/members/{member_address}
Update Member
PUT /mailgun/v3/lists/{list_address}/members/{member_address}
Content-Type: application/x-www-form-urlencoded
name=Jane Doe&subscribed=no
Delete Member
DELETE /mailgun/v3/lists/{list_address}/members/{member_address}
Suppressions
Bounces
# List bounces
GET /mailgun/v3/{domain_name}/bounces
# Add bounce
POST /mailgun/v3/{domain_name}/bounces
Content-Type: application/x-www-form-urlencoded
address=bounced@example.com&code=550&error=Mailbox not found
# Get bounce
GET /mailgun/v3/{domain_name}/bounces/{address}
# Delete bounce
DELETE /mailgun/v3/{domain_name}/bounces/{address}
Unsubscribes
# List unsubscribes
GET /mailgun/v3/{domain_name}/unsubscribes
# Add unsubscribe
POST /mailgun/v3/{domain_name}/unsubscribes
Content-Type: application/x-www-form-urlencoded
address=unsubscribed@example.com&tag=*
# Delete unsubscribe
DELETE /mailgun/v3/{domain_name}/unsubscribes/{address}
Complaints
# List complaints
GET /mailgun/v3/{domain_name}/complaints
# Add complaint
POST /mailgun/v3/{domain_name}/complaints
Content-Type: application/x-www-form-urlencoded
address=complainer@example.com
# Delete complaint
DELETE /mailgun/v3/{domain_name}/complaints/{address}
Whitelists
# List whitelists
GET /mailgun/v3/{domain_name}/whitelists
# Add to whitelist
POST /mailgun/v3/{domain_name}/whitelists
Content-Type: application/x-www-form-urlencoded
address=allowed@example.com
# Delete from whitelist
DELETE /mailgun/v3/{domain_name}/whitelists/{address}
Statistics
Get Stats
GET /mailgun/v3/{domain_name}/stats/total?event=delivered&event=opened
Query parameters:
event(required) - Event type(s): accepted, delivered, failed, opened, clicked, unsubscribed, complainedstart- Start date (RFC 2822 or Unix timestamp)end- End dateresolution- Data resolution (hour, day, month)duration- Period to show stats for
Tags
List Tags
GET /mailgun/v3/{domain_name}/tags
Get Tag
GET /mailgun/v3/{domain_name}/tags/{tag_name}
Delete Tag
DELETE /mailgun/v3/{domain_name}/tags/{tag_name}
IPs
List IPs
GET /mailgun/v3/ips
Get IP
GET /mailgun/v3/ips/{ip_address}
Domain Tracking
Get Tracking Settings
GET /mailgun/v3/domains/{domain_name}/tracking
Update Open Tracking
PUT /mailgun/v3/domains/{domain_name}/tracking/open
Content-Type: application/x-www-form-urlencoded
active=yes
Update Click Tracking
PUT /mailgun/v3/domains/{domain_name}/tracking/click
Content-Type: application/x-www-form-urlencoded
active=yes
Update Unsubscribe Tracking
PUT /mailgun/v3/domains/{domain_name}/tracking/unsubscribe
Content-Type: application/x-www-form-urlencoded
active=yes&html_footer=Unsubscribe
Credentials
List Credentials
GET /mailgun/v3/domains/{domain_name}/credentials
Create Credential
POST /mailgun/v3/domains/{domain_name}/credentials
Content-Type: application/x-www-form-urlencoded
login=alice&password=supersecret
Delete Credential
DELETE /mailgun/v3/domains/{domain_name}/credentials/{login}
Pagination
Mailgun uses cursor-based pagination:
{
"items": [...],
"paging": {
"first": "https://api.mailgun.net/v3/.../pages?page=first&limit=100",
"last": "https://api.mailgun.net/v3/.../pages?page=last&limit=100",
"next": "https://api.mailgun.net/v3/.../pages?page=next&limit=100",
"previous": "https://api.mailgun.net/v3/.../pages?page=prev&limit=100"
}
}
Use limit parameter to control page size (default: 100).
Code Examples
JavaScript - Send Email
const formData = new URLSearchParams();
formData.append('from', 'sender@example.com');
formData.append('to', 'recipient@example.com');
formData.append('subject', 'Hello');
formData.append('text', 'Hello World!');
const response = await fetch(
'https://gateway.maton.ai/mailgun/v3/example.com/messages',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
}
);
const result = await response.json();
console.log(result);
Python - Send Email
import os
import requests
response = requests.post(
'https://gateway.maton.ai/mailgun/v3/example.com/messages',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
data={
'from': 'sender@example.com',
'to': 'recipient@example.com',
'subject': 'Hello',
'text': 'Hello World!'
}
)
print(response.json())
Python - List Domains
import os
import requests
response = requests.get(
'https://gateway.maton.ai/mailgun/v3/domains',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
domains = response.json()
for domain in domains['items']:
print(f"{domain['name']}: {domain['state']}")
Python - Create Route and Webhook
import os
import requests
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
domain = 'example.com'
# Create route
route_response = requests.post(
'https://gateway.maton.ai/mailgun/v3/routes',
headers=headers,
data={
'priority': 0,
'description': 'Forward to webhook',
'expression': 'match_recipient("support@example.com")',
'action': 'forward("https://myapp.com/incoming-email")'
}
)
print(f"Route created: {route_response.json()}")
# Create webhook
webhook_response = requests.post(
f'https://gateway.maton.ai/mailgun/v3/domains/{domain}/webhooks',
headers=headers,
data={
'id': 'delivered',
'url': 'https://myapp.com/webhook/delivered'
}
)
print(f"Webhook created: {webhook_response.json()}")
Notes
- Mailgun uses
application/x-www-form-urlencodedfor POST/PUT requests, not JSON - Domain names must be included in most endpoint paths
- Routes are global (per account), not per domain
- Sandbox domains require authorized recipients for sending
- Dates are returned in RFC 2822 format
- Event logs are stored for at least 3 days
- Stats require at least one
eventparameter - Templates use Handlebars syntax by default
- IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jq, environment variables may not expand correctly. Use Python examples instead.
Rate Limits
| Operation | Limit |
|---|---|
| Sending | Varies by plan |
| API calls | No hard limit, but excessive requests may be throttled |
When rate limited, implement exponential backoff for retries.
Error Handling
| Status | Meaning |
|---|---|
| 400 | Bad request or missing Mailgun connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden (e.g., sandbox domain restrictions) |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Mailgun API |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
mailgun. For example:
- Correct:
https://gateway.maton.ai/mailgun/v3/domains - Incorrect:
https://gateway.maton.ai/v3/domains
Troubleshooting: Sandbox Domain Restrictions
Sandbox domains can only send to authorized recipients. To send emails:
- Upgrade to a paid plan, or
- Add recipient addresses to authorized recipients in the Mailgun dashboard
Resources
- Mailgun API Documentation
- Mailgun API Reference
- Mailgun Postman Collection
- Maton Community
- Maton Support
相关推荐
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
信号管道:自动化营销情报工具 - Openclaw Skills
技能收益追踪器:监控 Openclaw 技能并实现变现
AI 合规准备就绪度:评估与治理工具 - Openclaw Skills
FOSMVVM ServerRequest 测试生成器:自动化 API 测试 - Openclaw Skills
酒店搜索器:AI 赋能的住宿与位置情报 - Openclaw Skills
Dub 链接 API:程序化链接管理 - Openclaw Skills
IntercomSwap:P2P BTC 与 USDT 跨链兑换 - Openclaw Skills
spotplay:macOS 原生 Spotify 播放控制 - Openclaw Skills
DeepSeek OCR:AI驱动的图像文本识别 - Openclaw Skills
Web Navigator:自动化网页研究与浏览 - Openclaw Skills
AI精选
