summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-14 14:17:48 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-14 14:17:48 +0000
commitd56c47033c32d6d32a864e5c16a3b2fd959b08da (patch)
tree8a249fae71ddfef174030ce966e5ebe6ed2937c5
parent1b7933f32303f102555ce078716a33a701e434e1 (diff)
downloadgitlab-ce-d56c47033c32d6d32a864e5c16a3b2fd959b08da.tar.gz
Add latest changes from gitlab-org/gitlab@15-10-stable-ee
-rw-r--r--Gemfile4
-rw-r--r--config/initializers/mail_starttls_patch.rb87
-rw-r--r--spec/initializers/mail_starttls_patch_spec.rb86
3 files changed, 177 insertions, 0 deletions
diff --git a/Gemfile b/Gemfile
index 15995b07e1f..a8063691b7e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -546,6 +546,10 @@ gem 'lru_redux'
# Locked as long as quoted-printable encoding issues are not resolved
# Monkey-patched in `config/initializers/mail_encoding_patch.rb`
# See https://gitlab.com/gitlab-org/gitlab/issues/197386
+#
+# `config/initializers/mail_starttls_patch.rb` has also been patched to
+# fix STARTTLS handling until https://github.com/mikel/mail/pull/1536 is
+# released.
gem 'mail', '= 2.8.1'
gem 'mail-smtp_pool', '~> 0.1.0', path: 'vendor/gems/mail-smtp_pool', require: false
diff --git a/config/initializers/mail_starttls_patch.rb b/config/initializers/mail_starttls_patch.rb
new file mode 100644
index 00000000000..c4fe102edfb
--- /dev/null
+++ b/config/initializers/mail_starttls_patch.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'mail/network/delivery_methods/smtp'
+
+# Monkey patch mail 2.8.1 to make it possible to disable STARTTLS.
+# without having to change existing settings.
+# This brings in changes from https://github.com/mikel/mail/pull/1536,
+# which has not been released yet.
+module Mail
+ class SMTP
+ def initialize(values)
+ self.settings = DEFAULTS
+ settings[:enable_starttls_auto] = nil
+ settings.merge!(values)
+ end
+
+ private
+
+ # `key` is said to be provided when `settings` has a non-nil value for `key`.
+ def setting_provided?(key)
+ !settings[key].nil?
+ end
+
+ # Yields one of `:always`, `:auto` or `false` based on `enable_starttls` and `enable_starttls_auto` flags.
+ # Yields `false` when `smtp_tls?`.
+ def smtp_starttls
+ return false if smtp_tls?
+
+ if setting_provided?(:enable_starttls) && settings[:enable_starttls]
+ # enable_starttls: provided and truthy
+ case settings[:enable_starttls]
+ when :auto then :auto
+ when :always then :always
+ else
+ :always
+ end
+ elsif setting_provided?(:enable_starttls_auto)
+ # enable_starttls: not provided or false
+ settings[:enable_starttls_auto] ? :auto : false
+ else
+ # enable_starttls_auto: not provided
+ # enable_starttls: when provided then false
+ # use :auto when neither enable_starttls* provided
+ setting_provided?(:enable_starttls) ? false : :auto
+ end
+ end
+
+ def smtp_tls?
+ (setting_provided?(:tls) && settings[:tls]) || (setting_provided?(:ssl) && settings[:ssl])
+ end
+
+ def start_smtp_session(&block)
+ build_smtp_session.start(settings[:domain], settings[:user_name], settings[:password],
+ settings[:authentication], &block)
+ end
+
+ def build_smtp_session
+ if smtp_tls? && (settings[:enable_starttls] || settings[:enable_starttls_auto])
+ # rubocop:disable Layout/LineLength
+ raise ArgumentError,
+ ":enable_starttls and :tls are mutually exclusive. Set :tls if you're on an SMTPS connection. Set :enable_starttls if you're on an SMTP connection and using STARTTLS for secure TLS upgrade."
+ # rubocop:enable Layout/LineLength
+ end
+
+ Net::SMTP.new(settings[:address], settings[:port]).tap do |smtp|
+ if smtp_tls?
+ smtp.disable_starttls
+ smtp.enable_tls(ssl_context)
+ else
+ smtp.disable_tls
+
+ case smtp_starttls
+ when :always
+ smtp.enable_starttls(ssl_context)
+ when :auto
+ smtp.enable_starttls_auto(ssl_context)
+ else
+ smtp.disable_starttls
+ end
+ end
+
+ smtp.open_timeout = settings[:open_timeout] if settings[:open_timeout]
+ smtp.read_timeout = settings[:read_timeout] if settings[:read_timeout]
+ end
+ end
+ end
+end
diff --git a/spec/initializers/mail_starttls_patch_spec.rb b/spec/initializers/mail_starttls_patch_spec.rb
new file mode 100644
index 00000000000..126ffb98f0e
--- /dev/null
+++ b/spec/initializers/mail_starttls_patch_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+# rubocop:disable RSpec/VariableDefinition, RSpec/VariableName
+
+require 'spec_helper'
+require 'mail'
+require_relative '../../config/initializers/mail_starttls_patch'
+
+RSpec.describe 'Mail STARTTLS patch', feature_category: :integrations do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:message) do
+ Mail.new do
+ from 'sender@example.com'
+ to 'receiver@example.com'
+ subject 'test mesage'
+ end
+ end
+
+ # Taken from https://github.com/mikel/mail/pull/1536#issue-1490438378
+ where(:ssl, :tls, :enable_starttls, :enable_starttls_auto, :smtp_tls, :smtp_starttls_mode) do
+ true | nil | nil | nil | true | false
+ nil | false | nil | nil | false | :auto
+ nil | false | nil | true | false | :auto
+ false | false | true | false | false | :always
+ false | nil | false | false | false | false
+ false | false | false | nil | false | false
+ false | nil | :always | nil | false | :always
+ false | nil | :auto | nil | false | :auto
+ end
+
+ with_them do
+ let(:values) do
+ {
+ ssl: ssl,
+ tls: tls,
+ enable_starttls: enable_starttls,
+ enable_starttls_auto: enable_starttls_auto
+ }
+ end
+
+ let(:mail) { Mail::SMTP.new(values) }
+ let(:smtp) { double }
+
+ it 'sets TLS and STARTTLS settings properly' do
+ expect(smtp).to receive(:open_timeout=)
+ expect(smtp).to receive(:read_timeout=)
+ expect(smtp).to receive(:start)
+
+ if smtp_tls
+ expect(smtp).to receive(:enable_tls)
+ expect(smtp).to receive(:disable_starttls)
+ else
+ expect(smtp).to receive(:disable_tls)
+
+ case smtp_starttls_mode
+ when :always
+ expect(smtp).to receive(:enable_starttls)
+ when :auto
+ expect(smtp).to receive(:enable_starttls_auto)
+ when false
+ expect(smtp).to receive(:disable_starttls)
+ end
+ end
+
+ allow(Net::SMTP).to receive(:new).and_return(smtp)
+ mail.deliver!(message)
+ end
+ end
+
+ context 'when enable_starttls and tls are enabled' do
+ let(:values) do
+ {
+ tls: true,
+ enable_starttls: true
+ }
+ end
+
+ let(:mail) { Mail::SMTP.new(values) }
+
+ it 'raises an argument exception' do
+ expect { mail.deliver!(message) }.to raise_error(ArgumentError)
+ end
+ end
+end
+# rubocop:enable RSpec/VariableDefinition, RSpec/VariableName