diff --git a/app/helpers/api/v1/inboxes_helper.rb b/app/helpers/api/v1/inboxes_helper.rb index 3d6b559c8..8a10fa99c 100644 --- a/app/helpers/api/v1/inboxes_helper.rb +++ b/app/helpers/api/v1/inboxes_helper.rb @@ -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], diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index 24207cef2..2620f89f7 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -1011,7 +1011,8 @@ "LABEL": "Password", "PLACE_HOLDER": "Password" }, - "ENABLE_SSL": "Enable SSL" + "ENABLE_SSL": "Enable SSL", + "AUTH_MECHANISM": "Authentication" }, "MICROSOFT": { "TITLE": "Microsoft", diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/ImapSettings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/ImapSettings.vue index 7325793db..ab25ed1af 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/ImapSettings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/ImapSettings.vue @@ -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; + }, }, }; @@ -155,6 +169,13 @@ export default { /> {{ $t('INBOX_MGMT.IMAP.ENABLE_SSL') }} +