diff options
Diffstat (limited to 'lib/gitlab/email/receiver.rb')
-rw-r--r-- | lib/gitlab/email/receiver.rb | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index f5e47b43a9a..71db8ab6067 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -6,6 +6,8 @@ require_dependency 'gitlab/email/handler' module Gitlab module Email class Receiver + include Gitlab::Utils::StrongMemoize + def initialize(raw) @raw = raw end @@ -13,11 +15,7 @@ module Gitlab def execute raise EmptyEmailError if @raw.blank? - mail = build_mail - - ignore_auto_reply!(mail) - - handler = find_handler(mail) + ignore_auto_reply! raise UnknownIncomingEmail unless handler @@ -26,13 +24,33 @@ module Gitlab end end + def mail_metadata + { + mail_uid: mail.message_id, + from_address: mail.from, + to_address: mail.to, + mail_key: mail_key, + references: Array(mail.references), + delivered_to: delivered_to.map(&:value), + envelope_to: envelope_to.map(&:value), + x_envelope_to: x_envelope_to.map(&:value) + } + end + private - def find_handler(mail) - mail_key = extract_mail_key(mail) + def handler + strong_memoize(:handler) { find_handler } + end + + def find_handler Handler.for(mail, mail_key) end + def mail + strong_memoize(:mail) { build_mail } + end + def build_mail Mail::Message.new(@raw) rescue Encoding::UndefinedConversionError, @@ -40,22 +58,24 @@ module Gitlab raise EmailUnparsableError, e end - def extract_mail_key(mail) - key_from_to_header(mail) || key_from_additional_headers(mail) + def mail_key + strong_memoize(:mail_key) do + key_from_to_header || key_from_additional_headers + end end - def key_from_to_header(mail) + def key_from_to_header mail.to.find do |address| key = Gitlab::IncomingEmail.key_from_address(address) break key if key end end - def key_from_additional_headers(mail) - find_key_from_references(mail) || - find_key_from_delivered_to_header(mail) || - find_key_from_envelope_to_header(mail) || - find_key_from_x_envelope_to_header(mail) + def key_from_additional_headers + find_key_from_references || + find_key_from_delivered_to_header || + find_key_from_envelope_to_header || + find_key_from_x_envelope_to_header end def ensure_references_array(references) @@ -71,41 +91,53 @@ module Gitlab end end - def find_key_from_references(mail) + def find_key_from_references ensure_references_array(mail.references).find do |mail_id| key = Gitlab::IncomingEmail.key_from_fallback_message_id(mail_id) break key if key end end - def find_key_from_delivered_to_header(mail) - Array(mail[:delivered_to]).find do |header| + def delivered_to + Array(mail[:delivered_to]) + end + + def envelope_to + Array(mail[:envelope_to]) + end + + def x_envelope_to + Array(mail[:x_envelope_to]) + end + + def find_key_from_delivered_to_header + delivered_to.find do |header| key = Gitlab::IncomingEmail.key_from_address(header.value) break key if key end end - def find_key_from_envelope_to_header(mail) - Array(mail[:envelope_to]).find do |header| + def find_key_from_envelope_to_header + envelope_to.find do |header| key = Gitlab::IncomingEmail.key_from_address(header.value) break key if key end end - def find_key_from_x_envelope_to_header(mail) - Array(mail[:x_envelope_to]).find do |header| + def find_key_from_x_envelope_to_header + x_envelope_to.find do |header| key = Gitlab::IncomingEmail.key_from_address(header.value) break key if key end end - def ignore_auto_reply!(mail) - if auto_submitted?(mail) || auto_replied?(mail) + def ignore_auto_reply! + if auto_submitted? || auto_replied? raise AutoGeneratedEmailError end end - def auto_submitted?(mail) + def auto_submitted? # Mail::Header#[] is case-insensitive auto_submitted = mail.header['Auto-Submitted']&.value @@ -114,7 +146,7 @@ module Gitlab auto_submitted && auto_submitted != 'no' end - def auto_replied?(mail) + def auto_replied? autoreply = mail.header['X-Autoreply']&.value autoreply && autoreply == 'yes' |