-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathapplication_mailer.rb
More file actions
216 lines (187 loc) · 6.8 KB
/
Copy pathapplication_mailer.rb
File metadata and controls
216 lines (187 loc) · 6.8 KB
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
class ApplicationMailer < ActionMailer::Base
layout "mailer"
helper :application, # for format_text
:work_packages, # for css classes
:custom_fields, # for show_value
:mail_formatting, # for format_mail_html / format_mail_text
:mail_layout # for layouting
include OpenProject::LocaleHelper
# Send all delayed mails with the following job
self.delivery_job = ::Mails::MailerJob
# wrap in a lambda to allow changing at run-time
default from: Proc.new { Setting.mail_from }
class << self
##
# Provide an easy way to get the default from address
# which is overridden for SaaS for tenant specific from addresses
#
# @return [String] the default from address
def mail_from
default[:from].call
end
##
# Provide an easy way to get the default reply_to address
# which is overridden for SaaS for tenant specific from addresses
#
# @return [String] the default from address
def reply_to
if default[:reply_to]
default[:reply_to].call
else
mail_from
end
end
##
# Return the email address of reply to
#
# @return [String] the default from address
def reply_to_address
address = reply_to
# Extract email from "Name <email>" format if present
address[/<(.+)>/, 1] || address
end
def host
if OpenProject::Configuration.rails_relative_url_root.blank?
Setting.host_name
else
Setting.host_name.to_s.gsub(%r{/.*\z}, "")
end
end
delegate :protocol, to: :Setting
def default_url_options
options = super.merge(host:, protocol:)
if OpenProject::Configuration.rails_relative_url_root.present?
options[:script_name] = OpenProject::Configuration.rails_relative_url_root
end
options
end
end
# Sets a Message-ID header.
#
# While the value is set in here, email gateways such as postmark, unless instructed explicitly will assign
# their own message id overwriting the value calculated in here.
#
# Because of this, the message id and the value affected by it (In-Reply-To) is not relied upon when an email response
# is handled by OpenProject.
def message_id(object, user)
headers["Message-ID"] = "<#{message_id_value(object, user)}>"
end
# Sets a References header.
#
# The value is used within the MailHandler to find the appropriate objects for update
# when a mail has been received but should also allow mail clients to mails
# by the referenced entities. Because of this it might make sense to provide more than one object
# of reference. E.g. for a message, the message parent can also be provided.
def references(*objects)
refs = objects.map do |object|
if object.is_a?(Journal)
"<#{references_value(object.journable)}> <#{references_value(object)}>"
else
"<#{references_value(object)}>"
end
end
headers["References"] = refs.join(" ")
end
# Prepends given fields with 'X-OpenProject-' to save some duplication
def open_project_headers(hash)
hash.each { |key, value| headers["X-OpenProject-#{key}"] = value.to_s }
end
private
def default_formats_for_setting(format)
format.html unless Setting.plain_text_mail?
format.text
end
##
# Overwrite mailer method to prevent sending mails to locked users.
# Usually this would accept a string for the `to:` argument, but
# we always require an actual user object since fed95796.
def mail(headers = {}, &block)
block ||= method(:default_formats_for_setting)
to = headers[:to]
if to
raise ArgumentError, "Recipient needs to be instance of User" unless to.is_a?(User)
if to.locked? || to.deleted?
Rails.logger.info "Not sending #{action_name} mail to locked user #{to.id} (#{to.login})"
return
end
end
super(headers.merge(to: to.mail), &block)
end
def send_localized_mail(user, delivery_method_options: {})
with_locale_for(user) do
subject = yield
mail to: user, subject:, delivery_method_options:
end
end
# Generates a unique value for the Message-ID header.
# Contains:
# * an 'op' prefix
# * an object id part that consists of the object's class name and the id unless that part is provided as a string
# * the current time
# * the recipient's id
#
# Note that this values, as opposed to the one from #references_value is unique.
def message_id_value(object, recipient)
object_reference = case object
when String
object
else
"#{object.class.name.demodulize.underscore}-#{object.id}"
end
hash = "op" \
"." \
"#{object_reference}" \
"." \
"#{Time.current.strftime('%Y%m%d%H%M%S')}" \
"." \
"#{recipient.id}"
"#{hash}@#{header_host_value}"
end
# Generates a value for the References header.
# Contains:
# * an 'op' prefix
# * an object id part that consists of the object's class name and the id
#
# Note that this values, as opposed to the one from #message_id_value is not unique.
# It in fact is aimed not not so that similar messages (i.e. those belonging to the same
# work package and journal) end up being grouped together.
def references_value(object)
hash = "op" \
"." \
"#{object.class.name.demodulize.underscore}-#{object.id}"
"#{hash}@#{header_host_value}"
end
def header_host_value
host = ApplicationMailer.mail_from.to_s.gsub(%r{\A.*@}, "")
host = "#{::Socket.gethostname}.openproject" if host.empty?
host
end
end