diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 18:44:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 18:44:42 +0300 |
commit | 4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch) | |
tree | 5423a1c7516cffe36384133ade12572cf709398d /lib/gitlab/email | |
parent | e570267f2f6b326480d284e0164a6464ba4081bc (diff) |
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'lib/gitlab/email')
-rw-r--r-- | lib/gitlab/email/handler/create_issue_handler.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/email/handler/create_merge_request_handler.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/email/handler/reply_processing.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/email/handler/service_desk_handler.rb | 20 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing.rb | 19 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/base.rb | 154 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/create.rb | 101 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/helper.rb | 44 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/team.rb | 80 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/trial.rb | 75 | ||||
-rw-r--r-- | lib/gitlab/email/message/in_product_marketing/verify.rb | 93 | ||||
-rw-r--r-- | lib/gitlab/email/receiver.rb | 84 | ||||
-rw-r--r-- | lib/gitlab/email/reply_parser.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/email/service_desk_receiver.rb | 15 |
14 files changed, 655 insertions, 48 deletions
diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb index 22fc8addcd9..e927a5641e5 100644 --- a/lib/gitlab/email/handler/create_issue_handler.rb +++ b/lib/gitlab/email/handler/create_issue_handler.rb @@ -56,10 +56,12 @@ module Gitlab def create_issue Issues::CreateService.new( - project, - author, - title: mail.subject, - description: message_including_reply + project: project, + current_user: author, + params: { + title: mail.subject, + description: message_including_reply + } ).execute end diff --git a/lib/gitlab/email/handler/create_merge_request_handler.rb b/lib/gitlab/email/handler/create_merge_request_handler.rb index e8071bcafd0..df12aea1988 100644 --- a/lib/gitlab/email/handler/create_merge_request_handler.rb +++ b/lib/gitlab/email/handler/create_merge_request_handler.rb @@ -61,7 +61,7 @@ module Gitlab private def build_merge_request - MergeRequests::BuildService.new(project, author, merge_request_params).execute + MergeRequests::BuildService.new(project: project, current_user: author, params: merge_request_params).execute end def create_merge_request @@ -78,7 +78,7 @@ module Gitlab if merge_request.errors.any? merge_request else - MergeRequests::CreateService.new(project, author).create(merge_request) + MergeRequests::CreateService.new(project: project, current_user: author).create(merge_request) end end diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb index 9e476dd4e2b..63334169c8e 100644 --- a/lib/gitlab/email/handler/reply_processing.rb +++ b/lib/gitlab/email/handler/reply_processing.rb @@ -100,4 +100,4 @@ module Gitlab end end -Gitlab::Email::Handler::ReplyProcessing.prepend_if_ee('::EE::Gitlab::Email::Handler::ReplyProcessing') +Gitlab::Email::Handler::ReplyProcessing.prepend_mod_with('Gitlab::Email::Handler::ReplyProcessing') diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb index 80e8b726099..cab3538a447 100644 --- a/lib/gitlab/email/handler/service_desk_handler.rb +++ b/lib/gitlab/email/handler/service_desk_handler.rb @@ -38,7 +38,7 @@ module Gitlab if from_address add_email_participant - send_thank_you_email! + send_thank_you_email end end @@ -77,12 +77,14 @@ module Gitlab def create_issue! @issue = Issues::CreateService.new( - project, - User.support_bot, - title: mail.subject, - description: message_including_template, - confidential: true, - external_author: from_address + project: project, + current_user: User.support_bot, + params: { + title: mail.subject, + description: message_including_template, + confidential: true, + external_author: from_address + } ).execute raise InvalidIssueError unless @issue.persisted? @@ -92,8 +94,8 @@ module Gitlab end end - def send_thank_you_email! - Notify.service_desk_thank_you_email(@issue.id).deliver_later! + def send_thank_you_email + Notify.service_desk_thank_you_email(@issue.id).deliver_later end def message_including_template diff --git a/lib/gitlab/email/message/in_product_marketing.rb b/lib/gitlab/email/message/in_product_marketing.rb new file mode 100644 index 00000000000..d538238f26f --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + UnknownTrackError = Class.new(StandardError) + + TRACKS = [:create, :verify, :team, :trial].freeze + + def self.for(track) + raise UnknownTrackError unless TRACKS.include?(track) + + "Gitlab::Email::Message::InProductMarketing::#{track.to_s.classify}".constantize + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/base.rb b/lib/gitlab/email/message/in_product_marketing/base.rb new file mode 100644 index 00000000000..6341a7c7596 --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/base.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + class Base + include Gitlab::Email::Message::InProductMarketing::Helper + include Gitlab::Routing + + attr_accessor :format + + def initialize(group:, series:, format: :html) + raise ArgumentError, "Only #{total_series} series available for this track." unless series.between?(0, total_series - 1) + + @group = group + @series = series + @format = format + end + + def subject_line + raise NotImplementedError + end + + def tagline + raise NotImplementedError + end + + def title + raise NotImplementedError + end + + def subtitle + raise NotImplementedError + end + + def body_line1 + raise NotImplementedError + end + + def body_line2 + raise NotImplementedError + end + + def cta_text + raise NotImplementedError + end + + def cta_link + case format + when :html + link_to cta_text, group_email_campaigns_url(group, track: track, series: series), target: '_blank', rel: 'noopener noreferrer' + else + [cta_text, group_email_campaigns_url(group, track: track, series: series)].join(' >> ') + end + end + + def unsubscribe + parts = Gitlab.com? ? unsubscribe_com : unsubscribe_self_managed(track, series) + + case format + when :html + parts.join(' ') + else + parts.join("\n" + ' ' * 16) + end + end + + def progress + if Gitlab.com? + s_('InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series.') % { current_series: series + 1, total_series: total_series, track: track.to_s.humanize } + else + s_('InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}.') % { current_series: series + 1, total_series: total_series, track: track.to_s.humanize, unsubscribe_link: unsubscribe_link } + end + end + + def address + s_('InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA').html_safe % strong_options + end + + def footer_links + links = [ + [s_('InProductMarketing|Blog'), 'https://about.gitlab.com/blog'], + [s_('InProductMarketing|Twitter'), 'https://twitter.com/gitlab'], + [s_('InProductMarketing|Facebook'), 'https://www.facebook.com/gitlab'], + [s_('InProductMarketing|YouTube'), 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg'] + ] + case format + when :html + links.map do |text, link| + link_to(text, link) + end + else + '| ' + links.map do |text, link| + [text, link].join(' ') + end.join("\n| ") + end + end + + def logo_path + ["mailers/in_product_marketing", "#{track}-#{series}.png"].join('/') + end + + protected + + attr_reader :group, :series + + def total_series + 3 + end + + private + + def track + self.class.name.demodulize.downcase.to_sym + end + + def unsubscribe_com + [ + s_('InProductMarketing|If you no longer wish to receive marketing emails from us,'), + s_('InProductMarketing|you may %{unsubscribe_link} at any time.') % { unsubscribe_link: unsubscribe_link } + ] + end + + def unsubscribe_self_managed(track, series) + [ + s_('InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}.') % { unsubscribe_link: unsubscribe_link }, + s_("InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}.") % { marketing_preference_link: marketing_preference_link(track, series) } + ] + end + + def unsubscribe_link + unsubscribe_url = Gitlab.com? ? '%tag_unsubscribe_url%' : profile_notifications_url + + link(s_('InProductMarketing|unsubscribe'), unsubscribe_url) + end + + def marketing_preference_link(track, series) + params = { + utm_source: 'SM', + utm_medium: 'email', + utm_campaign: 'onboarding', + utm_term: "#{track}_#{series}" + } + + preference_link = "https://about.gitlab.com/company/preference-center/?#{params.to_query}" + + link(s_('InProductMarketing|update your preferences'), preference_link) + end + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/create.rb b/lib/gitlab/email/message/in_product_marketing/create.rb new file mode 100644 index 00000000000..5d3cac0a121 --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/create.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + class Create < Base + def subject_line + [ + s_('InProductMarketing|Create a project in GitLab in 5 minutes'), + s_('InProductMarketing|Import your project and code from GitHub, Bitbucket and others'), + s_('InProductMarketing|Understand repository mirroring') + ][series] + end + + def tagline + [ + s_('InProductMarketing|Get started today'), + s_('InProductMarketing|Get our import guides'), + s_('InProductMarketing|Need an alternative to importing?') + ][series] + end + + def title + [ + s_('InProductMarketing|Take your first steps with GitLab'), + s_('InProductMarketing|Start by importing your projects'), + s_('InProductMarketing|How (and why) mirroring makes sense') + ][series] + end + + def subtitle + [ + s_('InProductMarketing|Dig in and create a project and a repo'), + s_("InProductMarketing|Here's what you need to know"), + s_('InProductMarketing|Try it out') + ][series] + end + + def body_line1 + [ + s_("InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}.") % { project_link: project_link, repo_link: repo_link }, + s_("InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}.") % { github_link: github_link, bitbucket_link: bitbucket_link }, + s_("InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool.") % { mirroring_link: mirroring_link } + ][series] + end + + def body_line2 + [ + s_("InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started.") % { basics_link: basics_link }, + s_("InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}.") % { import_link: import_link }, + s_("InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD.") % { external_repo_link: external_repo_link } + ][series] + end + + def cta_text + [ + s_('InProductMarketing|Create your first project!'), + s_('InProductMarketing|Master the art of importing!'), + s_('InProductMarketing|Understand your project options') + ][series] + end + + private + + def project_link + link(s_('InProductMarketing|create a project'), help_page_url('gitlab-basics/create-project')) + end + + def repo_link + link(s_('InProductMarketing|set up a repo'), help_page_url('user/project/repository/index', anchor: 'create-a-repository')) + end + + def github_link + link(s_('InProductMarketing|GitHub Enterprise projects to GitLab'), help_page_url('integration/github')) + end + + def bitbucket_link + link(s_('InProductMarketing|from Bitbucket'), help_page_url('user/project/import/bitbucket_server')) + end + + def mirroring_link + link(s_('InProductMarketing|repository mirroring'), help_page_url('user/project/repository/repository_mirroring')) + end + + def basics_link + link(s_('InProductMarketing|Git basics'), help_page_url('gitlab-basics/README')) + end + + def import_link + link(s_('InProductMarketing|comprehensive guide'), help_page_url('user/project/import/index')) + end + + def external_repo_link + link(s_('InProductMarketing|connect an external repository'), new_project_url(anchor: 'cicd_for_external_repo')) + end + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/helper.rb b/lib/gitlab/email/message/in_product_marketing/helper.rb new file mode 100644 index 00000000000..4780e08322a --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/helper.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + module Helper + include ActionView::Context + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + + private + + def list(array) + case format + when :html + tag.ul { array.map { |item| tag.li item} } + else + '- ' + array.join("\n- ") + end + end + + def strong_options + case format + when :html + { strong_start: '<b>'.html_safe, strong_end: '</b>'.html_safe } + else + { strong_start: '', strong_end: '' } + end + end + + def link(text, link) + case format + when :html + link_to text, link + else + "#{text} (#{link})" + end + end + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/team.rb b/lib/gitlab/email/message/in_product_marketing/team.rb new file mode 100644 index 00000000000..46c2797e534 --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/team.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + class Team < Base + def subject_line + [ + s_('InProductMarketing|Working in GitLab = more efficient'), + s_("InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"), + s_('InProductMarketing|Your teams can be more efficient') + ][series] + end + + def tagline + [ + s_('InProductMarketing|Invite your colleagues to join in less than one minute'), + s_('InProductMarketing|Get your team set up on GitLab'), + nil + ][series] + end + + def title + [ + s_('InProductMarketing|Team work makes the dream work'), + s_('InProductMarketing|*GitLab*, noun: a synonym for efficient teams'), + s_('InProductMarketing|Find out how your teams are really doing') + ][series] + end + + def subtitle + [ + s_('InProductMarketing|Actually, GitLab makes the team work (better)'), + s_('InProductMarketing|Our tool brings all the things together'), + s_("InProductMarketing|It's all in the stats") + ][series] + end + + def body_line1 + [ + [ + s_('InProductMarketing|Did you know teams that use GitLab are far more efficient?'), + list([ + s_('InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day'), + s_('InProductMarketing|Ticketmaster decreased their CI build time by 15X') + ]) + ].join("\n"), + s_("InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."), + [ + s_('InProductMarketing|Stop wondering and use GitLab to answer questions like:'), + list([ + s_('InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?'), + s_('InProductMarketing|How many days does it take our team to complete various tasks?'), + s_('InProductMarketing|What does our value stream timeline look like from product to development to review and production?') + ]) + ].join("\n") + ][series] + end + + def body_line2 + [ + s_('InProductMarketing|Invite your colleagues and start shipping code faster.'), + s_("InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."), + s_('InProductMarketing|When your team is on GitLab these answers are a click away.') + ][series] + end + + def cta_text + [ + s_('InProductMarketing|Invite your colleagues today'), + s_('InProductMarketing|Invite your team in less than 60 seconds'), + s_('InProductMarketing|Invite your team now') + ][series] + end + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/trial.rb b/lib/gitlab/email/message/in_product_marketing/trial.rb new file mode 100644 index 00000000000..d87dc5c1b81 --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/trial.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + class Trial < Base + def subject_line + [ + s_('InProductMarketing|Go farther with GitLab'), + s_('InProductMarketing|Automated security scans directly within GitLab'), + s_('InProductMarketing|Take your source code management to the next level') + ][series] + end + + def tagline + [ + s_('InProductMarketing|Start a free trial of GitLab Ultimate – no CC required'), + s_('InProductMarketing|Improve app security with a 30-day trial'), + s_('InProductMarketing|Start with a GitLab Ultimate free trial') + ][series] + end + + def title + [ + s_('InProductMarketing|Give us one minute...'), + s_("InProductMarketing|Security that's integrated into your development lifecycle"), + s_('InProductMarketing|Improve code quality and streamline reviews') + ][series] + end + + def subtitle + [ + s_('InProductMarketing|...and you can get a free trial of GitLab Ultimate'), + s_('InProductMarketing|Try GitLab Ultimate for free'), + s_('InProductMarketing|Better code in less time') + ][series] + end + + def body_line1 + [ + [ + s_("InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"), + list([ + s_('InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels').html_safe % strong_options, + s_('InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals').html_safe % strong_options, + s_('InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection').html_safe % strong_options, + s_('InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream').html_safe % strong_options + ]) + ].join("\n"), + s_('InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance.'), + s_('InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process.') + ][series] + end + + def body_line2 + [ + s_('InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required.'), + s_('InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required.'), + s_('InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required.') + ][series] + end + + def cta_text + [ + s_('InProductMarketing|Start a trial'), + s_('InProductMarketing|Beef up your security'), + s_('InProductMarketing|Start your trial now!') + ][series] + end + end + end + end + end +end diff --git a/lib/gitlab/email/message/in_product_marketing/verify.rb b/lib/gitlab/email/message/in_product_marketing/verify.rb new file mode 100644 index 00000000000..d563de6c77e --- /dev/null +++ b/lib/gitlab/email/message/in_product_marketing/verify.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +module Gitlab + module Email + module Message + module InProductMarketing + class Verify < Base + def subject_line + [ + s_('InProductMarketing|Feel the need for speed?'), + s_('InProductMarketing|3 ways to dive into GitLab CI/CD'), + s_('InProductMarketing|Explore the power of GitLab CI/CD') + ][series] + end + + def tagline + [ + s_('InProductMarketing|Use GitLab CI/CD'), + s_('InProductMarketing|Test, create, deploy'), + s_('InProductMarketing|Are your runners ready?') + ][series] + end + + def title + [ + s_('InProductMarketing|Rapid development, simplified'), + s_('InProductMarketing|Get started with GitLab CI/CD'), + s_('InProductMarketing|Launch GitLab CI/CD in 20 minutes or less') + ][series] + end + + def subtitle + [ + s_('InProductMarketing|How to build and test faster'), + s_('InProductMarketing|Explore the options'), + s_('InProductMarketing|Follow our steps') + ][series] + end + + def body_line1 + [ + s_("InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}.") % { ci_link: ci_link }, + s_("InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"), + s_("InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy.") % { quick_start_link: quick_start_link } + ][series] + end + + def body_line2 + [ + nil, + list([ + s_('InProductMarketing|Start by %{performance_link}').html_safe % { performance_link: performance_link }, + s_('InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}').html_safe % { ci_template_link: ci_template_link }, + s_('InProductMarketing|And finally %{deploy_link} a Python application.').html_safe % { deploy_link: deploy_link } + ]), + nil + ][series] + end + + def cta_text + [ + s_('InProductMarketing|Get to know GitLab CI/CD'), + s_('InProductMarketing|Try it yourself'), + s_('InProductMarketing|Explore GitLab CI/CD') + ][series] + end + + private + + def ci_link + link(s_('InProductMarketing|how easy it is to get started'), help_page_url('ci/README')) + end + + def quick_start_link + link(s_('InProductMarketing|quick start guide'), help_page_url('ci/quick_start/README')) + end + + def performance_link + link(s_('InProductMarketing|testing browser performance'), help_page_url('user/project/merge_requests/browser_performance_testing')) + end + + def ci_template_link + link(s_('InProductMarketing|using a CI/CD template'), help_page_url('user/project/pages/getting_started/pages_ci_cd_template')) + end + + def deploy_link + link(s_('InProductMarketing|test and deploy'), help_page_url('ci/examples/test-and-deploy-python-application-to-heroku')) + end + end + end + end + end +end 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' diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb index dc44e9d7481..7579f3d8680 100644 --- a/lib/gitlab/email/reply_parser.rb +++ b/lib/gitlab/email/reply_parser.rb @@ -68,7 +68,7 @@ module Gitlab else object.body.to_s end - rescue + rescue StandardError nil end end diff --git a/lib/gitlab/email/service_desk_receiver.rb b/lib/gitlab/email/service_desk_receiver.rb index 1ee5c10097b..133c4ee4b45 100644 --- a/lib/gitlab/email/service_desk_receiver.rb +++ b/lib/gitlab/email/service_desk_receiver.rb @@ -5,14 +5,19 @@ module Gitlab class ServiceDeskReceiver < Receiver private - def find_handler(mail) - key = service_desk_key(mail) - return unless key + def find_handler + return unless service_desk_key - Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: key) + Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: service_desk_key) end - def service_desk_key(mail) + def service_desk_key + strong_memoize(:service_desk_key) do + find_service_desk_key + end + end + + def find_service_desk_key mail.to.find do |address| key = ::Gitlab::ServiceDeskEmail.key_from_address(address) break key if key |