带类型化 React Email 模板的事务邮件:Resend、SMTP 或开发时输出到控制台
代码9 个文件上下文约 544 个 token扫描通过
安装
$
genpm add @core/email你将获得
- 源代码位于 src/lib/email/,共 9 个文件。 (11.8 kB)
- AI 规则位于 src/lib/email/AGENTS.md,另附 IDE 规则文件。
- 添加到 .env.example 的环境变量:RESEND_API_KEY, EMAIL_FROM。
README
此包没有 README。
约 544 个 token→ src/lib/email/AGENTS.md→ .cursor/rules/genpm-core-email.mdc
这正是你的 AI 在 src/lib/email 中工作时读取的内容。不会向其上下文添加其他任何内容。
@core/email — rules for AI agents
Purpose
Transactional email with typed templates: sendEmail('welcome', { to, props }). Providers: Resend (default), SMTP
(optional, via nodemailer) and a console provider for development. Templates use React Email. No marketing lists,
no queues, no tracking pixels.
Map
index.ts— public API:sendEmail,renderEmail,setEmailProvider, provider factories,TemplateProps.send.ts— the template registry (templates) andsendEmail.templates/*.ts—welcome,magicLink,receipt, plus the sharedlayout.ts.providers.ts—EmailProviderinterface and implementations.
Integration
- Env:
EMAIL_FROM("App <hello@yourdomain.com>") andRESEND_API_KEY(verify the domain in Resend first). WithoutRESEND_API_KEY, outside production, emails are printed to the console.@types/reactis only needed at build time: move it to devDependencies if GenPM added it to dependencies. SMTP instead:EMAIL_PROVIDER=smtp,SMTP_URL=smtps://user:pass@host:465and installnodemailer. - Send from server code only:
import { sendEmail } from './lib/email/index.js'; await sendEmail('welcome', { to: user.email, props: { name: user.name, appUrl: 'https://app.example.com' } }); - With
@core/auth: sendwelcomeafter the first login (when the user was just created). - Verify: run the app without
RESEND_API_KEYand check the console output.
Conventions
- New template: create
templates/<name>.tsexporting{ subject(props), render(props) }built withcreateElement as h(no JSX, so it works with anyjsxImportSource), then add it totemplatesandTemplatePropsinsend.ts. TypeScript then enforces its props everywhere. - Amounts in minor units (cents); links absolute (
https://…). - Keep
sendEmailcalls out of request hot paths when possible (after the response, or in a job).
Don't
- Don't send from the browser or expose
RESEND_API_KEYto client code. - Don't interpolate untrusted HTML into templates; pass plain strings (React escapes them).
- Don't log full email bodies in production (they may contain sign-in links).
# @core/email — rules for AI agents
## Purpose
Transactional email with typed templates: `sendEmail('welcome', { to, props })`. Providers: Resend (default), SMTP
(optional, via `nodemailer`) and a console provider for development. Templates use React Email. No marketing lists,
no queues, no tracking pixels.
## Map
- `index.ts` — public API: `sendEmail`, `renderEmail`, `setEmailProvider`, provider factories, `TemplateProps`.
- `send.ts` — the template registry (`templates`) and `sendEmail`.
- `templates/*.ts` — `welcome`, `magicLink`, `receipt`, plus the shared `layout.ts`.
- `providers.ts` — `EmailProvider` interface and implementations.
## Integration
1. Env: `EMAIL_FROM` (`"App <hello@yourdomain.com>"`) and `RESEND_API_KEY` (verify the domain in Resend first).
Without `RESEND_API_KEY`, outside production, emails are printed to the console.
`@types/react` is only needed at build time: move it to devDependencies if GenPM added it to dependencies.
SMTP instead: `EMAIL_PROVIDER=smtp`, `SMTP_URL=smtps://user:pass@host:465` and install `nodemailer`.
2. Send from server code only:
```ts
import { sendEmail } from './lib/email/index.js';
await sendEmail('welcome', { to: user.email, props: { name: user.name, appUrl: 'https://app.example.com' } });
```
3. With `@core/auth`: send `welcome` after the first login (when the user was just created).
4. Verify: run the app without `RESEND_API_KEY` and check the console output.
## Conventions
- New template: create `templates/<name>.ts` exporting `{ subject(props), render(props) }` built with
`createElement as h` (no JSX, so it works with any `jsxImportSource`), then add it to `templates` and
`TemplateProps` in `send.ts`. TypeScript then enforces its props everywhere.
- Amounts in minor units (cents); links absolute (`https://…`).
- Keep `sendEmail` calls out of request hot paths when possible (after the response, or in a job).
## Don't
- Don't send from the browser or expose `RESEND_API_KEY` to client code.
- Don't interpolate untrusted HTML into templates; pass plain strings (React escapes them).
- Don't log full email bodies in production (they may contain sign-in links).
应用 .genpmignore 后将被注入的确切目录树。固定于
// Proveedores de envío. Elige con EMAIL_PROVIDER (resend | smtp | console); por defecto Resend si hay
// RESEND_API_KEY y, si no, consola (solo fuera de producción).
import { Resend } from 'resend';
export type EmailMessage = { from: string; to: string | string[]; subject: string; html: string; text: string; replyTo?: string };
export type SendResult = { id: string | null };
export interface EmailProvider {
readonly name: string;
send(message: EmailMessage): Promise<SendResult>;
}
export function resendProvider(apiKey: string = process.env.RESEND_API_KEY ?? ''): EmailProvider {
if (!apiKey) throw new Error('RESEND_API_KEY is not set (see .env.example)');
const client = new Resend(apiKey);
return {
name: 'resend',
async send(m) {
const { data, error } = await client.emails.send({
from: m.from,
to: m.to,
subject: m.subject,
html: m.html,
text: m.text,
...(m.replyTo ? { replyTo: m.replyTo } : {}),
});
if (error) throw new Error(`Resend: ${error.message}`);
return { id: data?.id ?? null };
},
};
}
/** SMTP con `nodemailer` (instálalo solo si lo usas): SMTP_URL=smtps://user:pass@smtp.example.com:465 */
export function smtpProvider(url: string = process.env.SMTP_URL ?? ''): EmailProvider {
if (!url) throw new Error('SMTP_URL is not set');
let transport: { sendMail(m: Record<string, unknown>): Promise<{ messageId?: string }> } | null = null;
return {
name: 'smtp',
async send(m) {
if (!transport) {
const name = 'nodemailer';
const mod = (await import(name)) as { default: { createTransport(url: string): NonNullable<typeof transport> } };
transport = mod.default.createTransport(url);
}
const info = await transport.sendMail({ from: m.from, to: m.to, subject: m.subject, html: m.html, text: m.text, replyTo: m.replyTo });
return { id: info.messageId ?? null };
},
};
}
/** Modo dev: imprime el correo (texto plano) en vez de enviarlo. */
export function consoleProvider(log: (line: string) => void = console.info): EmailProvider {
return {
name: 'console',
async send(m) {
log(`[email] to=${[m.to].flat().join(',')} subject=${JSON.stringify(m.subject)}\n${m.text}`);
return { id: null };
},
};
}
export function defaultProvider(env: NodeJS.ProcessEnv = process.env): EmailProvider {
const choice = env.EMAIL_PROVIDER ?? (env.RESEND_API_KEY ? 'resend' : 'console');
if (choice === 'resend') return resendProvider(env.RESEND_API_KEY);
if (choice === 'smtp') return smtpProvider(env.SMTP_URL);
if (env.NODE_ENV === 'production') throw new Error('No email provider configured in production (set RESEND_API_KEY)');
return consoleProvider();
}
此包未声明 MCP 服务器。
| 版本 | 提交 | 发布时间 | 扫描 |
|---|---|---|---|
| 1.0.0 | 3e2976e | 4小时前 | ✔ 扫描通过 |
- genpm
- 无
- npm
- @react-email/components ^1.0.12@react-email/render ^2.1.0@types/react ^19.0.0react ^19.0.0resend ^6.32.0
- 建议
- GenPM 会给出 npm 命令建议,只有你同意时才会运行。
- 扫描
- 扫描通过 · 0 个问题
- 提交
- v1.0.0 → 3e2976ea815795eca662b4be29d8f552ec1e0d96 · 获取后已校验
- 脚本
- 无。GenPM 从不运行包中的代码。
- 许可证
- MIT
- 举报
- 发现问题了吗?