diff --git a/apps/auth/src/lib/auth.ts b/apps/auth/src/lib/auth.ts index b23100c..ff8abab 100644 --- a/apps/auth/src/lib/auth.ts +++ b/apps/auth/src/lib/auth.ts @@ -94,12 +94,18 @@ export const auth = betterAuth({ sendOnSignUp: true, autoSignInAfterVerification: true, async sendVerificationEmail({ user, url }) { - await sendTransactionalEmail({ - to: user.email, - subject: "Verify your Primora email", - text: `Verify your Primora email: ${url}`, - html: `
Verify your Primora email.
`, - }); + // Verification is optional — a misconfigured transport must not fail + // sign-up or sign-in. + try { + await sendTransactionalEmail({ + to: user.email, + subject: "Verify your Primora email", + text: `Verify your Primora email: ${url}`, + html: `Verify your Primora email.
`, + }); + } catch (error) { + console.warn(JSON.stringify({ level: "warn", msg: "verification_email_failed", error })); + } }, }, // Enabled unconditionally — better-auth only turns this on when NODE_ENV is diff --git a/apps/auth/src/lib/mail.ts b/apps/auth/src/lib/mail.ts index e8d23ee..5090e69 100644 --- a/apps/auth/src/lib/mail.ts +++ b/apps/auth/src/lib/mail.ts @@ -51,7 +51,12 @@ export async function sendTransactionalEmail(input: { } if (!("smtp" in cfg) || !cfg.smtp) { - throw new Error("No mail transport configured for auth service."); + // Self-hosted instances may run without mail — auth still works, the + // email simply never goes out. + console.warn( + JSON.stringify({ level: "warn", msg: "mail_skipped_no_transport", to: input.to, subject: input.subject }), + ); + return; } await nodemailer.createTransport(cfg.smtp).sendMail({ diff --git a/apps/frontend/src/App.tsx b/apps/frontend/src/App.tsx index 29ebeca..f199d61 100644 --- a/apps/frontend/src/App.tsx +++ b/apps/frontend/src/App.tsx @@ -736,7 +736,7 @@ export default function App() { try { if (mode() === "sign-up") { await authClient.signUp.email({ email: email(), password: password(), name: name() }); - setAuthMessage("Account created. Check Mailpit (or your SMTP provider) for the verification email."); + setAuthMessage("Account created — signing you in."); } else { await authClient.signIn.email({ email: email(), password: password() }); } diff --git a/apps/frontend/src/components/Input.tsx b/apps/frontend/src/components/Input.tsx index 76b80a3..1563198 100644 --- a/apps/frontend/src/components/Input.tsx +++ b/apps/frontend/src/components/Input.tsx @@ -13,16 +13,17 @@ const sizeClasses = { }; export function Input(props: InputProps) { - const [local, rest] = splitProps(props, ["label", "error", "size", "class"]); + const [local, rest] = splitProps(props, ["label", "error", "size", "class", "id"]); const size = () => local.size ?? "md"; return (