diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/email/handler/base_handler.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/email/handler/create_issue_handler.rb | 28 | ||||
-rw-r--r-- | lib/gitlab/email/handler/create_merge_request_handler.rb | 24 | ||||
-rw-r--r-- | lib/gitlab/email/handler/create_note_handler.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/email/handler/reply_processing.rb | 19 | ||||
-rw-r--r-- | lib/gitlab/email/handler/unsubscribe_handler.rb | 24 | ||||
-rw-r--r-- | lib/gitlab/incoming_email.rb | 6 |
7 files changed, 80 insertions, 27 deletions
diff --git a/lib/gitlab/email/handler/base_handler.rb b/lib/gitlab/email/handler/base_handler.rb index 35bb49ad19a..f89d1d15010 100644 --- a/lib/gitlab/email/handler/base_handler.rb +++ b/lib/gitlab/email/handler/base_handler.rb @@ -6,12 +6,14 @@ module Gitlab class BaseHandler attr_reader :mail, :mail_key + HANDLER_ACTION_BASE_REGEX ||= /(?<project_slug>.+)-(?<project_id>\d+)/.freeze + def initialize(mail, mail_key) @mail = mail @mail_key = mail_key end - def can_execute? + def can_handle? raise NotImplementedError end diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb index 69982efbbe6..78a3a9489ac 100644 --- a/lib/gitlab/email/handler/create_issue_handler.rb +++ b/lib/gitlab/email/handler/create_issue_handler.rb @@ -2,21 +2,33 @@ require 'gitlab/email/handler/base_handler' +# handles issue creation emails with these formats: +# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-issue@incoming.gitlab.com +# incoming+gitlab-org/gitlab-ce+Author_Token12345678@incoming.gitlab.com (legacy) module Gitlab module Email module Handler class CreateIssueHandler < BaseHandler include ReplyProcessing - attr_reader :project_path, :incoming_email_token + + HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-issue\z/.freeze + HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\+(?<incoming_email_token>.*)\z/.freeze def initialize(mail, mail_key) super(mail, mail_key) - @project_path, @incoming_email_token = - mail_key && mail_key.split('+', 2) + + if !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s)) + @project_slug = matched[:project_slug] + @project_id = matched[:project_id]&.to_i + @incoming_email_token = matched[:incoming_email_token] + elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s) + @project_path = matched[:project_path] + @incoming_email_token = matched[:incoming_email_token] + end end def can_handle? - !incoming_email_token.nil? && !incoming_email_token.include?("+") && !mail_key.include?(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX) + incoming_email_token && (project_id || can_handle_legacy_format?) end def execute @@ -36,10 +48,6 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord - def project - @project ||= Project.find_by_full_path(project_path) - end - private def create_issue @@ -50,6 +58,10 @@ module Gitlab description: message_including_reply ).execute end + + def can_handle_legacy_format? + project_path && !incoming_email_token.include?('+') && !mail_key.include?(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY) + end end end end diff --git a/lib/gitlab/email/handler/create_merge_request_handler.rb b/lib/gitlab/email/handler/create_merge_request_handler.rb index 5772727e855..b3b5063f2ca 100644 --- a/lib/gitlab/email/handler/create_merge_request_handler.rb +++ b/lib/gitlab/email/handler/create_merge_request_handler.rb @@ -3,23 +3,33 @@ require 'gitlab/email/handler/base_handler' require 'gitlab/email/handler/reply_processing' +# handles merge request creation emails with these formats: +# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-merge-request@incoming.gitlab.com +# incoming+gitlab-org/gitlab-ce+merge-request+Author_Token12345678@incoming.gitlab.com (legacy) module Gitlab module Email module Handler class CreateMergeRequestHandler < BaseHandler include ReplyProcessing - attr_reader :project_path, :incoming_email_token + + HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-merge-request\z/.freeze + HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\+merge-request\+(?<incoming_email_token>.*)/.freeze def initialize(mail, mail_key) super(mail, mail_key) - if m = /\A([^\+]*)\+merge-request\+(.*)/.match(mail_key.to_s) - @project_path, @incoming_email_token = m.captures + if !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s)) + @project_slug = matched[:project_slug] + @project_id = matched[:project_id]&.to_i + @incoming_email_token = matched[:incoming_email_token] + elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s) + @project_path = matched[:project_path] + @incoming_email_token = matched[:incoming_email_token] end end def can_handle? - @project_path && @incoming_email_token + incoming_email_token && (project_id || project_path) end def execute @@ -40,10 +50,6 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord - def project - @project ||= Project.find_by_full_path(project_path) - end - def metrics_params super.merge(includes_patches: patch_attachments.any?) end @@ -97,7 +103,7 @@ module Gitlab def remove_patch_attachments patch_attachments.each { |patch| mail.parts.delete(patch) } - # reset the message, so it needs to be reporocessed when the attachments + # reset the message, so it needs to be reprocessed when the attachments # have been modified @message = nil end diff --git a/lib/gitlab/email/handler/create_note_handler.rb b/lib/gitlab/email/handler/create_note_handler.rb index c7c573595fa..b00af15364d 100644 --- a/lib/gitlab/email/handler/create_note_handler.rb +++ b/lib/gitlab/email/handler/create_note_handler.rb @@ -3,6 +3,8 @@ require 'gitlab/email/handler/base_handler' require 'gitlab/email/handler/reply_processing' +# handles note/reply creation emails with these formats: +# incoming+1234567890abcdef1234567890abcdef@incoming.gitlab.com module Gitlab module Email module Handler diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb index ff6b2c729b2..ba9730d2685 100644 --- a/lib/gitlab/email/handler/reply_processing.rb +++ b/lib/gitlab/email/handler/reply_processing.rb @@ -6,13 +6,26 @@ module Gitlab module ReplyProcessing private + attr_reader :project_id, :project_slug, :project_path, :incoming_email_token + def author raise NotImplementedError end + # rubocop:disable Gitlab/ModuleWithInstanceVariables def project - raise NotImplementedError + return @project if instance_variable_defined?(:@project) + + if project_id + @project = Project.find_by_id(project_id) + @project = nil unless valid_project_slug?(@project) + else + @project = Project.find_by_full_path(project_path) + end + + @project end + # rubocop:enable Gitlab/ModuleWithInstanceVariables def message @message ||= process_message @@ -58,6 +71,10 @@ module Gitlab raise invalid_exception, msg end + + def valid_project_slug?(found_project) + project_slug == found_project.full_path_slug + end end end end diff --git a/lib/gitlab/email/handler/unsubscribe_handler.rb b/lib/gitlab/email/handler/unsubscribe_handler.rb index d2f617b868a..20e4c125626 100644 --- a/lib/gitlab/email/handler/unsubscribe_handler.rb +++ b/lib/gitlab/email/handler/unsubscribe_handler.rb @@ -2,14 +2,28 @@ require 'gitlab/email/handler/base_handler' +# handles unsubscribe emails with these formats: +# incoming+1234567890abcdef1234567890abcdef-unsubscribe@incoming.gitlab.com +# incoming+1234567890abcdef1234567890abcdef+unsubscribe@incoming.gitlab.com (legacy) module Gitlab module Email module Handler class UnsubscribeHandler < BaseHandler delegate :project, to: :sent_notification, allow_nil: true + HANDLER_REGEX_FOR = -> (suffix) { /\A(?<reply_token>\w+)#{Regexp.escape(suffix)}\z/ }.freeze + HANDLER_REGEX = HANDLER_REGEX_FOR.call(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX).freeze + HANDLER_REGEX_LEGACY = HANDLER_REGEX_FOR.call(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY).freeze + + def initialize(mail, mail_key) + super(mail, mail_key) + + matched = HANDLER_REGEX.match(mail_key.to_s) || HANDLER_REGEX_LEGACY.match(mail_key.to_s) + @reply_token = matched[:reply_token] if matched + end + def can_handle? - mail_key =~ /\A\w+#{Regexp.escape(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX)}\z/ + reply_token.present? end def execute @@ -24,12 +38,10 @@ module Gitlab private - def sent_notification - @sent_notification ||= SentNotification.for(reply_key) - end + attr_reader :reply_token - def reply_key - mail_key.sub(Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX, '') + def sent_notification + @sent_notification ||= SentNotification.for(reply_token) end end end diff --git a/lib/gitlab/incoming_email.rb b/lib/gitlab/incoming_email.rb index 20fc8226611..cc0c633b943 100644 --- a/lib/gitlab/incoming_email.rb +++ b/lib/gitlab/incoming_email.rb @@ -2,8 +2,9 @@ module Gitlab module IncomingEmail - UNSUBSCRIBE_SUFFIX = '+unsubscribe'.freeze - WILDCARD_PLACEHOLDER = '%{key}'.freeze + UNSUBSCRIBE_SUFFIX = '-unsubscribe'.freeze + UNSUBSCRIBE_SUFFIX_LEGACY = '+unsubscribe'.freeze + WILDCARD_PLACEHOLDER = '%{key}'.freeze class << self def enabled? @@ -22,6 +23,7 @@ module Gitlab config.address.sub(WILDCARD_PLACEHOLDER, key) end + # example: incoming+1234567890abcdef1234567890abcdef-unsubscribe@incoming.gitlab.com def unsubscribe_address(key) config.address.sub(WILDCARD_PLACEHOLDER, "#{key}#{UNSUBSCRIBE_SUFFIX}") end |