smtp2go-api by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill smtp2go-api使用 SMTP2GO 事务型 API 构建电子邮件和短信发送功能。
// Send email with SMTP2GO
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'noreply@yourdomain.com',
to: ['recipient@example.com'],
subject: 'Hello from SMTP2GO',
html_body: '<h1>Welcome!</h1><p>Your account is ready.</p>',
text_body: 'Welcome! Your account is ready.',
}),
});
const result = await response.json();
// { request_id: "uuid", data: { succeeded: 1, failed: 0, email_id: "1er8bV-6Tw0Mi-7h" } }
| 区域 | 基础 URL |
|---|---|
| 全球 | https://api.smtp2go.com/v3 |
| 美国 | https://us-api.smtp2go.com/v3 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 欧洲 | https://eu-api.smtp2go.com/v3 |
| 澳大利亚 | https://au-api.smtp2go.com/v3 |
支持两种方法:
// Method 1: Header (recommended)
headers: {
'X-Smtp2go-Api-Key': 'your-api-key'
}
// Method 2: Request body
body: JSON.stringify({
api_key: 'your-api-key',
// ... other params
})
从 SMTP2GO 仪表板获取 API 密钥:发送 > API 密钥
POST /email/send
interface EmailSendRequest {
// Required
sender: string; // Verified sender email
to: string[]; // Recipients (max 100)
subject: string;
// Content (at least one required)
html_body?: string;
text_body?: string;
// Optional
cc?: string[]; // CC recipients (max 100)
bcc?: string[]; // BCC recipients (max 100)
reply_to?: string;
custom_headers?: Array<{ header: string; value: string }>;
attachments?: Attachment[];
inlines?: InlineImage[];
// Templates
template_id?: string;
template_data?: Record<string, any>;
// Subaccounts
subaccount_id?: string;
}
interface Attachment {
filename: string;
mimetype: string;
fileblob?: string; // Base64-encoded content
url?: string; // OR URL to fetch from
}
interface InlineImage {
filename: string;
mimetype: string;
fileblob: string;
cid: string; // Content-ID for HTML reference
}
响应:
interface EmailSendResponse {
request_id: string;
data: {
succeeded: number;
failed: number;
failures: string[];
email_id: string;
};
}
POST /email/mime
用于预编码的 MIME 消息:
const response = await fetch('https://api.smtp2go.com/v3/email/mime', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
mime_email: mimeEncodedString,
}),
});
// Convert file to base64
const fileBuffer = await file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(fileBuffer)));
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Document attached',
text_body: 'Please find the document attached.',
attachments: [{
filename: 'report.pdf',
fileblob: base64,
mimetype: 'application/pdf',
}],
};
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Image attached',
text_body: 'Photo from our event.',
attachments: [{
filename: 'photo.jpg',
url: 'https://cdn.example.com/photos/event.jpg',
mimetype: 'image/jpeg',
}],
};
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Newsletter',
html_body: '<h1>Welcome</h1><img src="cid:logo123" alt="Logo">',
inlines: [{
filename: 'logo.png',
fileblob: logoBase64,
mimetype: 'image/png',
cid: 'logo123', // Reference in HTML as src="cid:logo123"
}],
};
限制: 最大电子邮件总大小:50 MB(内容 + 附件 + 头部)
POST /template/add
const response = await fetch('https://api.smtp2go.com/v3/template/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
template_name: 'welcome-email',
html_body: '<h1>Welcome, {{ name }}!</h1><p>Thanks for joining {{ company }}.</p>',
text_body: 'Welcome, {{ name }}! Thanks for joining {{ company }}.',
}),
});
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Welcome aboard!',
template_id: 'template-uuid-here',
template_data: {
name: 'John',
company: 'Acme Corp',
},
};
模板语法: 使用带有 {{ 变量 }} 占位符的 HandlebarsJS。
| 端点 | 方法 | 描述 |
|---|---|---|
/template/add | POST | 创建新模板 |
/template/edit | POST | 更新现有模板 |
/template/delete | POST | 删除模板 |
/template/search | POST | 列出/搜索模板 |
/template/view | POST | 获取模板详细信息 |
配置 webhooks 以接收实时投递通知。
电子邮件事件:
| 事件 | 描述 |
|---|---|
processed | 电子邮件已排队等待投递 |
delivered | 成功投递 |
open | 收件人打开了电子邮件 |
click | 链接被点击 |
bounce | 投递失败 |
spam | 被标记为垃圾邮件 |
unsubscribe | 用户取消订阅 |
resubscribe | 用户重新订阅 |
reject | 被阻止(抑制列表/沙盒) |
短信事件:
| 事件 | 描述 |
|---|---|
sending | 处理中 |
submitted | 已发送给提供商 |
delivered | 确认投递 |
failed | 投递失败 |
rejected | 网络阻止 |
opt-out | 收件人选择退出 |
interface WebhookPayload {
event: string;
time: string; // Event timestamp
sendtime: string; // Original send time
sender: string;
from_address: string;
rcpt: string; // Recipient
recipients: string[];
email_id: string;
subject: string;
bounce?: string; // Bounce type if applicable
client?: string; // Email client (for opens)
'geoip-country'?: string;
}
POST /webhook/add
await fetch('https://api.smtp2go.com/v3/webhook/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
url: 'https://api.yourdomain.com/webhooks/smtp2go',
events: ['delivered', 'bounce', 'spam', 'unsubscribe'],
}),
});
| 端点 | 方法 | 描述 |
|---|---|---|
/webhook/view | POST | 列出 webhooks |
/webhook/add | POST | 创建 webhook |
/webhook/edit | POST | 更新 webhook |
/webhook/remove | POST | 删除 webhook |
重试策略: 48 小时内最多重试 35 次。超时时间:10 秒。
POST /stats/email_summary
包含退回、周期、垃圾邮件和取消订阅的综合报告。
const response = await fetch('https://api.smtp2go.com/v3/stats/email_summary', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({}),
});
| 端点 | 方法 | 描述 |
|---|---|---|
/stats/email_summary | POST | 综合统计 |
/stats/email_bounces | POST | 退回摘要(30 天) |
/stats/email_cycle | POST | 电子邮件周期数据 |
/stats/email_history | POST | 历史数据 |
/stats/email_spam | POST | 垃圾邮件报告 |
/stats/email_unsubs | POST | 取消订阅数据 |
POST /activity/search(速率限制:60 次/分钟)
搜索电子邮件事件:
const response = await fetch('https://api.smtp2go.com/v3/activity/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
// Filter parameters
}),
});
注意: 最多返回 1,000 个项目。对于实时数据,请改用 webhooks。
管理不应接收电子邮件的电子邮件地址。
POST /suppression/add
await fetch('https://api.smtp2go.com/v3/suppression/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
email: 'blocked@example.com',
}),
});
| 端点 | 方法 | 描述 |
|---|---|---|
/suppression/add | POST | 添加到抑制列表 |
/suppression/view | POST | 查看抑制列表 |
/suppression/remove | POST | 从列表中移除 |
POST /sms/send
const response = await fetch('https://api.smtp2go.com/v3/sms/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
to: ['+61400000000'], // Max 100 numbers
message: 'Your verification code is 123456',
}),
});
| 端点 | 方法 | 描述 |
|---|---|---|
/sms/send | POST | 发送短信 |
/sms/received | POST | 查看接收到的短信 |
/sms/sent | POST | 查看已发送的短信 |
/sms/summary | POST | 短信统计 |
| 代码 | 状态 | 描述 |
|---|---|---|
| 200 | OK | 成功 |
| 400 | Bad Request | 无效参数 |
| 401 | Unauthorized | 无效/缺少 API 密钥 |
| 402 | Request Failed | 参数有效,但请求失败 |
| 403 | Forbidden | 权限不足 |
| 404 | Not Found | 资源未找到 |
| 429 | Too Many Requests | 速率限制 |
| 5xx | Server Error | SMTP2GO 服务器问题 |
interface ErrorResponse {
request_id: string;
data: {
error: string;
error_code: string;
field_validation_errors?: Record<string, string>;
};
}
常见错误代码:
E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED - API 密钥缺少权限E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD - 无效的 JSON/电子邮件格式E_ApiResponseCodes.API_EXCEPTION - 通用 API 错误处理 429 错误:
async function sendWithRetry(payload: any, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify(payload),
});
if (response.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
continue;
}
return response.json();
}
throw new Error('Rate limit exceeded after retries');
}
// wrangler.jsonc
{
"name": "email-service",
"vars": {
"SMTP2GO_REGION": "api" // or "us-api", "eu-api", "au-api"
}
}
// .dev.vars
SMTP2GO_API_KEY=api-XXXXXXXXXXXX
// src/index.ts
export default {
async fetch(request: Request, env: Env) {
const baseUrl = `https://${env.SMTP2GO_REGION}.smtp2go.com/v3`;
// Send transactional email
const response = await fetch(`${baseUrl}/email/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'noreply@yourdomain.com',
to: ['user@example.com'],
subject: 'Order Confirmation',
template_id: 'order-confirmation-template',
template_data: {
order_id: '12345',
total: '$99.00',
},
}),
});
const result = await response.json();
return Response.json(result);
},
} satisfies ExportedHandler<Env>;
interface Env {
SMTP2GO_API_KEY: string;
SMTP2GO_REGION: string;
}
在发送之前,请验证您的发件人身份:
未经验证的发送者将被拒绝并返回 400 错误。
export async function handleContactForm(formData: FormData, env: Env) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'website@yourdomain.com',
to: ['support@yourdomain.com'],
reply_to: email,
subject: `Contact form: ${name}`,
text_body: `From: ${name} <${email}>\n\n${message}`,
html_body: `
<p><strong>From:</strong> ${name} <${email}></p>
<hr>
<p>${message.replace(/\n/g, '<br>')}</p>
`,
}),
});
if (!response.ok) {
throw new Error('Failed to send email');
}
return response.json();
}
export async function handleWebhook(request: Request) {
const payload = await request.json();
switch (payload.event) {
case 'bounce':
// Handle bounce - update user record, retry logic
console.log(`Bounce: ${payload.rcpt} - ${payload.bounce}`);
break;
case 'unsubscribe':
// Update preferences
console.log(`Unsubscribe: ${payload.rcpt}`);
break;
case 'spam':
// Add to suppression, alert team
console.log(`Spam report: ${payload.rcpt}`);
break;
}
return new Response('OK', { status: 200 });
}
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 401 未授权 | 缺少/无效的 API 密钥 | 检查头部或正文中的 API 密钥 |
| 400 发件人未验证 | 未验证的发件人域名 | 在 SMTP2GO 仪表板中验证域名 |
| 429 请求过多 | 超出速率限制 | 实现指数退避 |
| 附件过大 | 超过 50MB 总大小 | 压缩或使用 URL 引用 |
| 模板变量未替换 | 语法错误 | 使用 {{ 变量 }} Handlebars 语法 |
| Webhook 未接收事件 | 超时/错误 | 检查端点是否在 10 秒内返回 200 |
最后更新: 2026-02-06 API 版本: v3.0.3
每周安装次数
110
仓库
GitHub 星标数
643
首次出现
2026年2月6日
安全审计
安装于
claude-code91
replit82
opencode73
gemini-cli67
codex62
cursor62
Build email and SMS delivery with the SMTP2GO transactional API.
// Send email with SMTP2GO
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'noreply@yourdomain.com',
to: ['recipient@example.com'],
subject: 'Hello from SMTP2GO',
html_body: '<h1>Welcome!</h1><p>Your account is ready.</p>',
text_body: 'Welcome! Your account is ready.',
}),
});
const result = await response.json();
// { request_id: "uuid", data: { succeeded: 1, failed: 0, email_id: "1er8bV-6Tw0Mi-7h" } }
| Region | Base URL |
|---|---|
| Global | https://api.smtp2go.com/v3 |
| US | https://us-api.smtp2go.com/v3 |
| EU | https://eu-api.smtp2go.com/v3 |
| AU | https://au-api.smtp2go.com/v3 |
Two methods supported:
// Method 1: Header (recommended)
headers: {
'X-Smtp2go-Api-Key': 'your-api-key'
}
// Method 2: Request body
body: JSON.stringify({
api_key: 'your-api-key',
// ... other params
})
Get API keys from SMTP2GO dashboard: Sending > API Keys
POST /email/send
interface EmailSendRequest {
// Required
sender: string; // Verified sender email
to: string[]; // Recipients (max 100)
subject: string;
// Content (at least one required)
html_body?: string;
text_body?: string;
// Optional
cc?: string[]; // CC recipients (max 100)
bcc?: string[]; // BCC recipients (max 100)
reply_to?: string;
custom_headers?: Array<{ header: string; value: string }>;
attachments?: Attachment[];
inlines?: InlineImage[];
// Templates
template_id?: string;
template_data?: Record<string, any>;
// Subaccounts
subaccount_id?: string;
}
interface Attachment {
filename: string;
mimetype: string;
fileblob?: string; // Base64-encoded content
url?: string; // OR URL to fetch from
}
interface InlineImage {
filename: string;
mimetype: string;
fileblob: string;
cid: string; // Content-ID for HTML reference
}
Response:
interface EmailSendResponse {
request_id: string;
data: {
succeeded: number;
failed: number;
failures: string[];
email_id: string;
};
}
POST /email/mime
For pre-encoded MIME messages:
const response = await fetch('https://api.smtp2go.com/v3/email/mime', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
mime_email: mimeEncodedString,
}),
});
// Convert file to base64
const fileBuffer = await file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(fileBuffer)));
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Document attached',
text_body: 'Please find the document attached.',
attachments: [{
filename: 'report.pdf',
fileblob: base64,
mimetype: 'application/pdf',
}],
};
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Image attached',
text_body: 'Photo from our event.',
attachments: [{
filename: 'photo.jpg',
url: 'https://cdn.example.com/photos/event.jpg',
mimetype: 'image/jpeg',
}],
};
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Newsletter',
html_body: '<h1>Welcome</h1><img src="cid:logo123" alt="Logo">',
inlines: [{
filename: 'logo.png',
fileblob: logoBase64,
mimetype: 'image/png',
cid: 'logo123', // Reference in HTML as src="cid:logo123"
}],
};
Limits: Maximum total email size: 50 MB (content + attachments + headers)
POST /template/add
const response = await fetch('https://api.smtp2go.com/v3/template/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
template_name: 'welcome-email',
html_body: '<h1>Welcome, {{ name }}!</h1><p>Thanks for joining {{ company }}.</p>',
text_body: 'Welcome, {{ name }}! Thanks for joining {{ company }}.',
}),
});
const email = {
sender: 'noreply@example.com',
to: ['user@example.com'],
subject: 'Welcome aboard!',
template_id: 'template-uuid-here',
template_data: {
name: 'John',
company: 'Acme Corp',
},
};
Template Syntax: HandlebarsJS with {{ variable }} placeholders.
| Endpoint | Method | Description |
|---|---|---|
/template/add | POST | Create new template |
/template/edit | POST | Update existing template |
/template/delete | POST | Remove template |
/template/search | POST | List/search templates |
/template/view | POST | Get template details |
Configure webhooks to receive real-time delivery notifications.
Email Events:
| Event | Description |
|---|---|
processed | Email queued for delivery |
delivered | Successfully delivered |
open | Recipient opened email |
click | Link clicked |
bounce | Delivery failed |
spam | Marked as spam |
SMS Events:
| Event | Description |
|---|---|
sending | Processing |
submitted | Sent to provider |
delivered | Confirmed delivery |
failed | Delivery failed |
rejected | Network blocked |
opt-out | Recipient opted out |
interface WebhookPayload {
event: string;
time: string; // Event timestamp
sendtime: string; // Original send time
sender: string;
from_address: string;
rcpt: string; // Recipient
recipients: string[];
email_id: string;
subject: string;
bounce?: string; // Bounce type if applicable
client?: string; // Email client (for opens)
'geoip-country'?: string;
}
POST /webhook/add
await fetch('https://api.smtp2go.com/v3/webhook/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
url: 'https://api.yourdomain.com/webhooks/smtp2go',
events: ['delivered', 'bounce', 'spam', 'unsubscribe'],
}),
});
| Endpoint | Method | Description |
|---|---|---|
/webhook/view | POST | List webhooks |
/webhook/add | POST | Create webhook |
/webhook/edit | POST | Update webhook |
/webhook/remove | POST | Delete webhook |
Retry Policy: Up to 35 retries over 48 hours. Timeout: 10 seconds.
POST /stats/email_summary
Combined report of bounces, cycles, spam, and unsubscribes.
const response = await fetch('https://api.smtp2go.com/v3/stats/email_summary', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({}),
});
| Endpoint | Method | Description |
|---|---|---|
/stats/email_summary | POST | Combined statistics |
/stats/email_bounces | POST | Bounce summary (30 days) |
/stats/email_cycle | POST | Email cycle data |
/stats/email_history | POST | Historical data |
/stats/email_spam | POST |
POST /activity/search (Rate limited: 60/min)
Search for email events:
const response = await fetch('https://api.smtp2go.com/v3/activity/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
// Filter parameters
}),
});
Note: Returns max 1,000 items. For real-time data, use webhooks instead.
Manage email addresses that should not receive emails.
POST /suppression/add
await fetch('https://api.smtp2go.com/v3/suppression/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
email: 'blocked@example.com',
}),
});
| Endpoint | Method | Description |
|---|---|---|
/suppression/add | POST | Add to suppression list |
/suppression/view | POST | View suppressions |
/suppression/remove | POST | Remove from list |
POST /sms/send
const response = await fetch('https://api.smtp2go.com/v3/sms/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
to: ['+61400000000'], // Max 100 numbers
message: 'Your verification code is 123456',
}),
});
| Endpoint | Method | Description |
|---|---|---|
/sms/send | POST | Send SMS |
/sms/received | POST | View received SMS |
/sms/sent | POST | View sent SMS |
/sms/summary | POST | SMS statistics |
| Code | Status | Description |
|---|---|---|
| 200 | OK | Success |
| 400 | Bad Request | Invalid parameters |
| 401 | Unauthorized | Invalid/missing API key |
| 402 | Request Failed | Valid params, request failed |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limited |
| 5xx | Server Error | SMTP2GO server issue |
interface ErrorResponse {
request_id: string;
data: {
error: string;
error_code: string;
field_validation_errors?: Record<string, string>;
};
}
Common error codes:
E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED - API key lacks permissionE_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD - Invalid JSON/email formatE_ApiResponseCodes.API_EXCEPTION - General API errorHandling 429:
async function sendWithRetry(payload: any, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify(payload),
});
if (response.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
continue;
}
return response.json();
}
throw new Error('Rate limit exceeded after retries');
}
// wrangler.jsonc
{
"name": "email-service",
"vars": {
"SMTP2GO_REGION": "api" // or "us-api", "eu-api", "au-api"
}
}
// .dev.vars
SMTP2GO_API_KEY=api-XXXXXXXXXXXX
// src/index.ts
export default {
async fetch(request: Request, env: Env) {
const baseUrl = `https://${env.SMTP2GO_REGION}.smtp2go.com/v3`;
// Send transactional email
const response = await fetch(`${baseUrl}/email/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'noreply@yourdomain.com',
to: ['user@example.com'],
subject: 'Order Confirmation',
template_id: 'order-confirmation-template',
template_data: {
order_id: '12345',
total: '$99.00',
},
}),
});
const result = await response.json();
return Response.json(result);
},
} satisfies ExportedHandler<Env>;
interface Env {
SMTP2GO_API_KEY: string;
SMTP2GO_REGION: string;
}
Before sending, verify your sender identity:
Unverified senders are rejected with 400 error.
export async function handleContactForm(formData: FormData, env: Env) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'website@yourdomain.com',
to: ['support@yourdomain.com'],
reply_to: email,
subject: `Contact form: ${name}`,
text_body: `From: ${name} <${email}>\n\n${message}`,
html_body: `
<p><strong>From:</strong> ${name} <${email}></p>
<hr>
<p>${message.replace(/\n/g, '<br>')}</p>
`,
}),
});
if (!response.ok) {
throw new Error('Failed to send email');
}
return response.json();
}
export async function handleWebhook(request: Request) {
const payload = await request.json();
switch (payload.event) {
case 'bounce':
// Handle bounce - update user record, retry logic
console.log(`Bounce: ${payload.rcpt} - ${payload.bounce}`);
break;
case 'unsubscribe':
// Update preferences
console.log(`Unsubscribe: ${payload.rcpt}`);
break;
case 'spam':
// Add to suppression, alert team
console.log(`Spam report: ${payload.rcpt}`);
break;
}
return new Response('OK', { status: 200 });
}
| Issue | Cause | Solution |
|---|---|---|
| 401 Unauthorized | Missing/invalid API key | Check API key in header or body |
| 400 sender not verified | Unverified sender domain | Verify domain in SMTP2GO dashboard |
| 429 Too Many Requests | Rate limit exceeded | Implement exponential backoff |
| Attachment too large | Over 50MB total | Compress or use URL references |
| Template variables not replaced | Wrong syntax | Use {{ variable }} Handlebars syntax |
| Webhook not receiving events | Timeout/errors | Check endpoint returns 200 within 10s |
Last Updated: 2026-02-06 API Version: v3.0.3
Weekly Installs
110
Repository
GitHub Stars
643
First Seen
Feb 6, 2026
Security Audits
Gen Agent Trust HubWarnSocketPassSnykPass
Installed on
claude-code91
replit82
opencode73
gemini-cli67
codex62
cursor62
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
96,200 周安装
unsubscribe| User unsubscribed |
resubscribe | User resubscribed |
reject | Blocked (suppression/sandbox) |
| Spam reports |
/stats/email_unsubs | POST | Unsubscribe data |