pinme-email
Use this skill when a PinMe project (Worker TypeScript) needs to integrate email sending (send_email). Guides AI to generate correct Worker TS code.
- License 许可
- MIT
- 最近更新
- 2026-07-19
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- pinme-email
- description
- Use this skill when a PinMe project (Worker TypeScript) needs to integrate email sending (send_email). Guides AI to generate correct Worker TS code.
03 SKILL.md 正文
PinMe Worker Email API Integration
Guides how to call PinMe platform's email sending API in a PinMe Worker (TypeScript).
Environment Variables
The following environment variables are automatically injected when the Worker is created — no manual configuration needed:
// 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
}
API_KEYis the sole credential for the Worker to call PinMe platform APIs. WhenBASE_URLis not set, it defaults tohttps://pinme.cloud.
Send Email API
Endpoint: POST {BASE_URL}/api/v4/send_email
Authentication: X-API-Key header (using env.API_KEY)
Sender: Automatically set to {project_name}@pinme.cloud
Request Format
{
"to": "user@example.com",
"subject": "Your verification code",
"html": "<p>Your code is <strong>123456</strong></p>"
}
| Field | Type | Required | Description |
|---|---|---|---|
to |
string | Yes | Recipient email address |
subject |
string | Yes | Email subject |
html |
string | Yes | HTML body |
Response Format
Success (200):
{ "code": 200, "msg": "ok", "data": { "ok": true } }
Errors:
| HTTP Status | Meaning | data.error Example |
|---|---|---|
| 401 | API Key missing or invalid | "X-API-Key header is required" / "Invalid API key" |
| 400 | Parameter validation failed | "Invalid email address" / "Subject is required" |
| 500 | Email service error | "Failed to send email" |
Worker Example Code
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 });
}
Error Handling Pattern
PinMe platform API unified response format:
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
}
Recommended Unified Error Handler
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
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);
04 同仓库更多 Skills
gds-correct-course
Manage significant changes during sprint execution. Use when the user says "correct course" or "propose sprint change"
gds-code-review
Review code changes adversarially using parallel review layers (Blind Hunter, Edge Case Hunter, Acceptance Auditor) with structured triage into actionable categories. Use when the user says "run code review" or "review this code"
gds-check-implementation-readiness
Verify GDD, UX, Architecture, and Epics alignment before production. Use when the user says "check readiness" or "implementation readiness"
gds-brainstorm-game
Facilitate game brainstorming sessions with game-specific techniques. Use when the user says "brainstorm game" or "game ideas"
gds-agent-tech-writer
Technical documentation specialist and knowledge curator for game projects. Use when the user asks to talk to Paige or requests the Technical Writer.
gds-agent-game-solo-dev
Elite indie game developer for rapid prototyping and solo quick-flow development. Use when the user asks to talk to Indie or requests the Game Solo Dev.