React Email
React Email 是一个库,允许您使用 React 组件创建电子邮件。
由于 Elysia 使用 Bun 作为运行环境,我们可以直接编写一个 React Email 组件,并将 JSX 直接导入到我们的代码中以发送电子邮件。
安装
要安装 React Email,请运行以下命令:
bash
bun add -d react-email
bun add @react-email/components react react-dom
然后在 package.json
中添加以下脚本:
json
{
"scripts": {
"email": "email dev --dir src/emails"
}
}
我们建议将电子邮件模板添加到 src/emails
目录中,因为我们可以直接导入 JSX 文件。
TypeScript
如果您使用 TypeScript,可能需要在 tsconfig.json
中添加以下内容:
json
{
"compilerOptions": {
"jsx": "react"
}
}
您的第一封电子邮件
创建文件 src/emails/otp.tsx
,并输入以下代码:
tsx
import * as React from 'react'
import { Tailwind, Section, Text } from '@react-email/components'
export default function OTPEmail({ otp }: { otp: number }) {
return (
<Tailwind>
<Section className="flex justify-center items-center w-full min-h-screen font-sans">
<Section className="flex flex-col items-center w-76 rounded-2xl px-6 py-1 bg-gray-50">
<Text className="text-xs font-medium text-violet-500">
验证您的电子邮件地址
</Text>
<Text className="text-gray-500 my-0">
使用以下代码验证您的电子邮件地址
</Text>
<Text className="text-5xl font-bold pt-2">{otp}</Text>
<Text className="text-gray-400 font-light text-xs pb-4">
此代码在 10 分钟内有效
</Text>
<Text className="text-gray-600 text-xs">
感谢加入我们
</Text>
</Section>
</Section>
</Tailwind>
)
}
OTPEmail.PreviewProps = {
otp: 123456
}
您可能会注意到我们使用了 @react-email/components
来创建电子邮件模板。
该库提供了一组与邮件客户端(例如 Gmail、Outlook 等)兼容的组件,包括 使用 Tailwind 进行样式设置。
我们还向 OTPEmail
函数添加了 PreviewProps
。这仅在我们在 PLAYGROUND 上预览电子邮件时适用。
预览您的电子邮件
要预览您的电子邮件,请运行以下命令:
bash
bun email
这将打开一个浏览器窗口,显示您的电子邮件预览。
发送电子邮件
要发送电子邮件,我们可以使用 react-dom/server
来渲染电子邮件,然后使用首选提供商进行发送:
tsx
import { Elysia, t } from 'elysia'
import * as React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import OTPEmail from './emails/otp'
import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
host: 'smtp.gehenna.sh',
port: 465,
auth: {
user: 'makoto',
pass: '12345678'
}
})
new Elysia()
.get('/otp', async ({ body }) => {
// 随机生成 100,000 到 999,999 之间的数字
const otp = ~~(Math.random() * (900_000 - 1)) + 100_000
const html = renderToStaticMarkup(<OTPEmail otp={otp} />)
await transporter.sendMail({
from: 'ibuki@gehenna.sh',
to: body,
subject: '验证您的电子邮件地址',
html,
})
return { success: true }
}, {
body: t.String({ format: 'email' })
})
.listen(3000)
tsx
import { Elysia, t } from 'elysia'
import OTPEmail from './emails/otp'
import Resend from 'resend'
const resend = new Resend('re_123456789')
new Elysia()
.get('/otp', async ({ body }) => {
// 随机生成 100,000 到 999,999 之间的数字
const otp = ~~(Math.random() * (900_000 - 1)) + 100_000
await resend.emails.send({
from: 'ibuki@gehenna.sh',
to: body,
subject: '验证您的电子邮件地址',
html: <OTPEmail otp={otp} />,
})
return { success: true }
}, {
body: t.String({ format: 'email' })
})
.listen(3000)
tsx
import { Elysia, t } from 'elysia'
import * as React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import OTPEmail from './emails/otp'
import { type SendEmailCommandInput, SES } from '@aws-sdk/client-ses'
import { fromEnv } from '@aws-sdk/credential-providers'
const ses = new SES({
credentials:
process.env.NODE_ENV === 'production' ? fromEnv() : undefined
})
new Elysia()
.get('/otp', async ({ body }) => {
// 随机生成 100,000 到 999,999 之间的数字
const otp = ~~(Math.random() * (900_000 - 1)) + 100_000
const html = renderToStaticMarkup(<OTPEmail otp={otp} />)
await ses.sendEmail({
Source: 'ibuki@gehenna.sh',
Destination: {
ToAddresses: [body]
},
Message: {
Body: {
Html: {
Charset: 'UTF-8',
Data: html
}
},
Subject: {
Charset: 'UTF-8',
Data: '验证您的电子邮件地址'
}
}
} satisfies SendEmailCommandInput)
return { success: true }
}, {
body: t.String({ format: 'email' })
})
.listen(3000)
tsx
import { Elysia, t } from 'elysia'
import OTPEmail from './emails/otp'
import sendgrid from "@sendgrid/mail"
sendgrid.setApiKey(process.env.SENDGRID_API_KEY)
new Elysia()
.get('/otp', async ({ body }) => {
// 随机生成 100,000 到 999,999 之间的数字
const otp = ~~(Math.random() * (900_000 - 1)) + 100_000
const html = renderToStaticMarkup(<OTPEmail otp={otp} />)
await sendgrid.send({
from: 'ibuki@gehenna.sh',
to: body,
subject: '验证您的电子邮件地址',
html
})
return { success: true }
}, {
body: t.String({ format: 'email' })
})
.listen(3000)
TIP
注意,我们可以直接导入电子邮件组件,这要归功于 Bun
您可以在 React Email Integration 中查看所有可用的 React Email 集成,并在 React Email documentation 中了解更多信息。