smtp2go-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SMTP2GO 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

RegionBase 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
区域基础URL
全球
https://api.smtp2go.com/v3
美国
https://us-api.smtp2go.com/v3
欧盟
https://eu-api.smtp2go.com/v3
澳大利亚
https://au-api.smtp2go.com/v3

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/send
typescript
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/send
typescript
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/mime
For 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/add
typescript
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/add
typescript
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
{{ variable }}
placeholders.
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

模板相关端点

EndpointMethodDescription
/template/add
POSTCreate new template
/template/edit
POSTUpdate existing template
/template/delete
POSTRemove template
/template/search
POSTList/search templates
/template/view
POSTGet template details
端点请求方法描述
/template/add
POST创建新模板
/template/edit
POST更新现有模板
/template/delete
POST删除模板
/template/search
POST列出/搜索模板
/template/view
POST获取模板详情

Webhooks

Webhook配置

Configure webhooks to receive real-time delivery notifications.
配置Webhook以接收实时投递通知。

Event Types

事件类型

Email Events:
EventDescription
processed
Email queued for delivery
delivered
Successfully delivered
open
Recipient opened email
click
Link clicked
bounce
Delivery failed
spam
Marked as spam
unsubscribe
User unsubscribed
resubscribe
User resubscribed
reject
Blocked (suppression/sandbox)
SMS Events:
EventDescription
sending
Processing
submitted
Sent to provider
delivered
Confirmed delivery
failed
Delivery failed
rejected
Network blocked
opt-out
Recipient opted out
邮件事件:
事件描述
processed
邮件已进入投递队列
delivered
邮件成功投递
open
收件人已打开邮件
click
收件人点击了邮件链接
bounce
投递失败(退信)
spam
邮件被标记为垃圾邮件
unsubscribe
用户取消订阅
resubscribe
用户重新订阅
reject
邮件被拦截(在抑制列表/沙箱环境中)
SMS事件:
事件描述
sending
正在处理中
submitted
已提交给运营商
delivered
已确认投递成功
failed
投递失败
rejected
被网络拦截
opt-out
收件人退订

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/add
typescript
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/add
typescript
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相关端点

EndpointMethodDescription
/webhook/view
POSTList webhooks
/webhook/add
POSTCreate webhook
/webhook/edit
POSTUpdate webhook
/webhook/remove
POSTDelete webhook
Retry Policy: Up to 35 retries over 48 hours. Timeout: 10 seconds.
端点请求方法描述
/webhook/view
POST列出所有Webhook
/webhook/add
POST创建Webhook
/webhook/edit
POST更新Webhook
/webhook/remove
POST删除Webhook
重试策略: 48小时内最多重试35次。超时时间:10秒。

Statistics

统计信息

Email Summary

邮件汇总统计

POST
/stats/email_summary
Combined 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

统计相关端点

EndpointMethodDescription
/stats/email_summary
POSTCombined statistics
/stats/email_bounces
POSTBounce summary (30 days)
/stats/email_cycle
POSTEmail cycle data
/stats/email_history
POSTHistorical data
/stats/email_spam
POSTSpam reports
/stats/email_unsubs
POSTUnsubscribe data
端点请求方法描述
/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取消订阅数据

Activity Search

活动搜索

POST
/activity/search
(Rate limited: 60/min)
Search 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
/activity/search
(速率限制:60次/分钟)
搜索邮件事件:
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/add
typescript
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/add
typescript
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

抑制列表相关端点

EndpointMethodDescription
/suppression/add
POSTAdd to suppression list
/suppression/view
POSTView suppressions
/suppression/remove
POSTRemove from list
端点请求方法描述
/suppression/add
POST添加到抑制列表
/suppression/view
POST查看抑制列表
/suppression/remove
POST从列表中移除

SMS

SMS功能

POST
/sms/send
typescript
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/send
typescript
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相关端点

EndpointMethodDescription
/sms/send
POSTSend SMS
/sms/received
POSTView received SMS
/sms/sent
POSTView sent SMS
/sms/summary
POSTSMS statistics
端点请求方法描述
/sms/send
POST发送SMS
/sms/received
POST查看收到的SMS
/sms/sent
POST查看已发送的SMS
/sms/summary
POSTSMS统计信息

Response Codes

响应码

CodeStatusDescription
200OKSuccess
400Bad RequestInvalid parameters
401UnauthorizedInvalid/missing API key
402Request FailedValid params, request failed
403ForbiddenInsufficient permissions
404Not FoundResource not found
429Too Many RequestsRate limited
5xxServer ErrorSMTP2GO 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:
  • E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED
    - API key lacks permission
  • E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD
    - Invalid JSON/email format
  • E_ApiResponseCodes.API_EXCEPTION
    - General API error
typescript
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错误

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-XXXXXXXXXXXX
typescript
// 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-XXXXXXXXXXXX
typescript
// 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:
  1. Sender Domain (Recommended): Add and verify domain in SMTP2GO dashboard for SPF/DKIM alignment
  2. Single Sender Email: Verify individual email address
Unverified senders are rejected with 400 error.
发送邮件前,需验证发件人身份:
  1. 发件人域名(推荐): 在SMTP2GO控制台添加并验证域名,以实现SPF/DKIM对齐
  2. 单个发件人邮箱: 验证单个邮箱地址
未验证的发件人会被拒绝,返回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} &lt;${email}&gt;</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} &lt;${email}&gt;</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

故障排查

IssueCauseSolution
401 UnauthorizedMissing/invalid API keyCheck API key in header or body
400 sender not verifiedUnverified sender domainVerify domain in SMTP2GO dashboard
429 Too Many RequestsRate limit exceededImplement exponential backoff
Attachment too largeOver 50MB totalCompress or use URL references
Template variables not replacedWrong syntaxUse
{{ variable }}
Handlebars syntax
Webhook not receiving eventsTimeout/errorsCheck endpoint returns 200 within 10s
问题原因解决方案
401未授权API密钥缺失/无效检查请求头或请求体中的API密钥
400发件人未验证发件人域名未验证在SMTP2GO控制台验证域名
429请求过多触发速率限制实现指数退避重试机制
附件过大总大小超过50MB压缩文件或使用URL引用形式
模板变量未替换语法错误使用
{{ variable }}
格式的Handlebars语法
Webhook未收到事件超时/端点错误检查端点是否能在10秒内返回200状态码

References

参考链接