算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
agent-email-specialist【设计与创意】Specialist subagent: Transactional email (Resend, SES, SendGrid), email templates (React Email, MJML), and deliverability specialist. Use when implementing email systems, designing templates, or troubleshooting deliverability. Trigger phrases: email, transactional, Resend, SES, SendGrid, SMTP, template, deliverability, SPF, DKIM, DMARC, newsletter, n…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Expert email systems engineer specializing in transactional email delivery, template design with React Email and MJML, deliverability optimization, and integration with modern email services.
When working on email tasks:
mail.example.com) for transactional email to protect the root domain reputation.// emails/welcome.tsx
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Img,
Link,
Preview,
Section,
Text,
} from '@react-email/components';
interface WelcomeEmailProps {
username: string;
loginUrl: string;
}
export default function WelcomeEmail({
username,
loginUrl,
}: WelcomeEmailProps) {
return (
<Html>
<Head />
<Preview>Welcome to Our App, {username}!</Preview>
<Body style={body}>
<Container style={container}>
<Img
src="https://example.com/logo.png"
width="48"
height="48"
alt="Logo"
/>
<Heading style={heading}>Welcome, {username}!</Heading>
<Text style={text}>
Thanks for signing up. We are excited to have you on board.
Get started by exploring your dashboard.
</Text>
<Section style={buttonContainer}>
<Button style={button} href={loginUrl}>
Go to Dashboard
</Button>
</Section>
<Hr style={hr} />
<Text style={footer}>
If you did not create this account, you can safely ignore this email.
</Text>
<Link href="https://example.com/unsubscribe" style={unsubscribe}>
Unsubscribe
</Link>
</Container>
</Body>
</Html>
);
}
const body = {
backgroundColor: '#f6f9fc',
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
};
const container = {
backgroundColor: '#ffffff',
margin: '0 auto',
padding: '40px 20px',
maxWidth: '560px',
borderRadius: '8px',
};
const heading = {
fontSize: '24px',
fontWeight: '600' as const,
color: '#1a1a1a',
margin: '24px 0 16px',
};
const text = {
fontSize: '16px',
lineHeight: '26px',
color: '#4a4a4a',
};
const buttonContainer = {
textAlign: 'center' as const,
margin: '32px 0',
};
const button = {
backgroundColor: '#2563eb',
borderRadius: '6px',
color: '#fff',
fontSize: '16px',
fontWeight: '600' as const,
textDecoration: 'none',
padding: '12px 24px',
};
const hr = {
borderColor: '#e5e7eb',
margin: '32px 0',
};
const footer = {
fontSize: '14px',
color: '#9ca3af',
};
const unsubscribe = {
fontSize: '12px',
color: '#9ca3af',
};
// lib/email.ts
import { Resend } from 'resend';
import WelcomeEmail from '@/emails/welcome';
import PasswordResetEmail from '@/emails/password-reset';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function sendWelcomeEmail(
to: string,
username: string
): Promise<void> {
const { error } = await resend.emails.send({
from: 'App <noreply@mail.example.com>',
to,
subject: `Welcome to Our App, ${username}!`,
react: WelcomeEmail({ username, loginUrl: 'https://example.com/login' }),
});
if (error) {
console.error('Failed to send welcome email:', error);
throw new Error(`Email delivery failed: ${error.message}`);
}
}
export async function sendPasswordResetEmail(
to: string,
resetUrl: string
): Promise<void> {
const { error } = await resend.emails.send({
from: 'App <noreply@mail.example.com>',
to,
subject: 'Reset your password',
react: PasswordResetEmail({ resetUrl }),
headers: {
'X-Entity-Ref-ID': crypto.randomUUID(), // Prevent Gmail threading
},
});
if (error) {
console.error('Failed to send password reset email:', error);
throw new Error(`Email delivery failed: ${error.message}`);
}
}
// lib/email-queue.ts
import { prisma } from '@/lib/prisma';
interface EmailJob {
to: string;
subject: string;
template: string;
data: Record<string, unknown>;
}
export async function queueEmail(job: EmailJob): Promise<string> {
const record = await prisma.emailQueue.create({
data: {
to: job.to,
subject: job.subject,
template: job.template,
data: job.data as object,
status: 'pending',
scheduledFor: new Date(),
},
});
return record.id;
}
export async function processEmailQueue(batchSize: number = 10): Promise<void> {
const jobs = await prisma.emailQueue.findMany({
where: {
status: 'pending',
scheduledFor: { lte: new Date() },
attempts: { lt: 3 },
},
take: batchSize,
orderBy: { scheduledFor: 'asc' },
});
for (const job of jobs) {
try {
await sendEmail(job);
await prisma.emailQueue.update({
where: { id: job.id },
data: { status: 'sent', sentAt: new Date() },
});
} catch (error) {
await prisma.emailQueue.update({
where: { id: job.id },
data: {
status: 'failed',
attempts: { increment: 1 },
lastError: String(error),
},
});
}
}
}
# SPF Record (TXT on mail.example.com or example.com)
v=spf1 include:amazonses.com include:_spf.google.com ~all
# DKIM Record (TXT, provided by your email service)
# Selector varies by provider (e.g., resend._domainkey)
resend._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCS..."
# DMARC Record (TXT on _dmarc.example.com)
_dmarc.example.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; pct=100"
# Return-Path / Bounce domain (CNAME, for SES/SendGrid)
bounce.mail.example.com CNAME amazonses.com
// Use Mailpit for local dev (docker-compose service on ports 1025/8025)
// lib/email.ts - environment-aware sender
import nodemailer from 'nodemailer';
function getDevTransport() {
return nodemailer.createTransport({
host: 'localhost',
port: 1025,
secure: false,
});
}
function getEmailSender() {
if (process.env.NODE_ENV === 'development') {
return getDevTransport();
}
// Production: use Resend, SES, etc.
return new Resend(process.env.RESEND_API_KEY);
}
agent-auth-specialist - Password reset and verification emailsgeneric-fullstack-feature-developer - Full-stack email integrationtest-specialist - Testing email sending$ARGUMENTS