smtp2go-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSMTP2GO API Integration
SMTP2GO API 集成
Build email and SMS delivery with the SMTP2GO transactional API.
借助SMTP2GO事务性API实现邮件与SMS投递功能。
Quick Start
快速开始
typescript
// 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" } }typescript
// 借助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" } }Base URLs
基础URL
| Region | Base URL |
|---|---|
| Global | |
| US | |
| EU | |
| AU | |
| 区域 | 基础URL |
|---|---|
| 全球 | |
| 美国 | |
| 欧盟 | |
| 澳大利亚 | |
Authentication
认证方式
Two methods supported:
typescript
// 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
支持两种认证方法:
typescript
// 方法1:请求头(推荐)
headers: {
'X-Smtp2go-Api-Key': 'your-api-key'
}
// 方法2:请求体
body: JSON.stringify({
api_key: 'your-api-key',
// ... 其他参数
})从SMTP2GO控制台获取API密钥:发送 > API密钥
Core Endpoints
核心端点
Send Standard Email
发送标准邮件
POST
/email/sendtypescript
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:
typescript
interface EmailSendResponse {
request_id: string;
data: {
succeeded: number;
failed: number;
failures: string[];
email_id: string;
};
}POST
/email/sendtypescript
interface EmailSendRequest {
// 必填项
sender: string; // 已验证的发件人邮箱
to: string[]; // 收件人(最多100个)
subject: string;
// 内容(至少填一项)
html_body?: string;
text_body?: string;
// 可选项
cc?: string[]; // 抄送人(最多100个)
bcc?: string[]; // 密送人(最多100个)
reply_to?: string;
custom_headers?: Array<{ header: string; value: string }>;
attachments?: Attachment[];
inlines?: InlineImage[];
// 模板相关
template_id?: string;
template_data?: Record<string, any>;
// 子账户
subaccount_id?: string;
}
interface Attachment {
filename: string;
mimetype: string;
fileblob?: string; // Base64编码的内容
url?: string; // 或内容的获取URL
}
interface InlineImage {
filename: string;
mimetype: string;
fileblob: string;
cid: string; // HTML引用的内容ID
}响应:
typescript
interface EmailSendResponse {
request_id: string;
data: {
succeeded: number;
failed: number;
failures: string[];
email_id: string;
};
}Send MIME Email
发送MIME格式邮件
POST
/email/mimeFor pre-encoded MIME messages:
typescript
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,
}),
});POST
/email/mime适用于预编码的MIME消息:
typescript
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,
}),
});Attachments
附件处理
Base64 Encoding
Base64编码
typescript
// 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',
}],
};typescript
// 将文件转换为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',
}],
};URL Reference (Cached 24h)
URL引用(缓存24小时)
typescript
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',
}],
};typescript
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',
}],
};Inline Images in HTML
HTML中的内嵌图片
typescript
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)
typescript
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', // 在HTML中通过src="cid:logo123"引用
}],
};限制: 邮件总大小上限为50MB(内容+附件+请求头)
Templates
模板管理
Create Template
创建模板
POST
/template/addtypescript
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 }}.',
}),
});POST
/template/addtypescript
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 }}.',
}),
});Send with Template
使用模板发送邮件
typescript
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 placeholders.
{{ variable }}typescript
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的占位符格式。
{{ variable }}Template Endpoints
模板相关端点
| Endpoint | Method | Description |
|---|---|---|
| POST | Create new template |
| POST | Update existing template |
| POST | Remove template |
| POST | List/search templates |
| POST | Get template details |
| 端点 | 请求方法 | 描述 |
|---|---|---|
| POST | 创建新模板 |
| POST | 更新现有模板 |
| POST | 删除模板 |
| POST | 列出/搜索模板 |
| POST | 获取模板详情 |
Webhooks
Webhook配置
Configure webhooks to receive real-time delivery notifications.
配置Webhook以接收实时投递通知。
Event Types
事件类型
Email Events:
| Event | Description |
|---|---|
| Email queued for delivery |
| Successfully delivered |
| Recipient opened email |
| Link clicked |
| Delivery failed |
| Marked as spam |
| User unsubscribed |
| User resubscribed |
| Blocked (suppression/sandbox) |
SMS Events:
| Event | Description |
|---|---|
| Processing |
| Sent to provider |
| Confirmed delivery |
| Delivery failed |
| Network blocked |
| Recipient opted out |
邮件事件:
| 事件 | 描述 |
|---|---|
| 邮件已进入投递队列 |
| 邮件成功投递 |
| 收件人已打开邮件 |
| 收件人点击了邮件链接 |
| 投递失败(退信) |
| 邮件被标记为垃圾邮件 |
| 用户取消订阅 |
| 用户重新订阅 |
| 邮件被拦截(在抑制列表/沙箱环境中) |
SMS事件:
| 事件 | 描述 |
|---|---|
| 正在处理中 |
| 已提交给运营商 |
| 已确认投递成功 |
| 投递失败 |
| 被网络拦截 |
| 收件人退订 |
Webhook Payload (Email)
Webhook负载(邮件)
typescript
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;
}typescript
interface WebhookPayload {
event: string;
time: string; // 事件时间戳
sendtime: string; // 原始发送时间
sender: string;
from_address: string;
rcpt: string; // 收件人
recipients: string[];
email_id: string;
subject: string;
bounce?: string; // 退信类型(若适用)
client?: string; // 邮件客户端(针对打开事件)
'geoip-country'?: string;
}Webhook Configuration
Webhook配置方法
POST
/webhook/addtypescript
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'],
}),
});POST
/webhook/addtypescript
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 Endpoints
Webhook相关端点
| Endpoint | Method | Description |
|---|---|---|
| POST | List webhooks |
| POST | Create webhook |
| POST | Update webhook |
| POST | Delete webhook |
Retry Policy: Up to 35 retries over 48 hours. Timeout: 10 seconds.
| 端点 | 请求方法 | 描述 |
|---|---|---|
| POST | 列出所有Webhook |
| POST | 创建Webhook |
| POST | 更新Webhook |
| POST | 删除Webhook |
重试策略: 48小时内最多重试35次。超时时间:10秒。
Statistics
统计信息
Email Summary
邮件汇总统计
POST
/stats/email_summaryCombined report of bounces, cycles, spam, and unsubscribes.
typescript
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({}),
});POST
/stats/email_summary包含退信、循环投递、垃圾邮件报告和取消订阅的综合统计。
typescript
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({}),
});Statistics Endpoints
统计相关端点
| Endpoint | Method | Description |
|---|---|---|
| POST | Combined statistics |
| POST | Bounce summary (30 days) |
| POST | Email cycle data |
| POST | Historical data |
| POST | Spam reports |
| POST | Unsubscribe data |
| 端点 | 请求方法 | 描述 |
|---|---|---|
| POST | 综合统计信息 |
| POST | 退信汇总(最近30天) |
| POST | 邮件循环投递数据 |
| POST | 历史统计数据 |
| POST | 垃圾邮件报告统计 |
| POST | 取消订阅数据 |
Activity Search
活动搜索
POST (Rate limited: 60/min)
/activity/searchSearch for email events:
typescript
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.
POST (速率限制:60次/分钟)
/activity/search搜索邮件事件:
typescript
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({
// 过滤参数
}),
});注意: 最多返回1000条数据。如需实时数据,建议使用Webhook。
Suppressions
抑制列表管理
Manage email addresses that should not receive emails.
管理不应接收邮件的邮箱地址。
Add Suppression
添加抑制地址
POST
/suppression/addtypescript
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',
}),
});POST
/suppression/addtypescript
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 Endpoints
抑制列表相关端点
| Endpoint | Method | Description |
|---|---|---|
| POST | Add to suppression list |
| POST | View suppressions |
| POST | Remove from list |
| 端点 | 请求方法 | 描述 |
|---|---|---|
| POST | 添加到抑制列表 |
| POST | 查看抑制列表 |
| POST | 从列表中移除 |
SMS
SMS功能
POST
/sms/sendtypescript
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',
}),
});POST
/sms/sendtypescript
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'], // 最多100个号码
message: 'Your verification code is 123456',
}),
});SMS Endpoints
SMS相关端点
| Endpoint | Method | Description |
|---|---|---|
| POST | Send SMS |
| POST | View received SMS |
| POST | View sent SMS |
| POST | SMS statistics |
| 端点 | 请求方法 | 描述 |
|---|---|---|
| POST | 发送SMS |
| POST | 查看收到的SMS |
| POST | 查看已发送的SMS |
| POST | SMS统计信息 |
Response Codes
响应码
| 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 |
| 状态码 | 状态 | 描述 |
|---|---|---|
| 200 | 成功 | 请求处理成功 |
| 400 | 错误请求 | 参数无效 |
| 401 | 未授权 | API密钥无效/缺失 |
| 402 | 请求失败 | 参数有效但请求执行失败 |
| 403 | 禁止访问 | 权限不足 |
| 404 | 未找到 | 资源不存在 |
| 429 | 请求过多 | 触发速率限制 |
| 5xx | 服务器错误 | SMTP2GO服务器端问题 |
Error Response Format
错误响应格式
typescript
interface ErrorResponse {
request_id: string;
data: {
error: string;
error_code: string;
field_validation_errors?: Record<string, string>;
};
}Common error codes:
- - API key lacks permission
E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED - - Invalid JSON/email format
E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD - - General API error
E_ApiResponseCodes.API_EXCEPTION
typescript
interface ErrorResponse {
request_id: string;
data: {
error: string;
error_code: string;
field_validation_errors?: Record<string, string>;
};
}常见错误码:
- - API密钥缺少对应权限
E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED - - JSON/邮箱格式无效
E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD - - 通用API错误
E_ApiResponseCodes.API_EXCEPTION
Rate Limiting
速率限制
- Activity Search: 60 requests/minute
- Email Search (deprecated): 20 requests/minute
- Other endpoints: Configurable per API key
Handling 429:
typescript
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');
}- 活动搜索: 60次/分钟
- 邮件搜索(已废弃): 20次/分钟
- 其他端点: 速率限制可通过API密钥配置
处理429错误:
typescript
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');
}Cloudflare Workers Integration
Cloudflare Workers集成
typescript
// wrangler.jsonc
{
"name": "email-service",
"vars": {
"SMTP2GO_REGION": "api" // or "us-api", "eu-api", "au-api"
}
}
// .dev.vars
SMTP2GO_API_KEY=api-XXXXXXXXXXXXtypescript
// 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;
}typescript
// wrangler.jsonc
{
"name": "email-service",
"vars": {
"SMTP2GO_REGION": "api" // 或 "us-api", "eu-api", "au-api"
}
}
// .dev.vars
SMTP2GO_API_KEY=api-XXXXXXXXXXXXtypescript
// src/index.ts
export default {
async fetch(request: Request, env: Env) {
const baseUrl = `https://${env.SMTP2GO_REGION}.smtp2go.com/v3`;
// 发送事务性邮件
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;
}Sender Verification
发件人验证
Before sending, verify your sender identity:
- Sender Domain (Recommended): Add and verify domain in SMTP2GO dashboard for SPF/DKIM alignment
- Single Sender Email: Verify individual email address
Unverified senders are rejected with 400 error.
发送邮件前,需验证发件人身份:
- 发件人域名(推荐): 在SMTP2GO控制台添加并验证域名,以实现SPF/DKIM对齐
- 单个发件人邮箱: 验证单个邮箱地址
未验证的发件人会被拒绝,返回400错误。
Common Patterns
常见应用场景
Contact Form Handler
联系表单处理器
typescript
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();
}typescript
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();
}Webhook Handler
Webhook处理器
typescript
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 });
}typescript
export async function handleWebhook(request: Request) {
const payload = await request.json();
switch (payload.event) {
case 'bounce':
// 处理退信 - 更新用户记录、重试逻辑
console.log(`Bounce: ${payload.rcpt} - ${payload.bounce}`);
break;
case 'unsubscribe':
// 更新用户偏好
console.log(`Unsubscribe: ${payload.rcpt}`);
break;
case 'spam':
// 添加到抑制列表、通知团队
console.log(`Spam report: ${payload.rcpt}`);
break;
}
return new Response('OK', { status: 200 });
}Troubleshooting
故障排查
| 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 |
| Webhook not receiving events | Timeout/errors | Check endpoint returns 200 within 10s |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 401未授权 | API密钥缺失/无效 | 检查请求头或请求体中的API密钥 |
| 400发件人未验证 | 发件人域名未验证 | 在SMTP2GO控制台验证域名 |
| 429请求过多 | 触发速率限制 | 实现指数退避重试机制 |
| 附件过大 | 总大小超过50MB | 压缩文件或使用URL引用形式 |
| 模板变量未替换 | 语法错误 | 使用 |
| Webhook未收到事件 | 超时/端点错误 | 检查端点是否能在10秒内返回200状态码 |
References
参考链接
Last Updated: 2026-02-06
API Version: v3.0.3