feat(branding): add global dynamic theme system and fix 2fa mail

This commit is contained in:
DanielS
2026-08-14 15:57:29 +02:00
parent 009b167cbd
commit 9ecdc645e8
22 changed files with 1764 additions and 313 deletions

View File

@@ -4,6 +4,7 @@ import { createAdminClient } from '@/lib/supabase/admin';
/**
* Send an email using database-configured SMTP settings (or environment variable fallback).
* If SMTP is not configured, logs a warning and gracefully skips sending instead of throwing.
* @param to Recipient address
* @param subject Subject line
* @param text Plaintext body
@@ -26,47 +27,63 @@ export async function sendMail({
contentType?: string;
}[];
}) {
// Query custom SMTP settings from database
const supabase = createAdminClient();
const { data: dbSettings } = await supabase
.from('settings')
.select('*')
.eq('id', 'smtp')
.maybeSingle();
try {
// Query custom SMTP settings from database
const supabase = createAdminClient();
const { data: dbSettings } = await supabase
.from('settings')
.select('*')
.eq('id', 'smtp')
.maybeSingle();
// Resolve config from DB or environment variables
const host = dbSettings?.host || process.env.SMTP_HOST;
const port = dbSettings?.port ? Number(dbSettings.port) : Number(process.env.SMTP_PORT);
const secure = dbSettings
? !!dbSettings.secure
: (process.env.SMTP_SECURE === 'true' || process.env.SMTP_SECURE === '1');
const user = dbSettings?.user || process.env.SMTP_USER;
const pass = dbSettings?.pass || process.env.SMTP_PASS;
// Resolve config from DB or environment variables
const host = dbSettings?.host || process.env.SMTP_HOST;
const port = dbSettings?.port
? Number(dbSettings.port)
: process.env.SMTP_PORT
? Number(process.env.SMTP_PORT)
: 587;
const secure = dbSettings
? !!dbSettings.secure
: process.env.SMTP_SECURE === 'true' || process.env.SMTP_SECURE === '1';
const user = dbSettings?.user || process.env.SMTP_USER;
const pass = dbSettings?.pass || process.env.SMTP_PASS;
if (!host || !user) {
throw new Error('SMTP host and user must be configured (either in settings database table or environment variables).');
if (!host || !user) {
console.warn(
`SMTP is not configured (missing host/user). E-Mail to "${to}" skipped.`
);
return { messageId: 'skipped-no-smtp-config', skipped: true };
}
// Create transporter dynamically on send request
const transporter = nodemailer.createTransport({
host,
port,
secure,
auth: {
user,
pass: pass || '',
},
tls: {
rejectUnauthorized: false,
},
});
const fromAddress = process.env.SMTP_FROM || user;
const info = await transporter.sendMail({
from: fromAddress,
to,
subject,
text,
html,
attachments,
});
return info;
} catch (err: any) {
console.error(`Failed to send email to "${to}":`, err.message || err);
return { messageId: 'failed-smtp-error', error: err.message || err };
}
// Create transporter dynamically on send request
const transporter = nodemailer.createTransport({
host,
port,
secure,
auth: {
user,
pass,
},
});
const info = await transporter.sendMail({
from: user,
to,
subject,
text,
html,
attachments,
});
return info;
}