From 4ef5402d1c2866d5e201b404ef9722b3be505d8c Mon Sep 17 00:00:00 2001 From: Bob Develop Date: Mon, 27 Apr 2026 08:58:40 -0400 Subject: [PATCH] fix: expose SMTP security/authentication in read-only settings view Add ExternalConfig.smtp_display_settings returning a form-shaped hash (host/port/username/password/domain/from_email/security/authentication) so that the read-only Email SMTP settings view reflects the actual SECURITY value (e.g. noverify) when configured via env vars, instead of always defaulting to STARTTLS. --- app/views/email_smtp_settings/index.html.erb | 2 +- lib/external_config.rb | 18 ++++++++++ spec/lib/external_config_spec.rb | 38 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/app/views/email_smtp_settings/index.html.erb b/app/views/email_smtp_settings/index.html.erb index e2cfa82e..0233c4e7 100644 --- a/app/views/email_smtp_settings/index.html.erb +++ b/app/views/email_smtp_settings/index.html.erb @@ -8,7 +8,7 @@
SMTP is configured via environment variables. These settings are read-only.
- <% value = value.merge(ExternalConfig.smtp_settings.transform_keys { |k| { address: 'host', user_name: 'username' }.fetch(k, k.to_s) }.stringify_keys) %> + <% value = value.merge(ExternalConfig.smtp_display_settings) %> <% end %> <%= form_for @encrypted_config, url: settings_email_index_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
class="space-y-4"> diff --git a/lib/external_config.rb b/lib/external_config.rb index 1560097f..137e0138 100644 --- a/lib/external_config.rb +++ b/lib/external_config.rb @@ -67,6 +67,24 @@ module ExternalConfig }.compact_blank end + # Returns a form-friendly hash mirroring the EncryptedConfig SMTP value shape + # (host/port/username/password/domain/from_email/security/authentication). + # Used by the read-only Email SMTP settings view when configured via ENV. + def smtp_display_settings + return {} unless smtp_configured? + + { + 'host' => ENV.fetch(SMTP_ENV_KEYS[:address], nil), + 'port' => ENV.fetch(SMTP_ENV_KEYS[:port], nil), + 'username' => ENV.fetch(SMTP_ENV_KEYS[:user_name], nil), + 'password' => ENV.fetch(SMTP_ENV_KEYS[:password], nil), + 'domain' => ENV.fetch(SMTP_ENV_KEYS[:domain], nil), + 'from_email' => ENV.fetch(SMTP_ENV_KEYS[:from], nil), + 'security' => ENV.fetch(SMTP_ENV_KEYS[:security], nil).to_s.downcase.presence || 'none', + 'authentication' => ENV.fetch(SMTP_ENV_KEYS[:authentication], 'plain') + }.compact_blank + end + # Storage is considered configured when S3_ATTACHMENTS_BUCKET, GCS_BUCKET, or # AZURE_CONTAINER is provided via ENV. def storage_configured? diff --git a/spec/lib/external_config_spec.rb b/spec/lib/external_config_spec.rb index 1049cd09..88d9d100 100644 --- a/spec/lib/external_config_spec.rb +++ b/spec/lib/external_config_spec.rb @@ -113,6 +113,44 @@ RSpec.describe ExternalConfig do end end + describe '.smtp_display_settings' do + it 'returns empty hash when not configured' do + with_env('DOCUSEAL_CONFIG_SMTP_ADDRESS' => nil) do + expect(described_class.smtp_display_settings).to eq({}) + end + end + + it 'maps env vars to form-shaped string keys' do + envs = { + 'DOCUSEAL_CONFIG_SMTP_ADDRESS' => 'smtp.example.com', + 'DOCUSEAL_CONFIG_SMTP_PORT' => '2525', + 'DOCUSEAL_CONFIG_SMTP_USERNAME' => 'user', + 'DOCUSEAL_CONFIG_SMTP_PASSWORD' => 'secret', + 'DOCUSEAL_CONFIG_SMTP_DOMAIN' => 'example.com', + 'DOCUSEAL_CONFIG_SMTP_FROM' => 'noreply@example.com', + 'DOCUSEAL_CONFIG_SMTP_SECURITY' => 'noverify', + 'DOCUSEAL_CONFIG_SMTP_AUTHENTICATION' => 'login' + } + with_env(envs) do + settings = described_class.smtp_display_settings + expect(settings['host']).to eq('smtp.example.com') + expect(settings['port']).to eq('2525') + expect(settings['username']).to eq('user') + expect(settings['password']).to eq('secret') + expect(settings['domain']).to eq('example.com') + expect(settings['from_email']).to eq('noreply@example.com') + expect(settings['security']).to eq('noverify') + expect(settings['authentication']).to eq('login') + end + end + + it 'defaults security to "none" when blank' do + with_env('DOCUSEAL_CONFIG_SMTP_ADDRESS' => 'smtp.example.com') do + expect(described_class.smtp_display_settings['security']).to eq('none') + end + end + end + describe '.storage_configured?' do it 'returns true when S3_ATTACHMENTS_BUCKET is set' do with_env('S3_ATTACHMENTS_BUCKET' => 'my-bucket') do