Welcome to mirror list, hosted at ThFree Co, Russian Federation.

service_desk.rb « emails « mailers « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 1295f978049cb73a8c70ab4a4830ee477ab9b8be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# frozen_string_literal: true

module Emails
  module ServiceDesk
    extend ActiveSupport::Concern
    include MarkupHelper

    EMAIL_ATTACHMENTS_SIZE_LIMIT = 10.megabytes.freeze

    included do
      layout 'service_desk', only: [:service_desk_thank_you_email, :service_desk_new_note_email]
    end

    def service_desk_thank_you_email(issue_id)
      setup_service_desk_mail(issue_id)

      email_sender = sender(
        @support_bot.id,
        send_from_user_email: false,
        sender_name: @service_desk_setting&.outgoing_name,
        sender_email: service_desk_sender_email_address
      )
      options = service_desk_options(email_sender, 'thank_you', @issue.external_author)
                  .merge(subject: "Re: #{subject_base}")

      inject_service_desk_custom_email(mail_new_thread(@issue, options))
    end

    def service_desk_new_note_email(issue_id, note_id, recipient)
      @note = Note.find(note_id)
      setup_service_desk_mail(issue_id)

      email_sender = sender(
        @note.author_id,
        send_from_user_email: false,
        sender_email: service_desk_sender_email_address
      )

      add_uploads_as_attachments if Feature.enabled?(:service_desk_new_note_email_native_attachments, @note.project)
      options = service_desk_options(email_sender, 'new_note', recipient)
                  .merge(subject: subject_base)

      inject_service_desk_custom_email(mail_answer_thread(@issue, options))
    end

    private

    def setup_service_desk_mail(issue_id)
      @issue = Issue.find(issue_id)
      @project = @issue.project
      @support_bot = User.support_bot

      @service_desk_setting = @project.service_desk_setting

      @sent_notification = SentNotification.record(@issue, @support_bot.id, reply_key)
    end

    def service_desk_options(email_sender, email_type, recipient)
      {
        from: email_sender,
        to: recipient
      }.tap do |options|
        next unless template_body = template_content(email_type)

        options[:body] = template_body
        options[:content_type] = 'text/html' unless attachments.present?
      end
    end

    def inject_service_desk_custom_email(mail)
      return mail unless service_desk_custom_email_enabled?

      mail.delivery_method(::Mail::SMTP, @service_desk_setting.custom_email_delivery_options)
    end

    def service_desk_custom_email_enabled?
      Feature.enabled?(:service_desk_custom_email, @project) && @service_desk_setting&.custom_email_enabled?
    end

    def service_desk_sender_email_address
      return unless service_desk_custom_email_enabled?

      @service_desk_setting.custom_email
    end

    def template_content(email_type)
      template = Gitlab::Template::ServiceDeskTemplate.find(email_type, @project)
      text = substitute_template_replacements(template.content)

      context = { project: @project, pipeline: :service_desk_email, uploads_as_attachments: @uploads_as_attachments }

      context[:author] = @note.author if email_type == 'new_note'

      markdown(text, context)
    rescue Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
      nil
    end

    def substitute_template_replacements(template_body)
      template_body
        .gsub(/%\{\s*ISSUE_ID\s*\}/, issue_id)
        .gsub(/%\{\s*ISSUE_PATH\s*\}/, issue_path)
        .gsub(/%\{\s*NOTE_TEXT\s*\}/, note_text)
        .gsub(/%\{\s*SYSTEM_HEADER\s*\}/, text_header_message.to_s)
        .gsub(/%\{\s*SYSTEM_FOOTER\s*\}/, text_footer_message.to_s)
        .gsub(/%\{\s*UNSUBSCRIBE_URL\s*\}/, unsubscribe_sent_notification_url(@sent_notification))
        .gsub(/%\{\s*ADDITIONAL_TEXT\s*\}/, service_desk_email_additional_text.to_s)
    end

    def issue_id
      "#{Issue.reference_prefix}#{@issue.iid}"
    end

    def issue_path
      @issue.to_reference(full: true)
    end

    def note_text
      @note&.note.to_s
    end

    def subject_base
      "#{@issue.title} (##{@issue.iid})"
    end

    def add_uploads_as_attachments
      uploaders = find_uploaders_for(@note)
      return unless uploaders.present?
      return if uploaders.sum(&:size) > EMAIL_ATTACHMENTS_SIZE_LIMIT

      @uploads_as_attachments = []
      uploaders.each do |uploader|
        attachments[uploader.filename] = uploader.read
        @uploads_as_attachments << "#{uploader.secret}/#{uploader.filename}"
      rescue StandardError => e
        Gitlab::ErrorTracking.track_exception(e, project_id: @note.project.id)
      end
    end

    def find_uploaders_for(note)
      uploads = FileUploader::MARKDOWN_PATTERN.scan(note.note)
      return unless uploads.present?

      project = note.project
      uploads.map do |secret, file_name|
        UploaderFinder.new(project, secret, file_name).execute
      end
    rescue StandardError => e
      Gitlab::ErrorTracking.track_exception(e, project_id: note.project.id)
      nil
    end
  end
end