fix: email

This commit is contained in:
2026-03-11 16:34:51 +01:00
parent 17aa8956a7
commit 7f431c0091
7 changed files with 301 additions and 676 deletions

View File

@@ -95,7 +95,7 @@
"@orpc/zod": "catalog:",
"dotenv": "catalog:",
"drizzle-orm": "^0.45.1",
"nodemailer": "^8.0.1",
"nodemailer": "^8.0.2",
"zod": "catalog:",
},
"devDependencies": {
@@ -1511,7 +1511,7 @@
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
"nodemailer": ["nodemailer@8.0.1", "", {}, "sha512-5kcldIXmaEjZcHR6F28IKGSgpmZHaF1IXLWFTG+Xh3S+Cce4MiakLtWY+PlBU69fLbRa8HlaGIrC/QolUpHkhg=="],
"nodemailer": ["nodemailer@8.0.2", "", {}, "sha512-zbj002pZAIkWQFxyAaqoxvn+zoIwRnS40hgjqTXudKOOJkiFFgBeNqjgD3/YCR12sZnrghWYBY+yP1ZucdDRpw=="],
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
@@ -1987,8 +1987,6 @@
"@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
"@kk/auth/nodemailer": ["nodemailer@8.0.2", "", {}, "sha512-zbj002pZAIkWQFxyAaqoxvn+zoIwRnS40hgjqTXudKOOJkiFFgBeNqjgD3/YCR12sZnrghWYBY+yP1ZucdDRpw=="],
"@noble/curves/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="],

View File

@@ -20,7 +20,7 @@
"@orpc/zod": "catalog:",
"dotenv": "catalog:",
"drizzle-orm": "^0.45.1",
"nodemailer": "^8.0.1",
"nodemailer": "^8.0.2",
"zod": "catalog:"
},
"devDependencies": {

View File

@@ -0,0 +1,9 @@
// ---------------------------------------------------------------------------
// Single source-of-truth for event details used across the API
// ---------------------------------------------------------------------------
export const EVENT = "Open Mic Night — vrijdag 18 april 2026";
export const OPENS = "maandag 16 maart 2026 om 19:00";
// Registration opens — used for reminder scheduling windows
export const REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00");

File diff suppressed because it is too large Load Diff

View File

@@ -348,7 +348,7 @@ export const drinkkaartRouter = {
.then((r) => r[0]);
if (cardUser) {
sendDeductionEmail({
await sendDeductionEmail({
to: cardUser.email,
firstName: cardUser.name.split(" ")[0] ?? cardUser.name,
amountCents: input.amountCents,

View File

@@ -18,6 +18,7 @@ import {
sum,
} from "drizzle-orm";
import { z } from "zod";
import { REGISTRATION_OPENS_AT } from "../constants";
import {
emailLog,
sendCancellationEmail,
@@ -32,8 +33,7 @@ import { adminProcedure, protectedProcedure, publicProcedure } from "../index";
import { generateQrSecret } from "../lib/drinkkaart-utils";
import { drinkkaartRouter } from "./drinkkaart";
// Registration opens at this date — reminders fire 24 hours and 1 hour before
const REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00");
// Reminder windows derived from the canonical registration open date
const REMINDER_1H_WINDOW_START = new Date(
REGISTRATION_OPENS_AT.getTime() - 60 * 60 * 1000,
);
@@ -879,13 +879,15 @@ export const appRouter = {
email: input.email,
});
// Fire-and-forget — don't let a mail failure block the response
sendSubscriptionConfirmationEmail({ to: input.email }).catch((err) =>
emailLog("error", "email.catch", {
type: "subscription_confirmation",
to: input.email,
error: String(err),
}),
// Awaited — CF Workers abandon unawaited promises when the response
// returns. Mail errors are caught so they don't fail the request.
await sendSubscriptionConfirmationEmail({ to: input.email }).catch(
(err) =>
emailLog("error", "email.catch", {
type: "subscription_confirmation",
to: input.email,
error: String(err),
}),
);
return { ok: true };

View File

@@ -15,13 +15,13 @@ export const env = createEnv({
server: {
DATABASE_URL: z.string().min(1),
BETTER_AUTH_SECRET: z.string().min(32),
BETTER_AUTH_URL: z.url(),
BETTER_AUTH_URL: z.url().default("https://kunstenkamp.be"),
CORS_ORIGIN: z.url(),
SMTP_HOST: z.string().min(1).optional(),
SMTP_PORT: z.coerce.number().default(587),
SMTP_USER: z.string().min(1).optional(),
SMTP_PASS: z.string().min(1).optional(),
SMTP_FROM: z.string().min(1).optional(),
SMTP_FROM: z.string().min(1).default("Kunstenkamp <info@kunstenkamp.be>"),
NODE_ENV: z
.enum(["development", "production", "test"])
.default("development"),