OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/app/mailers/application_mailer.rb

211 lines
6.6 KiB

#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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
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
# Activates/deactivates email deliveries during +block+
def with_deliveries(temporary_state = true, &_block)
old_state = ActionMailer::Base.perform_deliveries
ActionMailer::Base.perform_deliveries = temporary_state
yield
ensure
ActionMailer::Base.perform_deliveries = old_state
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
def protocol
Setting.protocol
end
def default_url_options
options = super.merge host: host, protocol: protocol
if OpenProject::Configuration.rails_relative_url_root.present?
options[:script_name] = OpenProject::Configuration.rails_relative_url_root
end
options
end
end
def mail(headers = {}, &block)
block ||= method(:default_formats_for_setting)
super(headers, &block)
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
3 years ago
def send_mail(user, subject)
with_locale_for(user) do
mail to: user.mail, subject: subject
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 = Setting.mail_from.to_s.gsub(%r{\A.*@}, '')
host = "#{::Socket.gethostname}.openproject" if host.empty?
host
end
3 years ago
end
##
# Interceptors
#
# These are registered in config/initializers/register_mail_interceptors.rb
#
# Unfortunately, this results in changes on the interceptor classes during development mode
# not being reflected until a server restart.
class DefaultHeadersInterceptor
def self.delivering_email(mail)
mail.headers(default_headers)
end
def self.default_headers
{
'X-Mailer' => 'OpenProject',
'X-OpenProject-Host' => Setting.host_name,
'X-OpenProject-Site' => Setting.app_title,
'Precedence' => 'bulk',
'Auto-Submitted' => 'auto-generated'
}
end
end
class DoNotSendMailsWithoutReceiverInterceptor
def self.delivering_email(mail)
receivers = [mail.to, mail.cc, mail.bcc]
# the above fields might be empty arrays (if entries have been removed
# by another interceptor) or nil, therefore checking for blank?
mail.perform_deliveries = false if receivers.all?(&:blank?)
end
end