Commit 5c45af91 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'issue_222856_be_mailers_workers' into 'master'

Move mailers/workers service desk code to core

See merge request gitlab-org/gitlab!36132
parents 798e3475 12b98dc5
......@@ -19,6 +19,7 @@ class Notify < ApplicationMailer
include Emails::Releases
include Emails::Groups
include Emails::Reviews
include Emails::ServiceDesk
helper TimeboxesHelper
helper MergeRequestsHelper
......
......@@ -165,6 +165,18 @@ class NotifyPreview < ActionMailer::Preview
Notify.unknown_sign_in_email(user, '127.0.0.1', Time.current).message
end
def service_desk_new_note_email
cleanup do
note = create_note(noteable_type: 'Issue', noteable_id: issue.id, note: 'Issue note content')
Notify.service_desk_new_note_email(issue.id, note.id).message
end
end
def service_desk_thank_you_email
Notify.service_desk_thank_you_email(issue.id).message
end
private
def project
......
%html{ lang: "en" }
%head
%meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
-# haml-lint:disable NoPlainNodes
%title
GitLab
-# haml-lint:enable NoPlainNodes
= stylesheet_link_tag 'notify'
= yield :head
%body
......
......@@ -3,4 +3,4 @@ New response for issue #<%= @issue.iid %>:
Author: <%= sanitize_name(@note.author_name) %>
<%= @note.note %>
<%# EE-specific start %><%= render 'layouts/mailer/additional_text' %><%# EE-specific end %>
<%# EE-specific start %><%= render_if_exists 'layouts/mailer/additional_text'%><%# EE-specific end %>
......@@ -3,4 +3,4 @@ Thank you for your support request! We are tracking your request as ticket #<%=
To unsubscribe from this issue, please paste the following link into your browser:
<%= @unsubscribe_url %>
<%# EE-specific start %><%= render 'layouts/mailer/additional_text' %><%# EE-specific end %>
\ No newline at end of file
<%# EE-specific start %><%= render_if_exists 'layouts/mailer/additional_text' %><%# EE-specific end %>
......@@ -1660,6 +1660,14 @@
:weight: 2
:idempotent:
:tags: []
- :name: service_desk_email_receiver
:feature_category: :issue_tracking
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent:
:tags: []
- :name: system_hook_push
:feature_category: :source_code_management
:has_external_dependencies:
......
......@@ -10,7 +10,6 @@ module EE
# See https://gitlab.com/gitlab-org/gitlab/issues/7846
prepended do
include ::Emails::AdminNotification
include ::Emails::ServiceDesk
include ::Emails::Epics
end
......
......@@ -39,18 +39,6 @@ module EE
def send_unsubscribed_notification
::Notify.send_unsubscribed_notification(user.id).message
end
def service_desk_new_note_email
cleanup do
note = create_note(noteable_type: 'Issue', noteable_id: issue.id, note: 'Issue note content')
::Notify.service_desk_new_note_email(issue.id, note.id).message
end
end
def service_desk_thank_you_email
::Notify.service_desk_thank_you_email(issue.id).message
end
end
private
......
......@@ -683,14 +683,6 @@
:weight: 1
:idempotent: true
:tags: []
- :name: service_desk_email_receiver
:feature_category: :issue_tracking
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent:
:tags: []
- :name: status_page_publish
:feature_category: :incident_management
:has_external_dependencies: true
......
# frozen_string_literal: true
module EE
module Gitlab
module Email
module Handler
extend ActiveSupport::Concern
class_methods do
extend ::Gitlab::Utils::Override
override :load_handlers
def load_handlers
[
*super,
::Gitlab::Email::Handler::EE::ServiceDeskHandler
]
end
end
end
end
end
end
......@@ -9,22 +9,6 @@ module EE
private
# Support bot is specifically forbidden
# from using slash commands.
def strip_quick_actions(content)
return content unless author.support_bot?
command_definitions = ::QuickActions::InterpretService.command_definitions
extractor = ::Gitlab::QuickActions::Extractor.new(command_definitions)
extractor.redact_commands(content)
end
override :process_message
def process_message(**kwargs)
strip_quick_actions(super(kwargs))
end
override :upload_params
def upload_params
return super unless try(:noteable)&.is_a?(Epic)
......
# 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
module EE
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)
super(mail, mail_key)
if service_desk_key.present?
@service_desk_key = service_desk_key
elsif !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
@project_slug = matched[:project_slug]
@project_id = matched[:project_id]&.to_i
elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
@project_path = matched[:project_path]
end
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!
send_thank_you_email! if from_address
end
def metrics_params
super.merge(project: project&.full_path)
end
def metrics_event
:receive_email_service_desk
end
private
attr_reader :project_id, :project_path, :service_desk_key
def project
strong_memoize(:project) do
@project = service_desk_key ? project_from_key : super
@project = nil unless @project&.service_desk_enabled?
@project
end
end
def project_from_key
return unless match = service_desk_key.match(PROJECT_KEY_PATTERN)
project = Project.find_by_service_desk_project_key(match[:key])
return unless valid_project_key?(project, match[:slug])
project
end
def valid_project_key?(project, slug)
project.present? && slug == project.full_path_slug && Feature.enabled?(:service_desk_custom_address, project)
end
def create_issue!
@issue = Issues::CreateService.new(
project,
User.support_bot,
title: issue_title,
description: message_including_template,
confidential: true,
service_desk_reply_to: from_address
).execute
raise InvalidIssueError unless @issue.persisted?
if service_desk_setting&.issue_template_missing?
create_template_not_found_note(@issue)
end
end
def send_thank_you_email!
Notify.service_desk_thank_you_email(@issue.id).deliver_later!
end
def message_including_template
description = message_including_reply
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 issue_title
from = "(from #{from_address})" if from_address
"Service Desk #{from}: #{mail.subject}"
end
def can_handle_legacy_format?
project_path && project_path.include?('/') && !mail_key.include?('+')
end
def author
User.support_bot
end
end
end
end
end
end
......@@ -128,69 +128,4 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
end
context 'when the service desk' do
let(:project) { create(:project, :public, service_desk_enabled: true) }
let(:support_bot) { User.support_bot }
let(:noteable) { create(:issue, project: project, author: support_bot, title: 'service desk issue') }
let(:note) { create(:note, project: project, noteable: noteable) }
let(:email_raw) { fixture_file('emails/valid_reply_with_quick_actions.eml', dir: 'ee') }
let!(:sent_notification) do
SentNotification.record_note(note, support_bot.id, mail_key)
end
context 'is enabled' do
before do
allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(true)
project.project_feature.update!(issues_access_level: issues_access_level)
end
context 'when issues are enabled for everyone' do
let(:issues_access_level) { ProjectFeature::ENABLED }
it 'creates a comment' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
end
context 'when quick actions are present' do
it 'encloses quick actions with code span markdown' do
receiver.execute
noteable.reload
note = Note.last
expect(note.note).to include("Jake out\n\n`/close`\n`/title test`")
expect(noteable.title).to eq('service desk issue')
expect(noteable).to be_opened
end
end
end
context 'when issues are protected members only' do
let(:issues_access_level) { ProjectFeature::PRIVATE }
it 'creates a comment' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
end
end
context 'when issues are disabled' do
let(:issues_access_level) { ProjectFeature::DISABLED }
it 'does not create a comment' do
expect { receiver.execute }.to raise_error(::Gitlab::Email::UserNotAuthorizedError)
end
end
end
context 'is disabled' do
before do
allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
end
it 'does not create a comment' do
expect { receiver.execute }.to raise_error(::Gitlab::Email::ProjectNotFound)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Email::Handler do
before do
stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
stub_config_setting(host: 'localhost')
end
describe '.for' do
def handler_for(fixture, mail_key)
described_class.for(fixture_file(fixture), mail_key)
end
def ee_handler_for(fixture, mail_key)
described_class.for(fixture_file(fixture, dir: 'ee'), mail_key)
end
context 'a Service Desk email' do
it 'uses the Service Desk handler' do
expect(ee_handler_for('emails/service_desk.eml', 'some/project')).to be_instance_of(Gitlab::Email::Handler::EE::ServiceDeskHandler)
end
end
context 'a new issue email' do
let!(:user) { create(:user, email: 'jake@adventuretime.ooo', incoming_email_token: 'auth_token') }
it 'uses the create issue handler when Service Desk is enabled' do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:service_desk).and_return(true)
expect(handler_for('emails/valid_new_issue.eml', 'some/project+auth_token')).to be_instance_of(Gitlab::Email::Handler::CreateIssueHandler)
end
it 'uses the create issue handler when Service Desk is disabled' do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:service_desk).and_return(false)
expect(handler_for('emails/valid_new_issue.eml', 'some/project+auth_token')).to be_instance_of(Gitlab::Email::Handler::CreateIssueHandler)
end
end
end
end
......@@ -72,78 +72,6 @@ RSpec.describe Notify do
end
context 'for a project' do
context 'for service desk issues' do
before do
issue.update!(service_desk_reply_to: 'service.desk@example.com')
end
def expect_sender(username)
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(username)
expect(sender.address).to eq(gitlab_sender)
end
describe 'thank you email' do
subject { described_class.service_desk_thank_you_email(issue.id) }
it_behaves_like 'an unsubscribeable thread'
it 'has the correct recipient' do
is_expected.to deliver_to('service.desk@example.com')
end
it 'has the correct subject and body' do
aggregate_failures do
is_expected.to have_referable_subject(issue, include_project: false, reply: true)
is_expected.to have_body_text("Thank you for your support request! We are tracking your request as ticket #{issue.to_reference}, and will respond as soon as we can.")
end
end
it 'uses service bot name by default' do
expect_sender(User.support_bot.name)
end
context 'when custom outgoing name is set' do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: 'some custom name') }
it 'uses custom name in "from" header' do
expect_sender('some custom name')
end
end
context 'when custom outgoing name is empty' do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: '') }
it 'uses service bot name' do
expect_sender(User.support_bot.name)
end
end
end
describe 'new note email' do
let_it_be(:first_note) { create(:discussion_note_on_issue, note: 'Hello world') }
subject { described_class.service_desk_new_note_email(issue.id, first_note.id) }
it_behaves_like 'an unsubscribeable thread'
it 'has the correct recipient' do
is_expected.to deliver_to('service.desk@example.com')
end
it 'uses author\'s name in "from" header' do
expect_sender(first_note.author.name)
end
it 'has the correct subject and body' do
aggregate_failures do
is_expected.to have_referable_subject(issue, include_project: false, reply: true)
is_expected.to have_body_text(first_note.note)
end
end
end
end
context 'for merge requests' do
describe "that are new with approver" do
before do
......
......@@ -185,15 +185,6 @@ RSpec.describe API::Projects do
end
end
describe 'service desk attributes' do
it 'are exposed when the feature is available' do
get api("/projects/#{project.id}", user)
expect(json_response).to have_key 'service_desk_enabled'
expect(json_response).to have_key 'service_desk_address'
end
end
context 'project soft-deletion' do
subject { get api("/projects/#{project.id}", user) }
......
......@@ -12,7 +12,8 @@ module Gitlab
CreateNoteHandler,
CreateIssueHandler,
UnsubscribeHandler,
CreateMergeRequestHandler
CreateMergeRequestHandler,
ServiceDeskHandler
]
end
......@@ -25,5 +26,3 @@ module Gitlab
end
end
end
Gitlab::Email::Handler.prepend_if_ee('::EE::Gitlab::Email::Handler')
......@@ -37,7 +37,11 @@ module Gitlab
def process_message(**kwargs)
message = ReplyParser.new(mail, **kwargs).execute.strip
add_attachments(message)
message_with_attachments = add_attachments(message)
# Support bot is specifically forbidden
# from using slash commands.
strip_quick_actions(message_with_attachments)
end
def add_attachments(reply)
......@@ -82,6 +86,15 @@ module Gitlab
def valid_project_slug?(found_project)
project_slug == found_project.full_path_slug
end
def strip_quick_actions(content)
return content unless author.support_bot?
command_definitions = ::QuickActions::InterpretService.command_definitions
extractor = ::Gitlab::QuickActions::Extractor.new(command_definitions)
extractor.redact_commands(content)
end
end
end
end
......
# 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)
super(mail, mail_key)
if service_desk_key.present?
@service_desk_key = service_desk_key
elsif !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
@project_slug = matched[:project_slug]
@project_id = matched[:project_id]&.to_i
elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
@project_path = matched[:project_path]
end
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!
send_thank_you_email! if from_address
end
def metrics_params
super.merge(project: project&.full_path)
end
def metrics_event
:receive_email_service_desk
end
private
attr_reader :project_id, :project_path, :service_desk_key
def project
strong_memoize(:project) do
@project = service_desk_key ? project_from_key : super
@project = nil unless @project&.service_desk_enabled?
@project
end
end
def project_from_key
return unless match = service_desk_key.match(PROJECT_KEY_PATTERN)
project = Project.find_by_service_desk_project_key(match[:key])
return unless valid_project_key?(project, match[:slug])
project
end
def valid_project_key?(project, slug)
project.present? && slug == project.full_path_slug && Feature.enabled?(:service_desk_custom_address, project)
end
def create_issue!
@issue = Issues::CreateService.new(
project,
User.support_bot,
title: issue_title,
description: message_including_template,
confidential: true,
service_desk_reply_to: from_address
).execute
raise InvalidIssueError unless @issue.persisted?
if service_desk_setting&.issue_template_missing?
create_template_not_found_note(@issue)
end
end
def send_thank_you_email!
Notify.service_desk_thank_you_email(@issue.id).deliver_later!
end
def message_including_template
description = message_including_reply
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 issue_title
from = "(from #{from_address})" if from_address
"Service Desk #{from}: #{mail.subject}"
end
def can_handle_legacy_format?
project_path && project_path.include?('/') && !mail_key.include?('+')
end
def author
User.support_bot
end
end
end
end
end
......@@ -9,7 +9,7 @@ module Gitlab
key = service_desk_key(mail)
return unless key
::Gitlab::Email::Handler::EE::ServiceDeskHandler.new(mail, nil, service_desk_key: key)
Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: key)
end
def service_desk_key(mail)
......
......@@ -242,4 +242,70 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
it_behaves_like 'a reply to existing comment'
end
context 'when the service desk' do
let(:project) { create(:project, :public, service_desk_enabled: true) }
let(:support_bot) { User.support_bot }
let(:noteable) { create(:issue, project: project, author: support_bot, title: 'service desk issue') }
let(:note) { create(:note, project: project, noteable: noteable) }
let(:email_raw) { fixture_file('emails/valid_reply_with_quick_actions.eml') }
let!(:sent_notification) do
SentNotification.record_note(note, support_bot.id, mail_key)
end
context 'is enabled' do
before do
allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
project.project_feature.update!(issues_access_level: issues_access_level)
end
context 'when issues are enabled for everyone' do
let(:issues_access_level) { ProjectFeature::ENABLED }
it 'creates a comment' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
end
context 'when quick actions are present' do
it 'encloses quick actions with code span markdown' do
receiver.execute
noteable.reload
note = Note.last
expect(note.note).to include("Jake out\n\n`/close`\n`/title test`")
expect(noteable.title).to eq('service desk issue')
expect(noteable).to be_opened
end
end
end
context 'when issues are protected members only' do
let(:issues_access_level) { ProjectFeature::PRIVATE }
it 'creates a comment' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
end
end
context 'when issues are disabled' do
let(:issues_access_level) { ProjectFeature::DISABLED }
it 'does not create a comment' do
expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError)
end
end
end
context 'is disabled' do
before do
allow(Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(false)
end
it 'does not create a comment' do
expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
end
end
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
include_context :email_shared_context
before do
......@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
stub_config_setting(host: 'localhost')
end
let(:email_raw) { email_fixture('emails/service_desk.eml', dir: 'ee') }
let(:email_raw) { email_fixture('emails/service_desk.eml') }
let_it_be(:namespace) { create(:namespace, name: "email") }
let(:expected_description) do
"Service desk stuff!\n\n```\na = b\n```\n\n`/label ~label1`\n`/assign @user1`\n`/close`\n![image](uploads/image.png)"
......@@ -49,7 +49,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
it_behaves_like 'a new issue request'
context 'with legacy incoming email address' do
let(:email_raw) { fixture_file('emails/service_desk_legacy.eml', dir: 'ee') }
let(:email_raw) { fixture_file('emails/service_desk_legacy.eml') }
it_behaves_like 'a new issue request'
end
......@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
context 'and template cannot be found' do
before do
service = ServiceDeskSetting.new(project_id: project.id, issue_template_key: 'unknown')
service.save(validate: false)
service.save!(validate: false)
end
it 'does not append template text to issue description' do
......@@ -233,7 +233,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
end
context 'when there is a sender address and a from address' do
let(:email_raw) { email_fixture('emails/service_desk_sender_and_from.eml', dir: 'ee') }
let(:email_raw) { email_fixture('emails/service_desk_sender_and_from.eml') }
it 'prefers the from address' do
setup_attachment
......@@ -261,13 +261,13 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
end
context 'when the email is forwarded through an alias' do
let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml', dir: 'ee') }
let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml') }
it_behaves_like 'a new issue request'
end
context 'when the email is forwarded' do
let(:email_raw) { email_fixture('emails/service_desk_forwarded_new_issue.eml', dir: 'ee') }
let(:email_raw) { email_fixture('emails/service_desk_forwarded_new_issue.eml') }
it_behaves_like 'a new issue request' do
let(:expected_description) do
......@@ -300,12 +300,12 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
end
end
def email_fixture(path, dir:)
fixture_file(path, dir: dir).gsub('project_id', project.project_id.to_s)
def email_fixture(path)
fixture_file(path).gsub('project_id', project.project_id.to_s)
end
def service_desk_fixture(path, slug: nil, key: 'mykey')
slug ||= project.full_path_slug.to_s
fixture_file(path, dir: 'ee').gsub('project_slug', slug).gsub('project_key', key)
fixture_file(path).gsub('project_slug', slug).gsub('project_key', key)
end
end
......@@ -33,12 +33,40 @@ RSpec.describe Gitlab::Email::Handler do
it 'returns nil if provided email is nil' do
expect(described_class.for(nil, '')).to be_nil
end
context 'new issue email' do
def handler_for(fixture, mail_key)
described_class.for(fixture_file(fixture), mail_key)
end
before do
stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
stub_config_setting(host: 'localhost')
end
let!(:user) { create(:user, email: 'jake@adventuretime.ooo', incoming_email_token: 'auth_token') }
context 'a Service Desk email' do
it 'uses the Service Desk handler' do
expect(handler_for('emails/service_desk.eml', 'some/project')).to be_instance_of(Gitlab::Email::Handler::ServiceDeskHandler)
end
end
it 'return new issue handler' do
expect(handler_for('emails/valid_new_issue.eml', 'some/project+auth_token')).to be_instance_of(Gitlab::Email::Handler::CreateIssueHandler)
end
end
end
describe 'regexps are set properly' do
let(:addresses) do
%W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key path-to-project-123-user_email_token-merge-request path-to-project-123-user_email_token-issue) +
%W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY} sent_notification_key path/to/project+merge-request+user_email_token path/to/project+user_email_token)
%W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX} sent_notification_key path-to-project-123-user_email_token-merge-request) +
%W(sent_notification_key#{Gitlab::IncomingEmail::UNSUBSCRIBE_SUFFIX_LEGACY} sent_notification_key path-to-project-123-user_email_token-issue) +
%w(path/to/project+user_email_token path/to/project+merge-request+user_email_token some/project)
end
before do
allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
end
it 'picks each handler at least once' do
......@@ -46,12 +74,12 @@ RSpec.describe Gitlab::Email::Handler do
described_class.for(email, address).class
end
expect(matched_handlers.uniq).to match_array(ce_handlers)
expect(matched_handlers.uniq).to match_array(Gitlab::Email::Handler.handlers)
end
it 'can pick exactly one handler for each address' do
addresses.each do |address|
matched_handlers = ce_handlers.select do |handler|
matched_handlers = Gitlab::Email::Handler.handlers.select do |handler|
handler.new(email, address).can_handle?
end
......@@ -59,10 +87,4 @@ RSpec.describe Gitlab::Email::Handler do
end
end
end
def ce_handlers
@ce_handlers ||= Gitlab::Email::Handler.handlers.reject do |handler|
handler.name.start_with?('Gitlab::Email::Handler::EE::')
end
end
end
......@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Email::ServiceDeskReceiver do
let(:email) { fixture_file('emails/service_desk_custom_address.eml', dir: 'ee') }
let(:email) { fixture_file('emails/service_desk_custom_address.eml') }
let(:receiver) { described_class.new(email) }
context 'when the email contains a valid email address' do
......@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Email::ServiceDeskReceiver do
{ service_desk_key: 'project_slug-project_key' }
]
expect(::Gitlab::Email::Handler::EE::ServiceDeskHandler)
expect(Gitlab::Email::Handler::ServiceDeskHandler)
.to receive(:new).with(*expected_params).and_return(handler)
receiver.execute
......
......@@ -26,8 +26,6 @@ RSpec.describe Emails::ServiceDesk do
helper GitlabRoutingHelper
helper EmailsHelper
append_view_path Rails.root.join('ee', 'app', 'views', 'notify')
# this method is implemented in Notify class, we don't need to test it
def reply_key
'test-key'
......
......@@ -1253,6 +1253,78 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
end
end
context 'for service desk issues' do
before do
issue.update!(service_desk_reply_to: 'service.desk@example.com')
end
def expect_sender(username)
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(username)
expect(sender.address).to eq(gitlab_sender)
end
describe 'thank you email' do
subject { described_class.service_desk_thank_you_email(issue.id) }
it_behaves_like 'an unsubscribeable thread'
it 'has the correct recipient' do
is_expected.to deliver_to('service.desk@example.com')
end
it 'has the correct subject and body' do
aggregate_failures do
is_expected.to have_referable_subject(issue, include_project: false, reply: true)
is_expected.to have_body_text("Thank you for your support request! We are tracking your request as ticket #{issue.to_reference}, and will respond as soon as we can.")
end
end
it 'uses service bot name by default' do
expect_sender(User.support_bot.name)
end
context 'when custom outgoing name is set' do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: 'some custom name') }
it 'uses custom name in "from" header' do
expect_sender('some custom name')
end
end
context 'when custom outgoing name is empty' do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: '') }
it 'uses service bot name' do
expect_sender(User.support_bot.name)
end
end
end
describe 'new note email' do
let_it_be(:first_note) { create(:discussion_note_on_issue, note: 'Hello world') }
subject { described_class.service_desk_new_note_email(issue.id, first_note.id) }
it_behaves_like 'an unsubscribeable thread'
it 'has the correct recipient' do
is_expected.to deliver_to('service.desk@example.com')
end
it 'uses author\'s name in "from" header' do
expect_sender(first_note.author.name)
end
it 'has the correct subject and body' do
aggregate_failures do
is_expected.to have_referable_subject(issue, include_project: false, reply: true)
is_expected.to have_body_text(first_note.note)
end
end
end
end
end
context 'for a group' do
......
......@@ -1928,6 +1928,13 @@ RSpec.describe API::Projects do
end
end
end
it 'exposes service desk attributes' do
get api("/projects/#{project.id}", user)
expect(json_response).to have_key 'service_desk_enabled'
expect(json_response).to have_key 'service_desk_address'
end
end
describe 'GET /projects/:id/users' do
......
......@@ -5,7 +5,7 @@ require "spec_helper"
RSpec.describe ServiceDeskEmailReceiverWorker, :mailer do
describe '#perform' do
let(:worker) { described_class.new }
let(:email) { fixture_file('emails/service_desk_custom_address.eml', dir: 'ee') }
let(:email) { fixture_file('emails/service_desk_custom_address.eml') }
context 'when service_desk_email config is enabled' do
before do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment