pinme-email
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePinMe Worker Email API Integration
PinMe Worker 邮件API集成
Guides how to call PinMe platform's email sending API in a PinMe Worker (TypeScript).
指导如何在PinMe Worker(TypeScript)中调用PinMe平台的邮件发送API。
Environment Variables
环境变量
The following environment variables are automatically injected when the Worker is created — no manual configuration needed:
typescript
// backend/src/worker.ts
export interface Env {
DB: D1Database;
API_KEY: string; // Project API Key — used for send_email authentication
BASE_URL?: string; // Optional override for PinMe API base URL, defaults to https://pinme.cloud
}is the sole credential for the Worker to call PinMe platform APIs. WhenAPI_KEYis not set, it defaults toBASE_URL.https://pinme.cloud
创建Worker时会自动注入以下环境变量——无需手动配置:
typescript
// backend/src/worker.ts
export interface Env {
DB: D1Database;
API_KEY: string; // Project API Key — 用于send_email认证
BASE_URL?: string; // 可选的PinMe API基础URL覆盖,默认值为https://pinme.cloud
}是Worker调用PinMe平台API的唯一凭证。当未设置API_KEY时,默认值为BASE_URL。https://pinme.cloud
Send Email API
发送邮件API
Endpoint:
Authentication: header (using )
Sender: Automatically set to
POST {BASE_URL}/api/v4/send_emailX-API-Keyenv.API_KEY{project_name}@pinme.cloud端点:
认证方式: 请求头(使用)
发件人: 自动设置为
POST {BASE_URL}/api/v4/send_emailX-API-Keyenv.API_KEY{project_name}@pinme.cloudRequest Format
请求格式
json
{
"to": "user@example.com",
"subject": "Your verification code",
"html": "<p>Your code is <strong>123456</strong></p>"
}| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Recipient email address |
| string | Yes | Email subject |
| string | Yes | HTML body |
json
{
"to": "user@example.com",
"subject": "Your verification code",
"html": "<p>Your code is <strong>123456</strong></p>"
}| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
| string | 是 | 收件人邮箱地址 |
| string | 是 | 邮件主题 |
| string | 是 | HTML邮件正文 |
Response Format
响应格式
Success (200):
json
{ "code": 200, "msg": "ok", "data": { "ok": true } }Errors:
| HTTP Status | Meaning | data.error Example |
|---|---|---|
| 401 | API Key missing or invalid | |
| 400 | Parameter validation failed | |
| 500 | Email service error | |
成功(200):
json
{ "code": 200, "msg": "ok", "data": { "ok": true } }错误:
| HTTP状态码 | 含义 | data.error示例 |
|---|---|---|
| 401 | API密钥缺失或无效 | |
| 400 | 参数验证失败 | |
| 500 | 邮件服务错误 | |
Worker Example Code
Worker示例代码
typescript
async function sendEmail(env: Env, to: string, subject: string, html: string): Promise<{ ok: boolean; error?: string }> {
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
const resp = await fetch(`${baseUrl}/api/v4/send_email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': env.API_KEY,
},
body: JSON.stringify({ to, subject, html }),
});
const result = await resp.json() as { code: number; msg: string; data?: { ok?: boolean; error?: string } };
if (resp.status !== 200 || result.code !== 200) {
return { ok: false, error: result.data?.error || result.msg || 'Unknown error' };
}
return { ok: true };
}
// Usage in routes
async function handleSendVerification(request: Request, env: Env): Promise<Response> {
const { email } = await request.json() as { email: string };
const code = Math.random().toString().slice(2, 8);
const result = await sendEmail(env, email, 'Verification Code',
`<p>Your code is <strong>${code}</strong></p>`);
if (!result.ok) {
return json({ error: result.error }, 500);
}
return json({ ok: true });
}typescript
async function sendEmail(env: Env, to: string, subject: string, html: string): Promise<{ ok: boolean; error?: string }> {
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
const resp = await fetch(`${baseUrl}/api/v4/send_email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': env.API_KEY,
},
body: JSON.stringify({ to, subject, html }),
});
const result = await resp.json() as { code: number; msg: string; data?: { ok?: boolean; error?: string } };
if (resp.status !== 200 || result.code !== 200) {
return { ok: false, error: result.data?.error || result.msg || 'Unknown error' };
}
return { ok: true };
}
// 路由中的使用示例
async function handleSendVerification(request: Request, env: Env): Promise<Response> {
const { email } = await request.json() as { email: string };
const code = Math.random().toString().slice(2, 8);
const result = await sendEmail(env, email, 'Verification Code',
`<p>Your code is <strong>${code}</strong></p>`);
if (!result.ok) {
return json({ error: result.error }, 500);
}
return json({ ok: true });
}Error Handling Pattern
错误处理模式
PinMe platform API unified response format:
typescript
interface PinmeResponse<T = unknown> {
code: number; // 200=success, other=failure
msg: string; // "ok" | "error" | "invalid params"
data?: T; // Business data on success, may contain { error: string } on failure
}PinMe平台API统一响应格式:
typescript
interface PinmeResponse<T = unknown> {
code: number; // 200=成功,其他=失败
msg: string; // "ok" | "error" | "invalid params"
data?: T; // 成功时返回业务数据,失败时可能包含{ error: string }
}Recommended Unified Error Handler
推荐的统一错误处理器
typescript
async function callPinmeAPI<T>(url: string, apiKey: string, body: unknown): Promise<{ data?: T; error?: string }> {
let resp: Response;
try {
resp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey },
body: JSON.stringify(body),
});
} catch {
return { error: 'Network error' };
}
if (!resp.ok) {
try {
const err = await resp.json() as PinmeResponse;
return { error: err.data && typeof err.data === 'object' && 'error' in err.data
? (err.data as { error: string }).error
: err.msg || `HTTP ${resp.status}` };
} catch {
return { error: `HTTP ${resp.status}` };
}
}
const result = await resp.json() as PinmeResponse<T>;
if (result.code !== 200) {
return { error: result.data && typeof result.data === 'object' && 'error' in result.data
? (result.data as { error: string }).error
: result.msg };
}
return { data: result.data as T };
}typescript
async function callPinmeAPI<T>(url: string, apiKey: string, body: unknown): Promise<{ data?: T; error?: string }> {
let resp: Response;
try {
resp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey },
body: JSON.stringify(body),
});
} catch {
return { error: 'Network error' };
}
if (!resp.ok) {
try {
const err = await resp.json() as PinmeResponse;
return { error: err.data && typeof err.data === 'object' && 'error' in err.data
? (err.data as { error: string }).error
: err.msg || `HTTP ${resp.status}` };
} catch {
return { error: `HTTP ${resp.status}` };
}
}
const result = await resp.json() as PinmeResponse<T>;
if (result.code !== 200) {
return { error: result.data && typeof result.data === 'object' && 'error' in result.data
? (result.data as { error: string }).error
: result.msg };
}
return { data: result.data as T };
}Usage Example
使用示例
typescript
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
// Send email
const emailResult = await callPinmeAPI<{ ok: boolean }>(
`${baseUrl}/api/v4/send_email`, env.API_KEY,
{ to: 'user@example.com', subject: 'Hello', html: '<p>Hi</p>' },
);
if (emailResult.error) return json({ error: emailResult.error }, 500);typescript
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
// 发送邮件
const emailResult = await callPinmeAPI<{ ok: boolean }>(
`${baseUrl}/api/v4/send_email`, env.API_KEY,
{ to: 'user@example.com', subject: 'Hello', html: '<p>Hi</p>' },
);
if (emailResult.error) return json({ error: emailResult.error }, 500);