01ff137f43
- SMTP: add test-to field, send real email via sendMail() instead of verify() - SMTP: fix no_auth warning shown as error for open-relay servers - DKV: register dkv-fleet in MODULE_REGISTRY (fixes "Modul nicht gefunden") - DKV: add dynamic [category]/[moduleSlug]/settings + vehicles sub-routes - DKV: settings/vehicles links use useParams for consistent URLs - DKV: add gear icon settings link to module main page - DKV: rename module to "DKV-Rechnung" in seed + translations - DKV: add optional domain field for Exchange (WebCredentials 3rd arg) - DKV: hide IMAP-only fields (Port/Verschlüsselung/Ordner) when Exchange selected - DKV: hide Exchange-only field (Domain) when IMAP selected - Prisma: add domain column to DkvModuleConfig Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
/**
|
|
* Settings API client — SMTP configuration.
|
|
* Consumes the SettingsController built in 07-03.
|
|
* All calls use credentials: 'include' for cookie-based auth.
|
|
*
|
|
* T-07-17: SmtpConfig exposes only hasPassword, never the secret.
|
|
* The password field is never pre-filled from server data.
|
|
*/
|
|
|
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
|
|
|
// --- Types mirroring the 07-03 backend contract ---
|
|
|
|
/**
|
|
* SMTP configuration as returned by GET /settings/smtp.
|
|
* encryptedPassword is NEVER returned (T-07-17).
|
|
*/
|
|
export interface SmtpConfig {
|
|
host: string;
|
|
port: number;
|
|
encryption: 'none' | 'starttls' | 'ssl-tls';
|
|
username?: string;
|
|
fromAddress: string;
|
|
/** True when an encrypted password is stored; the password value is never exposed. */
|
|
hasPassword: boolean;
|
|
}
|
|
|
|
/**
|
|
* Payload for PUT /settings/smtp and POST /settings/smtp/test.
|
|
* password is optional — omit to preserve the existing stored password.
|
|
*/
|
|
export interface SaveSmtpPayload {
|
|
host: string;
|
|
port: number;
|
|
encryption: 'none' | 'starttls' | 'ssl-tls';
|
|
username?: string;
|
|
/** Only include when the user has typed a new password. */
|
|
password?: string;
|
|
fromAddress: string;
|
|
/** If set, backend sends a real test email to this address instead of just verify(). */
|
|
testTo?: string;
|
|
}
|
|
|
|
// --- API functions ---
|
|
|
|
/**
|
|
* Fetch the SMTP configuration for the current tenant.
|
|
* GET /settings/smtp
|
|
* Returns null when no configuration has been saved yet (404).
|
|
*/
|
|
export async function fetchSmtp(): Promise<SmtpConfig | null> {
|
|
const res = await fetch(`${API_URL}/settings/smtp`, {
|
|
credentials: 'include',
|
|
});
|
|
if (res.status === 404) return null;
|
|
if (!res.ok) throw new Error('Failed to fetch SMTP config');
|
|
return res.json();
|
|
}
|
|
|
|
/**
|
|
* Save the SMTP configuration.
|
|
* PUT /settings/smtp
|
|
*/
|
|
export async function saveSmtp(payload: SaveSmtpPayload): Promise<SmtpConfig> {
|
|
const res = await fetch(`${API_URL}/settings/smtp`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify(payload),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to save SMTP config');
|
|
return res.json();
|
|
}
|
|
|
|
/**
|
|
* Test the SMTP connection with the given settings.
|
|
* POST /settings/smtp/test
|
|
* Returns { success: boolean } — backend runs nodemailer.verify().
|
|
*/
|
|
export async function testSmtp(
|
|
payload: SaveSmtpPayload,
|
|
): Promise<{ success: boolean; warning?: string }> {
|
|
const res = await fetch(`${API_URL}/settings/smtp/test`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify(payload),
|
|
});
|
|
if (!res.ok) throw new Error('Failed to test SMTP config');
|
|
return res.json();
|
|
}
|