chore: Stop processing auto-response emails (#9606)

Stop processing auto-response emails
https://www.notion.so/chatwoot/Avoid-Auto-Replies-sorcerer-s-apprentice-mode-55ffb09efbd7451994f1ff852de4c168?pvs=4
This commit is contained in:
Sojan Jose
2024-06-13 14:19:11 -07:00
committed by GitHub
parent 08516e6c43
commit 7968e98529
9 changed files with 1344 additions and 34 deletions

View File

@@ -1,5 +1,6 @@
class Imap::ImapMailbox
include MailboxHelper
include IncomingEmailValidityHelper
attr_accessor :channel, :account, :inbox, :conversation, :processed_mail
def process(mail, channel)
@@ -9,11 +10,10 @@ class Imap::ImapMailbox
load_inbox
decorate_mail
# prevent loop from chatwoot notification emails
return if notification_email_from_chatwoot?
Rails.logger.info("Processing Email from: #{@processed_mail.original_sender} : inbox #{@inbox.id} : message_id #{@processed_mail.message_id}")
# Stop processing if email format doesn't match Chatwoot supported mail format
return unless email_from_valid_email?
# Skip processing email if it belongs to any of the edge cases
return unless incoming_email_from_valid_email?
ActiveRecord::Base.transaction do
find_or_create_contact
@@ -37,18 +37,6 @@ class Imap::ImapMailbox
@processed_mail = MailPresenter.new(@inbound_mail, @account)
end
def email_from_valid_email?
Rails.logger.info("Processing Email from: #{@processed_mail.original_sender} : inbox #{@inbox.id}")
# validate email with Devise.email_regexp
if Devise.email_regexp.match?(@processed_mail.original_sender)
true
else
Rails.logger.error("Email from: #{@processed_mail.original_sender} : inbox #{@inbox.id} is invalid")
false
end
end
def find_conversation_by_in_reply_to
return if in_reply_to.blank?

View File

@@ -0,0 +1,35 @@
module IncomingEmailValidityHelper
private
def incoming_email_from_valid_email?
return false unless valid_external_email_for_active_account?
# we skip processing auto reply emails like delivery status notifications
# out of office replies, etc.
return false if auto_reply_email?
# return if email doesn't have a valid sender
# This can happen in cases like bounce emails for invalid contact email address
# TODO: Handle the bounce separately and mark the contact as invalid in case of reply bounces
# The returned value could be "\"\"" for some email clients
return false unless Devise.email_regexp.match?(@processed_mail.original_sender)
true
end
def valid_external_email_for_active_account?
return false unless @account.active?
return false if @processed_mail.notification_email_from_chatwoot?
true
end
def auto_reply_email?
if @processed_mail.auto_reply?
Rails.logger.info "is_auto_reply? : #{processed_mail.auto_reply?}"
true
else
false
end
end
end

View File

@@ -112,11 +112,6 @@ module MailboxHelper
Rails.logger.info "[MailboxHelper] Contact created with ID: #{@contact.id} for inbox with ID: #{@inbox.id}"
end
def notification_email_from_chatwoot?
# notification emails are send via mailer sender email address. so it should match
@processed_mail.original_sender == Mail::Address.new(ENV.fetch('MAILER_SENDER_EMAIL', 'Chatwoot <accounts@chatwoot.com>')).address
end
def mail_content
if processed_mail.text_content.present?
processed_mail.text_content[:reply]

View File

@@ -1,4 +1,5 @@
class SupportMailbox < ApplicationMailbox
include IncomingEmailValidityHelper
attr_accessor :channel, :account, :inbox, :conversation, :processed_mail
before_processing :find_channel,
@@ -9,16 +10,8 @@ class SupportMailbox < ApplicationMailbox
def process
Rails.logger.info "Processing email #{mail.message_id} from #{original_sender_email} to #{mail.to} with subject #{mail.subject}"
# to turn off spam conversation creation
return unless @account.active?
# prevent loop from chatwoot notification emails
return if notification_email_from_chatwoot?
# return if email doesn't have a valid sender
# This can happen in cases like bounce emails for invalid contact email address
# TODO: Handle the bounce seperately and mark the contact as invalid
# we are checking for @ since the returned value could be "\"\"" for some email clients
return unless original_sender_email.include?('@')
# Skip processing email if it belongs to any of the edge cases
return unless incoming_email_from_valid_email?
ActiveRecord::Base.transaction do
find_or_create_contact

View File

@@ -146,8 +146,25 @@ class MailPresenter < SimpleDelegator
end
end
def auto_reply?
auto_submitted? || x_auto_reply?
end
def notification_email_from_chatwoot?
# notification emails are send via mailer sender email address. so it should match
original_sender == Mail::Address.new(ENV.fetch('MAILER_SENDER_EMAIL', 'Chatwoot <accounts@chatwoot.com>')).address
end
private
def auto_submitted?
@mail['Auto-Submitted'].present? && @mail['Auto-Submitted'].value != 'no'
end
def x_auto_reply?
@mail['X-Autoreply'].present? && @mail['X-Autoreply'].value == 'yes'
end
# forcing the encoding of the content to UTF-8 so as to be compatible with database and serializers
def encode_to_unicode(str)
return '' if str.blank?