/** * Transactional email templates. * * Uses simple HTML strings rather than React Email to avoid adding * a build-time dependency. Swap for @react-email/components if you * need richer templating. */ const PROJECT_DISPLAY_NAME = '{{PROJECT_DISPLAY_NAME}}'; /** Escape HTML entities to prevent HTML injection in emails */ function escapeHtml(str: string): string { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function layout(content: string): string { return `
${content}
`; } export function orgInviteEmail(params: { inviterName: string; organizationName: string; role: string; loginUrl: string; }): { subject: string; html: string } { const inviter = escapeHtml(params.inviterName); const org = escapeHtml(params.organizationName); const role = escapeHtml(params.role); return { subject: `You've been invited to ${params.organizationName}`, html: layout(`

You've been invited

${inviter} has invited you to join ${org} as a ${role}.

Accept Invitation

If you don't have an account yet, you'll be able to create one after clicking the link above.

`), }; } export function subscriptionConfirmEmail(params: { userName?: string; planName: string; amount: string; interval: string; }): { subject: string; html: string } { const userName = params.userName ? escapeHtml(params.userName) : null; const planName = escapeHtml(params.planName); const amount = escapeHtml(params.amount); const interval = escapeHtml(params.interval); return { subject: `Subscription confirmed: ${params.planName} plan`, html: layout(`

Subscription Confirmed

${userName ? `Hi ${userName},` : 'Hi,'}

You're now on the ${planName} plan.

${amount} / ${interval}

You can manage your subscription at any time from your billing settings.

`), }; } export function paymentFailedEmail(params: { userName?: string; planName: string; billingUrl: string; }): { subject: string; html: string } { const userName2 = params.userName ? escapeHtml(params.userName) : null; const planName2 = escapeHtml(params.planName); return { subject: `Payment failed for your ${PROJECT_DISPLAY_NAME} subscription`, html: layout(`

Payment Failed

${userName2 ? `Hi ${userName2},` : 'Hi,'}

We were unable to process the payment for your ${planName2} plan. Please update your payment method to avoid any interruption to your service.

Update Payment Method

If you believe this is an error, please contact support.

`), }; }