2020-12-31 11:56:13 +01:00
|
|
|
class EmailImporter
|
2021-01-04 22:03:24 +01:00
|
|
|
attr_accessor :email_class
|
|
|
|
attr_accessor :metadata_mapping_class
|
2021-01-04 22:05:42 +01:00
|
|
|
attr_accessor :html_to_text_class
|
2020-12-31 11:56:13 +01:00
|
|
|
|
2021-01-04 22:03:24 +01:00
|
|
|
def initialize(
|
|
|
|
email_class: Email,
|
|
|
|
metadata_mapping_class: MetadataMapping,
|
2021-01-04 22:05:42 +01:00
|
|
|
html_to_text_class: Rails.configuration.html_to_text_class)
|
2021-01-04 22:03:24 +01:00
|
|
|
|
|
|
|
@email_class = email_class
|
|
|
|
@metadata_mapping_class = metadata_mapping_class
|
2021-01-04 22:05:42 +01:00
|
|
|
@html_to_text_class = html_to_text_class
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def import(mail)
|
2021-01-04 22:03:24 +01:00
|
|
|
email = email_class.new(
|
2020-12-31 15:32:07 +01:00
|
|
|
message_id: mail.message_id,
|
|
|
|
subject: mail.subject,
|
|
|
|
date: mail.date,
|
|
|
|
to: mail.to,
|
2020-12-31 11:56:13 +01:00
|
|
|
delivered_to: delivered_to(mail),
|
2020-12-31 15:32:07 +01:00
|
|
|
from: mail.from,
|
|
|
|
plain_body: text_plain_body(mail),
|
|
|
|
headers: hashed_headers(mail),
|
|
|
|
cron: sent_by_cron?(mail),
|
2020-12-31 11:56:13 +01:00
|
|
|
mailing_list: mailing_list?(mail),
|
2020-12-31 15:32:07 +01:00
|
|
|
clients: clients(mail),
|
|
|
|
servers: servers(mail),
|
|
|
|
tickets: tickets(mail)
|
2020-12-31 11:56:13 +01:00
|
|
|
)
|
|
|
|
rescue => ex
|
|
|
|
binding.pry
|
|
|
|
end
|
|
|
|
|
|
|
|
def delivered_to(mail)
|
2021-01-04 22:05:42 +01:00
|
|
|
values_from_header(header: mail.header["Delivered-To"], default: Array(mail.to))
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def text_plain_body(mail)
|
|
|
|
if mail.parts.present?
|
|
|
|
if mail.text_part.present?
|
|
|
|
mail.text_part.decoded
|
|
|
|
elsif mail.html_part.present?
|
2021-01-04 22:05:42 +01:00
|
|
|
html_to_text_class.new.convert(mail.html_part.decoded)
|
2020-12-31 11:56:13 +01:00
|
|
|
else
|
|
|
|
mail.parts[0].decoded
|
|
|
|
end
|
2021-01-04 22:05:42 +01:00
|
|
|
elsif mail.content_type && mail.content_type.match?(/\btext\/html\b/)
|
|
|
|
html_to_text_class.new.convert(mail.decoded)
|
2020-12-31 11:56:13 +01:00
|
|
|
else
|
2021-01-01 22:33:47 +01:00
|
|
|
mail.decoded
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def hashed_headers(mail)
|
|
|
|
mail.header.map { |header|
|
|
|
|
{
|
|
|
|
name: header.name,
|
|
|
|
value: header.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def sent_by_cron?(mail)
|
|
|
|
(mail.subject.present? && mail.subject.match?(/cron/i)) \
|
2021-01-04 22:05:18 +01:00
|
|
|
|| mail.header["X-Cron-Env"].present?
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
2021-01-04 22:03:24 +01:00
|
|
|
|
2020-12-31 11:56:13 +01:00
|
|
|
def mailing_list?(mail)
|
|
|
|
mail.header["List-Unsubscribe"].present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def clients(mail)
|
2021-01-04 22:03:24 +01:00
|
|
|
metadata(mail).filter_map(&:entity).uniq
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def servers(mail)
|
2021-01-04 22:03:24 +01:00
|
|
|
metadata(mail).filter_map(&:server).uniq
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def tickets(mail)
|
2021-01-04 22:03:24 +01:00
|
|
|
values_from_header(header: mail.header["X-Ticket-Id"])
|
|
|
|
end
|
|
|
|
|
|
|
|
def values_from_header(header:, default: [])
|
2021-01-01 19:12:50 +01:00
|
|
|
if header.respond_to?(:map)
|
|
|
|
header.map(&:value)
|
|
|
|
elsif header.respond_to?(:value)
|
2021-01-04 22:03:24 +01:00
|
|
|
Array(header.value)
|
|
|
|
elsif block_given?
|
|
|
|
yield(header)
|
|
|
|
else
|
|
|
|
default
|
2021-01-01 19:12:50 +01:00
|
|
|
end
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
2021-01-04 22:03:24 +01:00
|
|
|
def metadata(mail)
|
|
|
|
@metadata ||= metadata_mapping_class.where(input: metadata_inputs(mail)).all
|
|
|
|
end
|
|
|
|
|
|
|
|
def metadata_inputs(mail)
|
|
|
|
inputs = []
|
|
|
|
# add mail addresses and hostnames from headers
|
|
|
|
inputs << ["To", "Delivered-To", "X-Original-To", "From", "Subject"].filter_map { |header_name|
|
|
|
|
mail.header[header_name]
|
|
|
|
}.flatten.map(&:value).filter_map() { |header_value|
|
|
|
|
keep_email_and_hostnames(header_value)
|
|
|
|
}.flatten.filter_map() { |value|
|
|
|
|
clean_subdomains(value)
|
|
|
|
}.flatten
|
|
|
|
# add other values from headers
|
|
|
|
inputs << mail.header["X-Client-Id"]
|
|
|
|
|
|
|
|
inputs.uniq
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
2021-01-04 22:03:24 +01:00
|
|
|
|
|
|
|
def keep_email_and_hostnames(string)
|
|
|
|
pattern = /\b((?:([-a-zA-Z0-9\._]+)@)?((?:[-a-zA-Z0-9\._]*)(?:\.[a-z]{2,})))\b/
|
|
|
|
results = string.scan(pattern)
|
|
|
|
if results.present?
|
|
|
|
results.map(&:first)
|
|
|
|
end
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
|
2021-01-04 22:03:24 +01:00
|
|
|
def clean_subdomains(value)
|
|
|
|
[
|
|
|
|
[/[-a-zA-Z0-9\._]+@([-a-zA-Z0-9]+).evolix.net/, '@\1']
|
|
|
|
].filter_map { |item|
|
|
|
|
if value.match?(item[0])
|
|
|
|
value.gsub!(item[0], item[1])
|
2020-12-31 11:56:13 +01:00
|
|
|
else
|
2021-01-04 22:03:24 +01:00
|
|
|
value
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
2021-01-04 22:03:24 +01:00
|
|
|
}
|
2020-12-31 11:56:13 +01:00
|
|
|
end
|
|
|
|
end
|