feat(server): Option to configure SMTPS transport (#22833)

* feat(server): Option to configure SMTPS transport

This commit adds a boolean option in the SMTP transport configuration to
enable the so-called "secure" mode. What it does is use SMTP over TLS
instead of relying on the more common STARTTLS option over plain SMTP.

* Add missing field in dto

* Add missing field

* Use a switch instead of text field

* Add field in spec

* chore: regen open-api

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
This commit is contained in:
Clement Martin 2025-10-17 12:21:27 +02:00 committed by GitHub
parent 81554e5ad1
commit 95889a69c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 24 additions and 0 deletions

View file

@ -211,6 +211,8 @@
"notification_email_ignore_certificate_errors_description": "Ignore TLS certificate validation errors (not recommended)", "notification_email_ignore_certificate_errors_description": "Ignore TLS certificate validation errors (not recommended)",
"notification_email_password_description": "Password to use when authenticating with the email server", "notification_email_password_description": "Password to use when authenticating with the email server",
"notification_email_port_description": "Port of the email server (e.g 25, 465, or 587)", "notification_email_port_description": "Port of the email server (e.g 25, 465, or 587)",
"notification_email_secure": "SMTPS",
"notification_email_secure_description": "Use SMTPS (SMTP over TLS)",
"notification_email_sent_test_email_button": "Send test email and save", "notification_email_sent_test_email_button": "Send test email and save",
"notification_email_setting_description": "Settings for sending email notifications", "notification_email_setting_description": "Settings for sending email notifications",
"notification_email_test_email": "Send test email", "notification_email_test_email": "Send test email",

View file

@ -16726,6 +16726,9 @@
"minimum": 0, "minimum": 0,
"type": "number" "type": "number"
}, },
"secure": {
"type": "boolean"
},
"username": { "username": {
"type": "string" "type": "string"
} }
@ -16735,6 +16738,7 @@
"ignoreCert", "ignoreCert",
"password", "password",
"port", "port",
"secure",
"username" "username"
], ],
"type": "object" "type": "object"

View file

@ -71,6 +71,7 @@ export type SystemConfigSmtpTransportDto = {
ignoreCert: boolean; ignoreCert: boolean;
password: string; password: string;
port: number; port: number;
secure: boolean;
username: string; username: string;
}; };
export type SystemConfigSmtpDto = { export type SystemConfigSmtpDto = {

View file

@ -159,6 +159,7 @@ export interface SystemConfig {
ignoreCert: boolean; ignoreCert: boolean;
host: string; host: string;
port: number; port: number;
secure: boolean;
username: string; username: string;
password: string; password: string;
}; };
@ -356,6 +357,7 @@ export const defaults = Object.freeze<SystemConfig>({
ignoreCert: false, ignoreCert: false,
host: '', host: '',
port: 587, port: 587,
secure: false,
username: '', username: '',
password: '', password: '',
}, },

View file

@ -463,6 +463,9 @@ class SystemConfigSmtpTransportDto {
@Max(65_535) @Max(65_535)
port!: number; port!: number;
@ValidateBoolean()
secure!: boolean;
@IsString() @IsString()
username!: string; username!: string;

View file

@ -23,6 +23,7 @@ export type SendEmailOptions = {
export type SmtpOptions = { export type SmtpOptions = {
host: string; host: string;
port?: number; port?: number;
secure?: boolean;
username?: string; username?: string;
password?: string; password?: string;
ignoreCert?: boolean; ignoreCert?: boolean;

View file

@ -14,6 +14,7 @@ const smtpTransport = Object.freeze<SystemConfig>({
ignoreCert: false, ignoreCert: false,
host: 'localhost', host: 'localhost',
port: 587, port: 587,
secure: false,
username: 'test', username: 'test',
password: 'test', password: 'test',
}, },

View file

@ -40,6 +40,7 @@ const configs = {
ignoreCert: false, ignoreCert: false,
host: 'localhost', host: 'localhost',
port: 587, port: 587,
secure: false,
username: 'test', username: 'test',
password: 'test', password: 'test',
}, },

View file

@ -197,6 +197,7 @@ const updatedConfig = Object.freeze<SystemConfig>({
transport: { transport: {
host: '', host: '',
port: 587, port: 587,
secure: false,
username: '', username: '',
password: '', password: '',
ignoreCert: false, ignoreCert: false,

View file

@ -45,6 +45,7 @@
transport: { transport: {
host: config.notifications.smtp.transport.host, host: config.notifications.smtp.transport.host,
port: config.notifications.smtp.transport.port, port: config.notifications.smtp.transport.port,
secure: config.notifications.smtp.transport.secure,
username: config.notifications.smtp.transport.username, username: config.notifications.smtp.transport.username,
password: config.notifications.smtp.transport.password, password: config.notifications.smtp.transport.password,
ignoreCert: config.notifications.smtp.transport.ignoreCert, ignoreCert: config.notifications.smtp.transport.ignoreCert,
@ -128,6 +129,13 @@
savedConfig.notifications.smtp.transport.password} savedConfig.notifications.smtp.transport.password}
/> />
<SettingSwitch
title={$t('admin.notification_email_secure')}
subtitle={$t('admin.notification_email_secure_description')}
disabled={disabled || !config.notifications.smtp.enabled}
bind:checked={config.notifications.smtp.transport.secure}
/>
<SettingSwitch <SettingSwitch
title={$t('admin.notification_email_ignore_certificate_errors')} title={$t('admin.notification_email_ignore_certificate_errors')}
subtitle={$t('admin.notification_email_ignore_certificate_errors_description')} subtitle={$t('admin.notification_email_ignore_certificate_errors_description')}