mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-29 18:22:53 +00:00
* fix: downcase email when finding * feat: add `from_email` class * refactor: use `from_email` * feat: add rule to disallow find_by email directly * chore: remove redundant test Since the previous imlpmentation didn't do a case-insentive search, a new user would be created, and the error would be raised at the DB layer. With the new changes, this test case is redundant * refactor: use from_email
101 lines
3.6 KiB
Ruby
101 lines
3.6 KiB
Ruby
class SupportMailbox < ApplicationMailbox
|
|
attr_accessor :channel, :account, :inbox, :conversation, :processed_mail
|
|
|
|
before_processing :find_channel,
|
|
:load_account,
|
|
:load_inbox,
|
|
:decorate_mail
|
|
|
|
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?('@')
|
|
|
|
ActiveRecord::Base.transaction do
|
|
find_or_create_contact
|
|
find_or_create_conversation
|
|
create_message
|
|
add_attachments_to_message
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def find_channel
|
|
find_channel_with_to_mail if @channel.blank?
|
|
|
|
raise 'Email channel/inbox not found' if @channel.nil?
|
|
|
|
@channel
|
|
end
|
|
|
|
def find_channel_with_to_mail
|
|
@channel = EmailChannelFinder.new(mail).perform
|
|
end
|
|
|
|
def load_account
|
|
@account = @channel.account
|
|
end
|
|
|
|
def load_inbox
|
|
@inbox = @channel.inbox
|
|
end
|
|
|
|
def decorate_mail
|
|
@processed_mail = MailPresenter.new(mail, @account)
|
|
end
|
|
|
|
def find_conversation_by_in_reply_to
|
|
return if in_reply_to.blank?
|
|
|
|
@account.conversations.where("additional_attributes->>'in_reply_to' = ?", in_reply_to).first
|
|
end
|
|
|
|
def in_reply_to
|
|
mail['In-Reply-To'].try(:value)
|
|
end
|
|
|
|
def original_sender_email
|
|
@processed_mail.original_sender&.downcase
|
|
end
|
|
|
|
def find_or_create_conversation
|
|
@conversation = find_conversation_by_in_reply_to || ::Conversation.create!({
|
|
account_id: @account.id,
|
|
inbox_id: @inbox.id,
|
|
contact_id: @contact.id,
|
|
contact_inbox_id: @contact_inbox.id,
|
|
additional_attributes: {
|
|
in_reply_to: in_reply_to,
|
|
source: 'email',
|
|
mail_subject: @processed_mail.subject,
|
|
initiated_at: {
|
|
timestamp: Time.now.utc
|
|
}
|
|
}
|
|
})
|
|
end
|
|
|
|
def find_or_create_contact
|
|
@contact = @inbox.contacts.from_email(original_sender_email)
|
|
if @contact.present?
|
|
@contact_inbox = ContactInbox.find_by(inbox: @inbox, contact: @contact)
|
|
else
|
|
create_contact
|
|
end
|
|
end
|
|
|
|
def identify_contact_name
|
|
processed_mail.sender_name || processed_mail.from.first.split('@').first
|
|
end
|
|
end
|