@ossy/email
v1.6.3
Published
React email rendering and AWS SES integration for the Ossy platform. Provides layout components, a server-side renderer, and the `email.integration.js` that the platform connects at startup.
Downloads
3,325
Readme
@ossy/email
React email rendering and AWS SES integration for the Ossy platform. Provides layout components, a server-side renderer, and the email.integration.js that the platform connects at startup.
Packages at a glance
| Export | Purpose |
|---|---|
| EmailLayout | Responsive email shell (600 px centered table layout) |
| EmailButton | Themed call-to-action button |
| EmailText | Body paragraph with sensible defaults |
| EmailRenderer | Renders a React component to { html, text } |
| emailIntegration / connect | AWS SES integration factory |
*.email.jsx — Transactional email template primitive
An email template is a React component discovered and bundled by @ossy/app build. You do not register it manually — the platform picks it up by filename.
File naming: <name>.email.jsx or <name>.email.tsx. Place it anywhere inside src/.
Required exports:
| Export | Type | Description |
|---|---|---|
| metadata.id or id | string | Canonical template id, e.g. @ossy/authentication/emails/verify-sign-in. |
| default | React.ComponentType | The email component. |
Optional exports:
| Export | Type | Description |
|---|---|---|
| subject | string | Default subject line. |
Minimal example:
// src/auth/verify-sign-in.email.jsx
import { EmailLayout, EmailButton, EmailText } from '@ossy/email'
export const id = '@ossy/authentication/emails/verify-sign-in'
export const subject = 'Sign in'
export default function VerifySignInEmail({ token, baseUrl = 'https://app.example.com', theme }) {
const url = `${baseUrl}/verify?token=${token}`
return (
<EmailLayout theme={theme}>
<h1 style={{ color: '#111111', margin: '0 0 16px' }}>Sign in</h1>
<EmailText>Click the button below to sign in.</EmailText>
<EmailButton href={url} theme={theme}>Sign in</EmailButton>
</EmailLayout>
)
}See PRIMITIVES.md for the full primitive specification.
Components
EmailLayout
A responsive 600 px centered table layout. Wraps the email body.
import { EmailLayout } from '@ossy/email'
<EmailLayout theme={theme}>
{/* email content */}
</EmailLayout>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Email body content. |
| theme | { primaryColor?, backgroundColor?, fontFamily? } | {} | Colour/font overrides. |
Theme defaults:
| Key | Default |
|---|---|
| primaryColor | '#111111' |
| backgroundColor | '#f5f5f5' |
| fontFamily | 'sans-serif' |
EmailButton
A styled call-to-action link rendered as an <a> tag (for maximum email client compatibility).
import { EmailButton } from '@ossy/email'
<EmailButton href="https://example.com/action" theme={theme}>
Click me
</EmailButton>Props:
| Prop | Type | Description |
|---|---|---|
| href | string | Link destination. |
| children | ReactNode | Button label. |
| theme | object | Same shape as EmailLayout theme. |
EmailText
A body paragraph with sensible line-height and colour defaults.
import { EmailText } from '@ossy/email'
<EmailText>You have requested to sign in.</EmailText>Props:
| Prop | Type | Description |
|---|---|---|
| children | ReactNode | Paragraph content. |
| style | CSSProperties | Additional inline styles (merged with defaults). |
EmailRenderer
Server-side renderer. Converts a React email component to HTML and a plain-text fallback.
import { EmailRenderer } from '@ossy/email'
const { html, text } = EmailRenderer.render(VerifySignInEmail, { token: 'abc', baseUrl: 'https://app.example.com' })render(Component, props) calls renderToStaticMarkup (from react-dom/server) and strips HTML tags for the plain-text output. Both strings are suitable for passing directly to the AWS SES SendEmailCommand.
email.integration.js — AWS SES integration
The email integration is an *.integration.js primitive that the platform connects at startup. It provides two methods: send (raw) and sendTemplate (React component).
Required environment variables (not required when BUILD_ENVIRONMENT=local — emails are logged to stdout instead):
| Variable | Description |
|---|---|
| SES_REGION | AWS region for SES (e.g. eu-west-1) |
| AWS_ACCESS_KEY_ID | AWS access key |
| AWS_SECRET_ACCESS_KEY | AWS secret key |
If any variable is missing (and BUILD_ENVIRONMENT is not local), the integration is skipped with a warning, and integrations.get('email') returns null.
Using the email client in a task:
// src/send-invite.task.js
import WorkspaceInvitationEmail from './workspace-invitation.email.jsx'
export const metadata = {
id: '@ossy/workspaces/tasks/send-workspace-invitation',
triggers: [{ type: '@ossy/workspaces/schema/workspace', event: 'UserInvited' }],
}
export async function run({ event, integrations }) {
const email = integrations.get('email')
if (!email) return
// Send a raw email
await email.send({
to: event.payload.email,
from: '[email protected]',
subject: 'You have been invited',
html: '<p>Click <a href="...">here</a> to accept.</p>',
text: 'Click the link to accept the invitation.',
})
// Or send a React template
await email.sendTemplate(
WorkspaceInvitationEmail,
{ inviteUrl: event.payload.inviteUrl, theme: {} },
{ to: event.payload.email, from: '[email protected]', subject: 'Invitation' },
)
}Client API:
| Method | Signature | Description |
|---|---|---|
| send | ({ to, from, subject, html, text }) => Promise | Send a raw HTML/text email via SES. |
| sendTemplate | (Component, props, { to, from, subject }) => Promise | Render a React component with EmailRenderer.render and send via SES. |
Localized email copy
Resolve subjects and body strings from the merged build catalog in the action or task that sends the mail — not from hardcoded exports on the template:
import path from 'node:path'
import { createTranslatorForBuild } from '@ossy/platform/locale'
const buildDir = path.resolve(process.cwd(), 'build')
const t = createTranslatorForBuild(buildDir, language, { defaultLanguage: 'en' })
await email.sendTemplate(
VerifySignInEmail,
{ token, baseUrl, t },
{ to: email, from: '[email protected]', subject: t('authentication.verifySignIn.subject') },
)See @ossy/locale README for the full server-side pattern.
Using emailIntegration directly
If you need to connect the integration without the platform's auto-loader:
import { emailIntegration } from '@ossy/email'
import { IntegrationService } from '@ossy/platform'
await IntegrationService.load([emailIntegration], process.env)
const emailClient = IntegrationService.get('email')