fix(smtp): proper SMTP dialogue, encoded mails, optional skip-verify
- Explicit SMTP flow (dial -> EHLO -> STARTTLS -> AUTH -> MAIL/RCPT/DATA) with errors naming the refusing step (also logged as smtp_step) - EHLO with the sender's domain instead of "localhost" - Envelope gets the bare address; "Name <addr>" stays in the From header (was rejected as invalid MAIL FROM) - Date and Message-ID headers, RFC 2047 subject, quoted-printable body - SMTP_SKIP_VERIFY / admin switch for self-signed certificates; SMTP checkboxes are switches now - Tests against a fake SMTP server (STARTTLS, 451, display names) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf0d68e7e1
commit
ce321ce579
15 files changed
+477
-96
No files matched your search
@@ -100,6 +100,7 @@ export const AdminSettingsView: React.FC<AdminSettingsViewProps> = ({
|
||||
smtpPass: '',
|
||||
smtpFrom: '',
|
||||
smtpTls: true,
|
||||
smtpSkipVerify: false,
|
||||
smtpConfiguredViaEnv: false,
|
||||
});
|
||||
const [testSmtpEmail, setTestSmtpEmail] = useState(currentUser.email || '');
|
||||
@@ -129,6 +130,7 @@ export const AdminSettingsView: React.FC<AdminSettingsViewProps> = ({
|
||||
smtpPass: sys.smtpPass || '',
|
||||
smtpFrom: sys.smtpFrom || '',
|
||||
smtpTls: sys.smtpTls ?? true,
|
||||
smtpSkipVerify: Boolean(sys.smtpSkipVerify),
|
||||
smtpConfiguredViaEnv: Boolean(sys.smtpConfiguredViaEnv),
|
||||
});
|
||||
}
|
||||
@@ -1202,20 +1204,33 @@ export const AdminSettingsView: React.FC<AdminSettingsViewProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center pt-5">
|
||||
<label className="flex items-center gap-2 cursor-pointer select-none">
|
||||
<input
|
||||
type="checkbox"
|
||||
<div className="sm:col-span-2 space-y-3 pt-1">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<p className="text-main font-medium">Verschlüsselung (`SMTP_TLS`)</p>
|
||||
<p className="text-[11px] text-muted">
|
||||
Port 465: TLS ab Verbindungsbeginn, sonst STARTTLS. Ist es an, wird ohne Verschlüsselung nicht gesendet.
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
checked={settings.smtpTls ?? true}
|
||||
onChange={(e) =>
|
||||
setSettings((prev) => ({ ...prev, smtpTls: e.target.checked }))
|
||||
}
|
||||
className="w-4 h-4 checkbox-square cursor-pointer"
|
||||
onChange={(smtpTls) => setSettings((prev) => ({ ...prev, smtpTls }))}
|
||||
/>
|
||||
<span className="text-main font-medium">
|
||||
STARTTLS / TLS-Verschlüsselung verwenden (`SMTP_TLS=true`)
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<p className="text-main font-medium">Zertifikatsprüfung deaktivieren (`SMTP_SKIP_VERIFY`)</p>
|
||||
<p className="text-[11px] text-muted">
|
||||
Nur für interne Mailserver mit selbstsigniertem Zertifikat oder abweichendem Namen. Die Verbindung
|
||||
bleibt verschlüsselt, der Server wird aber nicht mehr geprüft.
|
||||
</p>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
checked={settings.smtpSkipVerify ?? false}
|
||||
disabled={!(settings.smtpTls ?? true)}
|
||||
onChange={(smtpSkipVerify) => setSettings((prev) => ({ ...prev, smtpSkipVerify }))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ export interface SystemSettings {
|
||||
smtpPass?: string;
|
||||
smtpFrom?: string;
|
||||
smtpTls?: boolean;
|
||||
smtpSkipVerify?: boolean;
|
||||
smtpConfiguredViaEnv?: boolean;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user