diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index 757af9b62..f12421012 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -31,6 +31,9 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController end def create + validate_new_email_channel + return if performed? + ActiveRecord::Base.transaction do channel = create_channel @inbox = Current.account.inboxes.build( @@ -43,6 +46,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController ) @inbox.save! end + enqueue_initial_imap_fetch end def update @@ -96,6 +100,26 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController account_channels_method.create!(permitted_params(channel_type_from_params::EDITABLE_ATTRS)[:channel].except(:type)) end + def validate_new_email_channel + return unless params.dig(:channel, :type) == 'email' + + validate_email_channel(Channel::Email::EDITABLE_ATTRS) + rescue StandardError => e + render json: { message: e }, status: :unprocessable_entity + end + + def enqueue_initial_imap_fetch + return unless @inbox.channel.is_a?(Channel::Email) + return unless @inbox.channel.imap_enabled? + + ::Inboxes::FetchImapEmailsJob.perform_later(@inbox.channel, initial_imap_fetch_interval) + end + + def initial_imap_fetch_interval + interval = params[:imap_fetch_interval].to_i + [1, 7, 30].include?(interval) ? interval : 1 + end + def allowed_channel_types %w[web_widget api email line telegram whatsapp sms] end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index b6df015f7..ad9bd3ff2 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -77,6 +77,7 @@ class DashboardController < ActionController::Base FACEBOOK_API_VERSION: GlobalConfigService.load('FACEBOOK_API_VERSION', 'v18.0'), WHATSAPP_APP_ID: GlobalConfigService.load('WHATSAPP_APP_ID', ''), WHATSAPP_CONFIGURATION_ID: GlobalConfigService.load('WHATSAPP_CONFIGURATION_ID', ''), + INBOUND_EMAIL_DOMAIN_PRESENT: GlobalConfigService.load('MAILER_INBOUND_EMAIL_DOMAIN', '').present?, IS_ENTERPRISE: ChatwootApp.enterprise?, AZURE_APP_ID: GlobalConfigService.load('AZURE_APP_ID', ''), GIT_SHA: GIT_HASH, diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index cd7e46330..654eed152 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -401,11 +401,25 @@ "API": { "ERROR_MESSAGE": "We were not able to save the email channel" }, - "FINISH_MESSAGE": "Your email inbox has been created successfully! You can start forwarding your emails to the address below, or configure SMTP and IMAP credentials to send and receive emails directly.", - "FINISH_MESSAGE_NO_FORWARDING": "Your email inbox has been created successfully! You need to configure SMTP and IMAP credentials to send and receive emails. Without these settings, no emails will be processed.", + "SETUP_OPTIONS": { + "FORWARDING": { + "TITLE": "Email forwarding", + "DESCRIPTION": "Use a forwarding address" + } + }, + "FETCH_EMAILS_FROM": "Fetch emails from", + "IMPORT_OPTIONS": { + "TITLE": "Initial import", + "ONE_DAY": "Last 1 day", + "SEVEN_DAYS": "Last 7 days", + "THIRTY_DAYS": "Last 30 days" + }, + "FINISH_MESSAGE_FORWARDING": "Your email inbox is ready. Set up a forwarding rule in your email provider to start receiving conversations in Chatwoot.", + "FINISH_MESSAGE_IMAP_SMTP": "Your email inbox is connected. Chatwoot will fetch new emails from your mailbox and use the SMTP settings for replies.", "FORWARDING_ADDRESS_LABEL": "Forward emails to this address:", - "CONFIGURE_SMTP_IMAP_LINK": "Click here", - "CONFIGURE_SMTP_IMAP_TEXT": " to configure IMAP and SMTP settings" + "FORWARDING_RULE_HELP": "Use this address as the destination when you create the forwarding rule in your mailbox.", + "CONFIGURE_EMAIL_SETTINGS_LINK": "Open email settings", + "MANAGE_SMTP_IMAP_TEXT": " to review or update IMAP and SMTP settings." }, "LINE_CHANNEL": { "TITLE": "LINE Channel", @@ -520,8 +534,8 @@ "DESC": "You have successfully finished integrating your Facebook Page with Chatwoot. Next time a customer messages your Page, the conversation will automatically appear on your inbox.
We are also providing you with a widget script that you can easily add to your website. Once this is live on your website, customers can message you right from your website without the help of any external tool and the conversation will appear right here, on Chatwoot.
Cool, huh? Well, we sure try to be :)" }, "EMAIL_PROVIDER": { - "TITLE": "Select your email provider", - "DESCRIPTION": "Select an email provider from the list below. If you don't see your email provider in the list, you can select the other provider option and provide the IMAP and SMTP Credentials." + "TITLE": "Set up your email inbox", + "DESCRIPTION": "Connect a provider, use IMAP/SMTP, or forward emails to Chatwoot." }, "MICROSOFT": { "TITLE": "Microsoft Email", @@ -795,8 +809,8 @@ "HMAC_MANDATORY_DESCRIPTION": "If enabled, requests that cannot be verified will be rejected.", "INBOX_IDENTIFIER": "Inbox Identifier", "INBOX_IDENTIFIER_SUB_TEXT": "Use the `inbox_identifier` token shown here to authentication your API clients.", - "FORWARD_EMAIL_TITLE": "Forward to Email", - "FORWARD_EMAIL_SUB_TEXT": "Start forwarding your emails to the following email address.", + "FORWARD_EMAIL_TITLE": "Email forwarding", + "FORWARD_EMAIL_SUB_TEXT": "Forward emails from your provider to this address.", "FORWARD_EMAIL_NOT_CONFIGURED": "Forwarding emails to your inbox is currently disabled on this installation. To use this feature, it must be enabled by your administrator. Please get in touch with them to proceed.", "ALLOW_MESSAGES_AFTER_RESOLVED": "Allow messages after conversation resolved", "ALLOW_MESSAGES_AFTER_RESOLVED_SUB_TEXT": "Allow the end-users to send messages even after the conversation is resolved.", @@ -1017,6 +1031,7 @@ }, "IMAP": { "TITLE": "IMAP", + "CREATE_HELP": "Receive emails from this mailbox.", "SUBTITLE": "Set your IMAP details", "NOTE_TEXT": "To enable SMTP, please configure IMAP.", "UPDATE": "Update IMAP settings", @@ -1050,11 +1065,12 @@ "SUBTITLE": "Reauthorize your MICROSOFT account" }, "SMTP": { - "TITLE": "SMTP", - "SUBTITLE": "Set your SMTP details", + "TITLE": "Outgoing email", + "CREATE_HELP": "Send replies through this mailbox.", + "SUBTITLE": "Send replies using your own email provider.", "UPDATE": "Update SMTP settings", - "TOGGLE_AVAILABILITY": "Enable SMTP configuration for this inbox", - "TOGGLE_HELP": "Enabling SMTP will help the user to send email", + "TOGGLE_AVAILABILITY": "Send replies via a custom mail server", + "TOGGLE_HELP": "Optional. Configure SMTP when replies should be sent through your own email provider.", "EDIT": { "SUCCESS_MESSAGE": "SMTP settings updated successfully", "ERROR_MESSAGE": "Unable to update SMTP settings" diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/ChannelList.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/ChannelList.vue index de0c6059b..6bef179d2 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/ChannelList.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/ChannelList.vue @@ -1,5 +1,5 @@ diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/EmailInboxFinish.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/EmailInboxFinish.vue index be5b94087..90d551e14 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/EmailInboxFinish.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/EmailInboxFinish.vue @@ -15,31 +15,41 @@ const props = defineProps({ const { t } = useI18n(); +const isImapSmtpInbox = computed(() => { + return props.inbox.imap_enabled; +}); + const message = computed(() => { - return props.inbox.forwarding_enabled - ? t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE') - : t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE_NO_FORWARDING'); + return isImapSmtpInbox.value + ? t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE_IMAP_SMTP') + : t('INBOX_MGMT.ADD.EMAIL_CHANNEL.FINISH_MESSAGE_FORWARDING'); }); const showForwardingAddress = computed(() => { - return props.inbox.forwarding_enabled; + return !isImapSmtpInbox.value && props.inbox.forwarding_enabled; }); diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/ImapSmtpOption.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/ImapSmtpOption.vue new file mode 100644 index 000000000..09c5582db --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/ImapSmtpOption.vue @@ -0,0 +1,345 @@ + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/ConfigurationPage.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/ConfigurationPage.vue index 8beaea489..c850ffb21 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/ConfigurationPage.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/ConfigurationPage.vue @@ -59,6 +59,9 @@ export default { isForwardingEnabled() { return !!this.inbox.forwarding_enabled; }, + isForwardingEmailInbox() { + return this.isForwardingEnabled && !this.inbox.imap_enabled; + }, }, watch: { inbox() { @@ -331,7 +334,7 @@ export default {
-
+
- + +
diff --git a/app/javascript/shared/store/globalConfig.js b/app/javascript/shared/store/globalConfig.js index c1786238b..ed33166ae 100644 --- a/app/javascript/shared/store/globalConfig.js +++ b/app/javascript/shared/store/globalConfig.js @@ -15,6 +15,7 @@ const { MAXIMUM_FILE_UPLOAD_SIZE: maximumFileUploadSize, HCAPTCHA_SITE_KEY: hCaptchaSiteKey, INSTALLATION_NAME: installationName, + INBOUND_EMAIL_DOMAIN_PRESENT: inboundEmailDomainPresent, LOGO_THUMBNAIL: logoThumbnail, LOGO: logo, LOGO_DARK: logoDark, @@ -43,6 +44,7 @@ const state = { maximumFileUploadSize: resolveMaximumFileUploadSize(maximumFileUploadSize), hCaptchaSiteKey, installationName, + inboundEmailDomainPresent: parseBoolean(inboundEmailDomainPresent), logo, logoDark, logoThumbnail, diff --git a/app/views/api/v1/models/_inbox.json.jbuilder b/app/views/api/v1/models/_inbox.json.jbuilder index 0ae0745cd..9ec47d858 100644 --- a/app/views/api/v1/models/_inbox.json.jbuilder +++ b/app/views/api/v1/models/_inbox.json.jbuilder @@ -79,8 +79,8 @@ end if resource.email? ## Email Channel Attributes json.email resource.channel.try(:email) - json.forwarding_enabled ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', '').present? - json.forward_to_email resource.channel.try(:forward_to_email) if ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', '').present? + json.forwarding_enabled resource.account.inbound_email_domain.present? + json.forward_to_email resource.channel.try(:forward_to_email) if resource.account.inbound_email_domain.present? ## IMAP if Current.account_user&.administrator? diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb index 9e03e2587..a0d352a97 100644 --- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb @@ -399,6 +399,40 @@ RSpec.describe 'Inboxes API', type: :request do expect(response.body).to include('test@test.com') end + it 'creates an email inbox with imap settings and queues the selected import window' do + imap_connection = instance_double(Net::IMAP, disconnected?: false) + + allow(Net::IMAP).to receive(:new).and_return(imap_connection) + allow(imap_connection).to receive(:login) + allow(imap_connection).to receive(:disconnect) + + expect do + post "/api/v1/accounts/#{account.id}/inboxes", + headers: admin.create_new_auth_token, + params: { + name: 'Support', + imap_fetch_interval: 7, + channel: { + type: 'email', + email: 'support@example.com', + imap_enabled: true, + imap_address: 'imap.example.com', + imap_port: 993, + imap_login: 'support@example.com', + imap_password: 'imap-password', + imap_enable_ssl: true, + imap_authentication: 'login' + } + }, + as: :json + end.to have_enqueued_job(Inboxes::FetchImapEmailsJob).with(a_kind_of(Channel::Email), 7) + + expect(response).to have_http_status(:success) + channel = Channel::Email.find_by!(email: 'support@example.com') + expect(channel.imap_enabled).to be true + expect(channel.smtp_enabled).to be false + end + it 'creates an api inbox when administrator' do post "/api/v1/accounts/#{account.id}/inboxes", headers: admin.create_new_auth_token,