mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-30 18:47:51 +00:00 
			
		
		
		
	chore: Enable email channel (#1851)
This commit is contained in:
		| @@ -25,7 +25,7 @@ | |||||||
|           <woot-code |           <woot-code | ||||||
|             v-if="isAEmailInbox" |             v-if="isAEmailInbox" | ||||||
|             lang="html" |             lang="html" | ||||||
|             :script="currentInbox.forward_to_address" |             :script="currentInbox.forward_to_email" | ||||||
|           > |           > | ||||||
|           </woot-code> |           </woot-code> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ class ApplicationMailbox < ActionMailbox::Base | |||||||
|     proc do |inbound_mail_obj| |     proc do |inbound_mail_obj| | ||||||
|       is_a_support_email = false |       is_a_support_email = false | ||||||
|       inbound_mail_obj.mail.to.each do |email| |       inbound_mail_obj.mail.to.each do |email| | ||||||
|         channel = Channel::Email.find_by(email: email) |         channel = Channel::Email.find_by('email = ? OR forward_to_email = ?', email, email) | ||||||
|         if channel.present? |         if channel.present? | ||||||
|           is_a_support_email = true |           is_a_support_email = true | ||||||
|           break |           break | ||||||
| @@ -37,7 +37,10 @@ class ApplicationMailbox < ActionMailbox::Base | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   # routing should be defined below the referenced procs |   # routing should be defined below the referenced procs | ||||||
|  |  | ||||||
|  |   # routes as a reply to existing conversations | ||||||
|   routing(reply_mail? => :reply) |   routing(reply_mail? => :reply) | ||||||
|  |   # routes as a new conversation in email channel | ||||||
|   routing(support_mail? => :support) |   routing(support_mail? => :support) | ||||||
|   routing(catch_all_mail? => :default) |   routing(catch_all_mail? => :default) | ||||||
| end | end | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ class SupportMailbox < ApplicationMailbox | |||||||
|  |  | ||||||
|   def find_channel |   def find_channel | ||||||
|     mail.to.each do |email| |     mail.to.each do |email| | ||||||
|       @channel = Channel::Email.find_by(email: email) |       @channel = Channel::Email.find_by('email = ? OR forward_to_email = ?', email, email) | ||||||
|       break if @channel.present? |       break if @channel.present? | ||||||
|     end |     end | ||||||
|     raise 'Email channel/inbox not found' if @channel.nil? |     raise 'Email channel/inbox not found' if @channel.nil? | ||||||
|   | |||||||
| @@ -142,11 +142,7 @@ class ConversationReplyMailer < ApplicationMailer | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def current_domain |   def current_domain | ||||||
|     @current_domain ||= begin |     @current_domain ||= @account.inbound_email_domain | ||||||
|       @account.domain || |  | ||||||
|         ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', false) || |  | ||||||
|         GlobalConfig.get('MAILER_INBOUND_EMAIL_DOMAIN')['MAILER_INBOUND_EMAIL_DOMAIN'] |  | ||||||
|     end |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def account_support_email |   def account_support_email | ||||||
|   | |||||||
| @@ -87,6 +87,14 @@ class Account < ApplicationRecord | |||||||
|     } |     } | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def inbound_email_domain | ||||||
|  |     domain || GlobalConfig.get('MAILER_INBOUND_EMAIL_DOMAIN')['MAILER_INBOUND_EMAIL_DOMAIN'] || ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', false) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def support_email | ||||||
|  |     super || GlobalConfig.get('MAILER_SUPPORT_EMAIL')['MAILER_SUPPORT_EMAIL'] || ENV.fetch('MAILER_SENDER_EMAIL', nil) | ||||||
|  |   end | ||||||
|  |  | ||||||
|   private |   private | ||||||
|  |  | ||||||
|   def notify_creation |   def notify_creation | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| # | # | ||||||
| #  id               :bigint           not null, primary key | #  id               :bigint           not null, primary key | ||||||
| #  email            :string           not null | #  email            :string           not null | ||||||
| #  forward_to_address :string           not null | #  forward_to_email :string           not null | ||||||
| #  created_at       :datetime         not null | #  created_at       :datetime         not null | ||||||
| #  updated_at       :datetime         not null | #  updated_at       :datetime         not null | ||||||
| #  account_id       :integer          not null | #  account_id       :integer          not null | ||||||
| @@ -12,7 +12,7 @@ | |||||||
| # Indexes | # Indexes | ||||||
| # | # | ||||||
| #  index_channel_email_on_email             (email) UNIQUE | #  index_channel_email_on_email             (email) UNIQUE | ||||||
| #  index_channel_email_on_forward_to_address  (forward_to_address) UNIQUE | #  index_channel_email_on_forward_to_email  (forward_to_email) UNIQUE | ||||||
| # | # | ||||||
|  |  | ||||||
| class Channel::Email < ApplicationRecord | class Channel::Email < ApplicationRecord | ||||||
| @@ -21,10 +21,10 @@ class Channel::Email < ApplicationRecord | |||||||
|   validates :account_id, presence: true |   validates :account_id, presence: true | ||||||
|   belongs_to :account |   belongs_to :account | ||||||
|   validates :email, uniqueness: true |   validates :email, uniqueness: true | ||||||
|   validates :forward_to_address, uniqueness: true |   validates :forward_to_email, uniqueness: true | ||||||
|  |  | ||||||
|   has_one :inbox, as: :channel, dependent: :destroy |   has_one :inbox, as: :channel, dependent: :destroy | ||||||
|   before_validation :ensure_forward_to_address, on: :create |   before_validation :ensure_forward_to_email, on: :create | ||||||
|  |  | ||||||
|   def name |   def name | ||||||
|     'Email' |     'Email' | ||||||
| @@ -36,8 +36,7 @@ class Channel::Email < ApplicationRecord | |||||||
|  |  | ||||||
|   private |   private | ||||||
|  |  | ||||||
|   def ensure_forward_to_address |   def ensure_forward_to_email | ||||||
|     email_domain = InstallationConfig.find_by(name: 'MAILER_INBOUND_EMAIL_DOMAIN')&.value |     self.forward_to_email ||= "#{SecureRandom.hex}@#{account.inbound_email_domain}" | ||||||
|     self.forward_to_address ||= "#{SecureRandom.hex}@#{email_domain}" |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -91,13 +91,13 @@ class MailPresenter < SimpleDelegator | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   def quoted_text_regexes |   def quoted_text_regexes | ||||||
|     return sender_agnostic_regexes if @account.nil? || account_support_email.blank? |     return sender_agnostic_regexes if @account.nil? || @account.support_email.blank? | ||||||
|  |  | ||||||
|     [ |     [ | ||||||
|       Regexp.new("From:\s* #{Regexp.escape(account_support_email)}", Regexp::IGNORECASE), |       Regexp.new("From:\s* #{Regexp.escape(@account.support_email)}", Regexp::IGNORECASE), | ||||||
|       Regexp.new("<#{Regexp.escape(account_support_email)}>", Regexp::IGNORECASE), |       Regexp.new("<#{Regexp.escape(@account.support_email)}>", Regexp::IGNORECASE), | ||||||
|       Regexp.new("#{Regexp.escape(account_support_email)}\s+wrote:", Regexp::IGNORECASE), |       Regexp.new("#{Regexp.escape(@account.support_email)}\s+wrote:", Regexp::IGNORECASE), | ||||||
|       Regexp.new("On(.*)#{Regexp.escape(account_support_email)}(.*)wrote:", Regexp::IGNORECASE) |       Regexp.new("On(.*)#{Regexp.escape(@account.support_email)}(.*)wrote:", Regexp::IGNORECASE) | ||||||
|     ] + sender_agnostic_regexes |     ] + sender_agnostic_regexes | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -109,12 +109,4 @@ class MailPresenter < SimpleDelegator | |||||||
|       Regexp.new("from:\s*$", Regexp::IGNORECASE) |       Regexp.new("from:\s*$", Regexp::IGNORECASE) | ||||||
|     ] |     ] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def account_support_email |  | ||||||
|     @account_support_email ||= begin |  | ||||||
|       @account.support_email || |  | ||||||
|         GlobalConfig.get('MAILER_SUPPORT_EMAIL')['MAILER_SUPPORT_EMAIL'] || |  | ||||||
|         ENV.fetch('MAILER_SENDER_EMAIL', nil) |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end | end | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ json.welcome_tagline resource.channel.try(:welcome_tagline) | |||||||
| json.enable_auto_assignment resource.enable_auto_assignment | json.enable_auto_assignment resource.enable_auto_assignment | ||||||
| json.web_widget_script resource.channel.try(:web_widget_script) | json.web_widget_script resource.channel.try(:web_widget_script) | ||||||
| json.website_token resource.channel.try(:website_token) | json.website_token resource.channel.try(:website_token) | ||||||
| json.forward_to_address resource.channel.try(:forward_to_address) | json.forward_to_email resource.channel.try(:forward_to_email) | ||||||
| json.phone_number resource.channel.try(:phone_number) | json.phone_number resource.channel.try(:phone_number) | ||||||
| json.selected_feature_flags resource.channel.try(:selected_feature_flags) | json.selected_feature_flags resource.channel.try(:selected_feature_flags) | ||||||
| json.reply_time resource.channel.try(:reply_time) | json.reply_time resource.channel.try(:reply_time) | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| - name: inbound_emails | - name: inbound_emails | ||||||
|   enabled: false |   enabled: false | ||||||
| - name: channel_email | - name: channel_email | ||||||
|   enabled: false |   enabled: true | ||||||
| - name: channel_facebook | - name: channel_facebook | ||||||
|   enabled: true |   enabled: true | ||||||
| - name: channel_twitter | - name: channel_twitter | ||||||
|   | |||||||
| @@ -0,0 +1,5 @@ | |||||||
|  | class RenameChannelEmailForwardAddress < ActiveRecord::Migration[6.0] | ||||||
|  |   def change | ||||||
|  |     rename_column :channel_email, :forward_to_address, :forward_to_email | ||||||
|  |   end | ||||||
|  | end | ||||||
| @@ -10,7 +10,7 @@ | |||||||
| # | # | ||||||
| # It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||||
|  |  | ||||||
| ActiveRecord::Schema.define(version: 2021_02_22_131155) do | ActiveRecord::Schema.define(version: 2021_03_03_192243) do | ||||||
|  |  | ||||||
|   # These are extensions that must be enabled in order to support this database |   # These are extensions that must be enabled in order to support this database | ||||||
|   enable_extension "pg_stat_statements" |   enable_extension "pg_stat_statements" | ||||||
| @@ -131,11 +131,11 @@ ActiveRecord::Schema.define(version: 2021_02_22_131155) do | |||||||
|   create_table "channel_email", force: :cascade do |t| |   create_table "channel_email", force: :cascade do |t| | ||||||
|     t.integer "account_id", null: false |     t.integer "account_id", null: false | ||||||
|     t.string "email", null: false |     t.string "email", null: false | ||||||
|     t.string "forward_to_address", null: false |     t.string "forward_to_email", null: false | ||||||
|     t.datetime "created_at", precision: 6, null: false |     t.datetime "created_at", precision: 6, null: false | ||||||
|     t.datetime "updated_at", precision: 6, null: false |     t.datetime "updated_at", precision: 6, null: false | ||||||
|     t.index ["email"], name: "index_channel_email_on_email", unique: true |     t.index ["email"], name: "index_channel_email_on_email", unique: true | ||||||
|     t.index ["forward_to_address"], name: "index_channel_email_on_forward_to_address", unique: true |     t.index ["forward_to_email"], name: "index_channel_email_on_forward_to_email", unique: true | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   create_table "channel_facebook_pages", id: :serial, force: :cascade do |t| |   create_table "channel_facebook_pages", id: :serial, force: :cascade do |t| | ||||||
|   | |||||||
| @@ -13,9 +13,7 @@ unless Rails.env.production? | |||||||
|   SuperAdmin.create!(email: 'john@acme.inc', password: '123456') |   SuperAdmin.create!(email: 'john@acme.inc', password: '123456') | ||||||
|  |  | ||||||
|   account = Account.create!( |   account = Account.create!( | ||||||
|     name: 'Acme Inc', |     name: 'Acme Inc' | ||||||
|     domain: 'support.chatwoot.com', |  | ||||||
|     support_email: ENV.fetch('MAILER_SENDER_EMAIL', 'accounts@chatwoot.com') |  | ||||||
|   ) |   ) | ||||||
|  |  | ||||||
|   user = User.new(name: 'John', email: 'john@acme.inc', password: '123456') |   user = User.new(name: 'John', email: 'john@acme.inc', password: '123456') | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| FactoryBot.define do | FactoryBot.define do | ||||||
|   factory :channel_email, class: 'Channel::Email' do |   factory :channel_email, class: 'Channel::Email' do | ||||||
|     sequence(:email) { |n| "care-#{n}@example.com" } |     sequence(:email) { |n| "care-#{n}@example.com" } | ||||||
|     sequence(:forward_to_address) { |n| "forward-#{n}@chatwoot.com" } |     sequence(:forward_to_email) { |n| "forward-#{n}@chatwoot.com" } | ||||||
|     account |     account | ||||||
|     after(:create) do |channel_email| |     after(:create) do |channel_email| | ||||||
|       create(:inbox, channel: channel_email, account: channel_email.account) |       create(:inbox, channel: channel_email, account: channel_email.account) | ||||||
|   | |||||||
| @@ -29,13 +29,18 @@ RSpec.describe ApplicationMailbox, type: :mailbox do | |||||||
|     describe 'Support' do |     describe 'Support' do | ||||||
|       let!(:channel_email) { create(:channel_email) } |       let!(:channel_email) { create(:channel_email) } | ||||||
|  |  | ||||||
|       before do |       it 'routes support emails to Support Mailbox when mail is to channel email' do | ||||||
|         # this email is hardcoded in the support.eml, that's why we are updating this |         # this email is hardcoded in the support.eml, that's why we are updating this | ||||||
|         channel_email.email = 'care@example.com' |         channel_email.update(email: 'care@example.com') | ||||||
|         channel_email.save |         dbl = double | ||||||
|  |         expect(SupportMailbox).to receive(:new).and_return(dbl) | ||||||
|  |         expect(dbl).to receive(:perform_processing).and_return(true) | ||||||
|  |         described_class.route support_mail | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       it 'routes support emails to Support Mailbox' do |       it 'routes support emails to Support Mailbox when mail is to channel forward to email' do | ||||||
|  |         # this email is hardcoded in the support.eml, that's why we are updating this | ||||||
|  |         channel_email.update(forward_to_email: 'care@example.com') | ||||||
|         dbl = double |         dbl = double | ||||||
|         expect(SupportMailbox).to receive(:new).and_return(dbl) |         expect(SupportMailbox).to receive(:new).and_return(dbl) | ||||||
|         expect(dbl).to receive(:perform_processing).and_return(true) |         expect(dbl).to receive(:perform_processing).and_return(true) | ||||||
|   | |||||||
| @@ -95,7 +95,7 @@ RSpec.describe ConversationReplyMailer, type: :mailer do | |||||||
|       let(:conversation) { create(:conversation, assignee: agent, inbox: inbox_member.inbox, account: account) } |       let(:conversation) { create(:conversation, assignee: agent, inbox: inbox_member.inbox, account: account) } | ||||||
|       let!(:message) { create(:message, conversation: conversation, account: account) } |       let!(:message) { create(:message, conversation: conversation, account: account) } | ||||||
|       let(:mail) { described_class.reply_with_summary(message.conversation, Time.zone.now).deliver_now } |       let(:mail) { described_class.reply_with_summary(message.conversation, Time.zone.now).deliver_now } | ||||||
|       let(:domain) { account.domain || ENV.fetch('MAILER_INBOUND_EMAIL_DOMAIN', false) } |       let(:domain) { account.inbound_email_domain } | ||||||
|  |  | ||||||
|       it 'renders the receiver email' do |       it 'renders the receiver email' do | ||||||
|         expect(mail.to).to eq([message&.conversation&.contact&.email]) |         expect(mail.to).to eq([message&.conversation&.contact&.email]) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sojan Jose
					Sojan Jose