fcb7625616
* Bugfix: Fixed quoted text parsing in incoming email We had changed the support email from an account based only value to account based with fallback on global config and environment variable. Incoming email quoted text parsing was still based on account based support email. Changed this to utilize the newly introduced fallback values from global config and environment for parsing quoted text. * Bugfix: Added one more sender agnostic regex for quoted text parsing
114 lines
3.3 KiB
Ruby
114 lines
3.3 KiB
Ruby
class MailPresenter < SimpleDelegator
|
|
attr_accessor :mail
|
|
|
|
def initialize(mail, account = nil)
|
|
super(mail)
|
|
@mail = mail
|
|
@account = account
|
|
end
|
|
|
|
def subject
|
|
encode_to_unicode(@mail.subject)
|
|
end
|
|
|
|
def text_content
|
|
@decoded_text_content ||= encode_to_unicode(text_part&.body&.decoded || '')
|
|
@text_content ||= {
|
|
full: @decoded_text_content,
|
|
reply: extract_reply(@decoded_text_content)[:reply],
|
|
quoted: extract_reply(@decoded_text_content)[:quoted_text]
|
|
}
|
|
end
|
|
|
|
def html_content
|
|
@decoded_html_content ||= encode_to_unicode(html_part&.body&.decoded || '')
|
|
@html_content ||= {
|
|
full: @decoded_html_content,
|
|
reply: extract_reply(@decoded_html_content)[:reply],
|
|
quoted: extract_reply(@decoded_html_content)[:quoted_text]
|
|
}
|
|
end
|
|
|
|
def attachments
|
|
# ref : https://github.com/gorails-screencasts/action-mailbox-action-text/blob/master/app/mailboxes/posts_mailbox.rb
|
|
mail.attachments.map do |attachment|
|
|
blob = ActiveStorage::Blob.create_after_upload!(
|
|
io: StringIO.new(attachment.body.to_s),
|
|
filename: attachment.filename,
|
|
content_type: attachment.content_type
|
|
)
|
|
{ original: attachment, blob: blob }
|
|
end
|
|
end
|
|
|
|
def number_of_attachments
|
|
mail.attachments.count
|
|
end
|
|
|
|
def serialized_data
|
|
{
|
|
text_content: text_content,
|
|
html_content: html_content,
|
|
number_of_attachments: number_of_attachments,
|
|
subject: subject,
|
|
date: date,
|
|
to: to,
|
|
from: from,
|
|
in_reply_to: in_reply_to,
|
|
cc: cc,
|
|
bcc: bcc,
|
|
message_id: message_id
|
|
}
|
|
end
|
|
|
|
private
|
|
|
|
# forcing the encoding of the content to UTF-8 so as to be compatible with database and serializers
|
|
def encode_to_unicode(str)
|
|
current_encoding = str.encoding.name
|
|
str.encode(current_encoding, 'UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
|
end
|
|
|
|
def extract_reply(content)
|
|
@regex_arr ||= quoted_text_regexes
|
|
|
|
content_length = content.length
|
|
# calculates the matching regex closest to top of page
|
|
index = @regex_arr.inject(content_length) do |min, regex|
|
|
[(content.index(regex) || content_length), min].min
|
|
end
|
|
|
|
{
|
|
reply: content[0..(index - 1)].strip,
|
|
quoted_text: content[index..].strip
|
|
}
|
|
end
|
|
|
|
def quoted_text_regexes
|
|
return sender_agnostic_regexes if @account.nil? || account_support_email.blank?
|
|
|
|
[
|
|
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) + "\s+wrote:", Regexp::IGNORECASE),
|
|
Regexp.new('On(.*)' + Regexp.escape(account_support_email) + '(.*)wrote:', Regexp::IGNORECASE)
|
|
] + sender_agnostic_regexes
|
|
end
|
|
|
|
def sender_agnostic_regexes
|
|
@sender_agnostic_regexes ||= [
|
|
Regexp.new("^.*On.*(\n)?wrote:$", Regexp::IGNORECASE),
|
|
Regexp.new('^.*On(.*)(.*)wrote:$', Regexp::IGNORECASE),
|
|
Regexp.new("-+original\s+message-+\s*$", Regexp::IGNORECASE),
|
|
Regexp.new("from:\s*$", Regexp::IGNORECASE)
|
|
]
|
|
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
|