Files
kan/packages/email/src/sendEmail.tsx
Henry 1fb56aafd0 feat: add logger package to improve observability (#437)
* feat: add logger package to improve observability

* chore: add LOG_LEVEL to docker compose and readme
2026-03-13 22:57:47 +00:00

76 lines
2.1 KiB
TypeScript

import { render } from "@react-email/render";
import nodemailer from "nodemailer";
import { createLogger } from "@kan/logger";
const log = createLogger("email");
import JoinWorkspaceTemplate from "./templates/join-workspace";
import MagicLinkTemplate from "./templates/magic-link";
import MentionTemplate from "./templates/mention";
import ResetPasswordTemplate from "./templates/reset-password";
type Templates = "MAGIC_LINK" | "JOIN_WORKSPACE" | "RESET_PASSWORD" | "MENTION";
const emailTemplates: Record<Templates, React.ComponentType<any>> = {
MAGIC_LINK: MagicLinkTemplate,
JOIN_WORKSPACE: JoinWorkspaceTemplate,
RESET_PASSWORD: ResetPasswordTemplate,
MENTION: MentionTemplate,
};
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure:
process.env.SMTP_SECURE === undefined
? true
: process.env.SMTP_SECURE?.toLowerCase() === "true",
tls: {
// do not fail on invalid certs
rejectUnauthorized:
process.env.SMTP_REJECT_UNAUTHORIZED === undefined
? true
: process.env.SMTP_REJECT_UNAUTHORIZED?.toLowerCase() === "true",
},
...(process.env.SMTP_USER &&
process.env.SMTP_PASSWORD && {
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
}),
});
export const sendEmail = async (
to: string,
subject: string,
template: Templates,
data: Record<string, string>,
) => {
log.info({ to, subject, template }, "Sending email");
try {
const EmailTemplate = emailTemplates[template];
const html = await render(<EmailTemplate {...data} />, { pretty: true });
const options = {
from: process.env.EMAIL_FROM,
to,
subject,
html,
};
const response = await transporter.sendMail(options);
if (!response.accepted.length) {
throw new Error(`Failed to send email: ${response.response}`);
}
log.info({ to, subject, template, messageId: response.messageId }, "Email sent");
return response;
} catch (error) {
log.error({ err: error, to, from: process.env.EMAIL_FROM, subject, template }, "Email sending failed");
throw error;
}
};