debian-mirror-gitlab/lib/gitlab/email/handler/service_desk_handler.rb

166 lines
4.8 KiB
Ruby
Raw Normal View History

2020-07-28 23:09:34 +05:30
# frozen_string_literal: true
# handles service desk issue creation emails with these formats:
# incoming+gitlab-org-gitlab-ce-20-issue-@incoming.gitlab.com
# incoming+gitlab-org/gitlab-ce@incoming.gitlab.com (legacy)
module Gitlab
module Email
module Handler
class ServiceDeskHandler < BaseHandler
include ReplyProcessing
include Gitlab::Utils::StrongMemoize
HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-issue-\z/.freeze
HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\z/.freeze
PROJECT_KEY_PATTERN = /\A(?<slug>.+)-(?<key>[a-z0-9_]+)\z/.freeze
def initialize(mail, mail_key, service_desk_key: nil)
2021-12-11 22:18:48 +05:30
if service_desk_key
mail_key ||= service_desk_key
2020-07-28 23:09:34 +05:30
@service_desk_key = service_desk_key
end
2021-12-11 22:18:48 +05:30
super(mail, mail_key)
match_project_slug || match_legacy_project_slug
2020-07-28 23:09:34 +05:30
end
def can_handle?
Gitlab::ServiceDesk.supported? && (project_id || can_handle_legacy_format? || service_desk_key)
end
def execute
raise ProjectNotFound if project.nil?
create_issue!
2021-03-11 19:13:27 +05:30
if from_address
add_email_participant
2021-06-08 01:23:25 +05:30
send_thank_you_email
2021-03-11 19:13:27 +05:30
end
2020-07-28 23:09:34 +05:30
end
2021-12-11 22:18:48 +05:30
def match_project_slug
return if mail_key&.include?('/')
return unless matched = HANDLER_REGEX.match(mail_key.to_s)
@project_slug = matched[:project_slug]
@project_id = matched[:project_id]&.to_i
end
def match_legacy_project_slug
return unless matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
@project_path = matched[:project_path]
end
2020-07-28 23:09:34 +05:30
def metrics_event
:receive_email_service_desk
end
def project
strong_memoize(:project) do
2021-12-11 22:18:48 +05:30
project_record = super
project_record ||= project_from_key if service_desk_key
project_record&.service_desk_enabled? ? project_record : nil
2020-07-28 23:09:34 +05:30
end
end
2021-09-30 23:02:18 +05:30
private
attr_reader :project_id, :project_path, :service_desk_key
2020-07-28 23:09:34 +05:30
def project_from_key
return unless match = service_desk_key.match(PROJECT_KEY_PATTERN)
2021-09-04 01:27:46 +05:30
Project.with_service_desk_key(match[:key]).find do |project|
valid_project_key?(project, match[:slug])
end
2020-07-28 23:09:34 +05:30
end
def valid_project_key?(project, slug)
2021-03-08 18:12:59 +05:30
project.present? && slug == project.full_path_slug
2020-07-28 23:09:34 +05:30
end
def create_issue!
2021-11-11 11:23:49 +05:30
@issue = ::Issues::CreateService.new(
2021-06-08 01:23:25 +05:30
project: project,
current_user: User.support_bot,
params: {
title: mail.subject,
description: message_including_template,
confidential: true,
external_author: from_address
2021-09-30 23:02:18 +05:30
},
spam_params: nil
2020-07-28 23:09:34 +05:30
).execute
raise InvalidIssueError unless @issue.persisted?
if service_desk_setting&.issue_template_missing?
create_template_not_found_note(@issue)
end
end
2021-06-08 01:23:25 +05:30
def send_thank_you_email
Notify.service_desk_thank_you_email(@issue.id).deliver_later
2021-09-30 23:02:18 +05:30
Gitlab::Metrics::BackgroundTransaction.current&.add_event(:service_desk_thank_you_email)
2020-07-28 23:09:34 +05:30
end
def message_including_template
2021-12-11 22:18:48 +05:30
description = process_message(trim_reply: false, allow_only_quotes: true)
2020-07-28 23:09:34 +05:30
template_content = service_desk_setting&.issue_template_content
if template_content.present?
description += " \n" + template_content
end
description
end
def service_desk_setting
strong_memoize(:service_desk_setting) do
project.service_desk_setting
end
end
def create_template_not_found_note(issue)
issue_template_key = service_desk_setting&.issue_template_key
warning_note = <<-MD.strip_heredoc
WARNING: The template file #{issue_template_key}.md used for service desk issues is empty or could not be found.
Please check service desk settings and update the file to be used.
MD
note_params = {
noteable: issue,
note: warning_note
}
::Notes::CreateService.new(
project,
User.support_bot,
note_params
).execute
end
def from_address
(mail.reply_to || []).first || mail.from.first || mail.sender
end
def can_handle_legacy_format?
project_path && project_path.include?('/') && !mail_key.include?('+')
end
def author
User.support_bot
end
2021-03-11 19:13:27 +05:30
def add_email_participant
@issue.issue_email_participants.create(email: from_address)
end
2020-07-28 23:09:34 +05:30
end
end
end
end