Merge branch 'develop' into fix/CW-7007
This commit is contained in:
@@ -17,15 +17,12 @@ module Api::V1::InboxesHelper
|
||||
def validate_imap(channel_data)
|
||||
return unless channel_data.key?('imap_enabled') && channel_data[:imap_enabled]
|
||||
|
||||
Mail.defaults do
|
||||
retriever_method :imap, { address: channel_data[:imap_address],
|
||||
port: channel_data[:imap_port],
|
||||
user_name: channel_data[:imap_login],
|
||||
password: channel_data[:imap_password],
|
||||
enable_ssl: channel_data[:imap_enable_ssl] }
|
||||
end
|
||||
# Validate the user-selected auth mechanism before opening the connection.
|
||||
authentication = Imap::Authentication.validate_user_configurable!(channel_data[:imap_authentication])
|
||||
|
||||
check_imap_connection(channel_data)
|
||||
# Use the same auth adapter as the fetch service so LOGIN uses the IMAP LOGIN command,
|
||||
# not SASL AUTH=LOGIN.
|
||||
check_imap_connection(channel_data, authentication)
|
||||
end
|
||||
|
||||
def validate_smtp(channel_data)
|
||||
@@ -37,8 +34,8 @@ module Api::V1::InboxesHelper
|
||||
check_smtp_connection(channel_data, smtp)
|
||||
end
|
||||
|
||||
def check_imap_connection(channel_data)
|
||||
Mail.connection {} # rubocop:disable:block
|
||||
def check_imap_connection(channel_data, authentication)
|
||||
imap = open_imap_connection(channel_data, authentication)
|
||||
rescue SocketError => e
|
||||
raise StandardError, I18n.t('errors.inboxes.imap.socket_error')
|
||||
rescue Net::IMAP::NoResponseError => e
|
||||
@@ -53,9 +50,20 @@ module Api::V1::InboxesHelper
|
||||
rescue StandardError => e
|
||||
raise StandardError, e.message
|
||||
ensure
|
||||
imap.disconnect if imap.present? && !imap.disconnected?
|
||||
Rails.logger.error "[Api::V1::InboxesHelper] check_imap_connection failed with #{e.message}" if e.present?
|
||||
end
|
||||
|
||||
def open_imap_connection(channel_data, authentication)
|
||||
imap = build_imap_connection(channel_data)
|
||||
Imap::Authentication.authenticate!(imap, authentication, channel_data[:imap_login], channel_data[:imap_password])
|
||||
imap
|
||||
end
|
||||
|
||||
def build_imap_connection(channel_data)
|
||||
Net::IMAP.new(channel_data[:imap_address], port: channel_data[:imap_port], ssl: channel_data[:imap_enable_ssl])
|
||||
end
|
||||
|
||||
def check_smtp_connection(channel_data, smtp)
|
||||
smtp.open_timeout = 10
|
||||
smtp.start(channel_data[:smtp_domain], channel_data[:smtp_login], channel_data[:smtp_password],
|
||||
|
||||
@@ -1011,7 +1011,8 @@
|
||||
"LABEL": "Password",
|
||||
"PLACE_HOLDER": "Password"
|
||||
},
|
||||
"ENABLE_SSL": "Enable SSL"
|
||||
"ENABLE_SSL": "Enable SSL",
|
||||
"AUTH_MECHANISM": "Authentication"
|
||||
},
|
||||
"MICROSOFT": {
|
||||
"TITLE": "Microsoft",
|
||||
|
||||
@@ -5,11 +5,13 @@ import SettingsFieldSection from 'dashboard/components-next/Settings/SettingsFie
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
import { required, minLength } from '@vuelidate/validators';
|
||||
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||
import SingleSelectDropdown from './components/SingleSelectDropdown.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SettingsFieldSection,
|
||||
NextButton,
|
||||
SingleSelectDropdown,
|
||||
},
|
||||
props: {
|
||||
inbox: {
|
||||
@@ -28,6 +30,12 @@ export default {
|
||||
login: '',
|
||||
password: '',
|
||||
isSSLEnabled: true,
|
||||
authMechanism: 'plain',
|
||||
authMechanisms: [
|
||||
{ key: 1, value: 'plain' },
|
||||
{ key: 2, value: 'login' },
|
||||
{ key: 3, value: 'cram-md5' },
|
||||
],
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
@@ -56,6 +64,7 @@ export default {
|
||||
imap_login,
|
||||
imap_password,
|
||||
imap_enable_ssl,
|
||||
imap_authentication,
|
||||
} = this.inbox;
|
||||
this.isIMAPEnabled = imap_enabled;
|
||||
this.address = imap_address;
|
||||
@@ -63,6 +72,7 @@ export default {
|
||||
this.login = imap_login;
|
||||
this.password = imap_password;
|
||||
this.isSSLEnabled = imap_enable_ssl;
|
||||
this.authMechanism = imap_authentication || 'plain';
|
||||
},
|
||||
async updateInbox() {
|
||||
try {
|
||||
@@ -77,6 +87,7 @@ export default {
|
||||
imap_login: this.login,
|
||||
imap_password: this.password,
|
||||
imap_enable_ssl: this.isSSLEnabled,
|
||||
imap_authentication: this.authMechanism,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -90,6 +101,9 @@ export default {
|
||||
useAlert(error.message);
|
||||
}
|
||||
},
|
||||
handleAuthMechanismChange(mode) {
|
||||
this.authMechanism = mode;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -155,6 +169,13 @@ export default {
|
||||
/>
|
||||
{{ $t('INBOX_MGMT.IMAP.ENABLE_SSL') }}
|
||||
</label>
|
||||
<SingleSelectDropdown
|
||||
class="w-full"
|
||||
:label="$t('INBOX_MGMT.IMAP.AUTH_MECHANISM')"
|
||||
:selected="authMechanism"
|
||||
:options="authMechanisms"
|
||||
:action="handleAuthMechanismChange"
|
||||
/>
|
||||
</div>
|
||||
<NextButton
|
||||
type="submit"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# email :string not null
|
||||
# forward_to_email :string not null
|
||||
# imap_address :string default("")
|
||||
# imap_authentication :string default("plain")
|
||||
# imap_enable_ssl :boolean default(TRUE)
|
||||
# imap_enabled :boolean default(FALSE)
|
||||
# imap_login :string default("")
|
||||
@@ -47,7 +48,7 @@ class Channel::Email < ApplicationRecord
|
||||
end
|
||||
|
||||
self.table_name = 'channel_email'
|
||||
EDITABLE_ATTRS = [:email, :imap_enabled, :imap_login, :imap_password, :imap_address, :imap_port, :imap_enable_ssl,
|
||||
EDITABLE_ATTRS = [:email, :imap_enabled, :imap_login, :imap_password, :imap_address, :imap_port, :imap_enable_ssl, :imap_authentication,
|
||||
:smtp_enabled, :smtp_login, :smtp_password, :smtp_address, :smtp_port, :smtp_domain, :smtp_enable_starttls_auto,
|
||||
:smtp_enable_ssl_tls, :smtp_openssl_verify_mode, :smtp_authentication, :provider, :verified_for_sending].freeze
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
module Imap::Authentication
|
||||
DEFAULT_MECHANISM = 'plain'.freeze
|
||||
USER_CONFIGURABLE_MECHANISMS = %w[plain login cram-md5].freeze
|
||||
|
||||
module_function
|
||||
|
||||
def normalize(mechanism)
|
||||
mechanism.presence || DEFAULT_MECHANISM
|
||||
end
|
||||
|
||||
def validate_user_configurable!(mechanism)
|
||||
normalized_mechanism = normalize(mechanism).to_s.downcase
|
||||
return normalized_mechanism if USER_CONFIGURABLE_MECHANISMS.include?(normalized_mechanism)
|
||||
|
||||
allowed_values = USER_CONFIGURABLE_MECHANISMS.join(', ')
|
||||
raise StandardError, "Invalid IMAP authentication mechanism. Allowed values: #{allowed_values}"
|
||||
end
|
||||
|
||||
def authenticate!(imap, mechanism, username, password)
|
||||
normalized_mechanism = normalize(mechanism).to_s.downcase
|
||||
|
||||
case normalized_mechanism
|
||||
when 'cram-md5'
|
||||
imap.authenticate('CRAM-MD5', username, password)
|
||||
when 'login'
|
||||
imap.login(username, password)
|
||||
else
|
||||
imap.authenticate(normalize(mechanism), username, password)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -130,8 +130,9 @@ class Imap::BaseFetchEmailService
|
||||
end
|
||||
|
||||
def build_imap_client
|
||||
imap = Net::IMAP.new(channel.imap_address, port: channel.imap_port, ssl: true)
|
||||
imap.authenticate(authentication_type, channel.imap_login, imap_password)
|
||||
imap = Net::IMAP.new(channel.imap_address, port: channel.imap_port, ssl: channel.imap_enable_ssl)
|
||||
Imap::Authentication.authenticate!(imap, authentication_type, channel.imap_login, imap_password)
|
||||
|
||||
imap.select('INBOX')
|
||||
imap
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class Imap::FetchEmailService < Imap::BaseFetchEmailService
|
||||
private
|
||||
|
||||
def authentication_type
|
||||
'PLAIN'
|
||||
channel.imap_authentication || 'plain'
|
||||
end
|
||||
|
||||
def imap_password
|
||||
|
||||
@@ -90,6 +90,7 @@ if resource.email?
|
||||
json.imap_port resource.channel.try(:imap_port)
|
||||
json.imap_enabled resource.channel.try(:imap_enabled)
|
||||
json.imap_enable_ssl resource.channel.try(:imap_enable_ssl)
|
||||
json.imap_authentication resource.channel.try(:imap_authentication)
|
||||
|
||||
if resource.channel.try(:microsoft?) || resource.channel.try(:google?) || resource.channel.try(:legacy_google?)
|
||||
json.reauthorization_required resource.channel.try(:provider_config).empty? || resource.channel.try(:reauthorization_required?)
|
||||
|
||||
Reference in New Issue
Block a user