omg-actionmailer 8.0.0.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +2 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +141 -0
- data/lib/action_mailer/base.rb +1076 -0
- data/lib/action_mailer/callbacks.rb +31 -0
- data/lib/action_mailer/collector.rb +32 -0
- data/lib/action_mailer/delivery_methods.rb +83 -0
- data/lib/action_mailer/deprecator.rb +7 -0
- data/lib/action_mailer/form_builder.rb +37 -0
- data/lib/action_mailer/gem_version.rb +17 -0
- data/lib/action_mailer/inline_preview_interceptor.rb +59 -0
- data/lib/action_mailer/log_subscriber.rb +44 -0
- data/lib/action_mailer/mail_delivery_job.rb +48 -0
- data/lib/action_mailer/mail_helper.rb +74 -0
- data/lib/action_mailer/message_delivery.rb +156 -0
- data/lib/action_mailer/parameterized.rb +154 -0
- data/lib/action_mailer/preview.rb +142 -0
- data/lib/action_mailer/queued_delivery.rb +12 -0
- data/lib/action_mailer/railtie.rb +94 -0
- data/lib/action_mailer/rescuable.rb +33 -0
- data/lib/action_mailer/test_case.rb +126 -0
- data/lib/action_mailer/test_helper.rb +264 -0
- data/lib/action_mailer/version.rb +11 -0
- data/lib/action_mailer.rb +79 -0
- data/lib/rails/generators/mailer/USAGE +20 -0
- data/lib/rails/generators/mailer/mailer_generator.rb +38 -0
- data/lib/rails/generators/mailer/templates/application_mailer.rb.tt +6 -0
- data/lib/rails/generators/mailer/templates/mailer.rb.tt +19 -0
- metadata +162 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
module Callbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include ActiveSupport::Callbacks
|
9
|
+
define_callbacks :deliver, skip_after_callbacks_if_terminated: true
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Defines a callback that will get called right before the
|
14
|
+
# message is sent to the delivery method.
|
15
|
+
def before_deliver(*filters, &blk)
|
16
|
+
set_callback(:deliver, :before, *filters, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Defines a callback that will get called right after the
|
20
|
+
# message's delivery method is finished.
|
21
|
+
def after_deliver(*filters, &blk)
|
22
|
+
set_callback(:deliver, :after, *filters, &blk)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Defines a callback that will get called around the message's deliver method.
|
26
|
+
def around_deliver(*filters, &blk)
|
27
|
+
set_callback(:deliver, :around, *filters, &blk)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "abstract_controller/collector"
|
4
|
+
require "active_support/core_ext/hash/reverse_merge"
|
5
|
+
require "active_support/core_ext/array/extract_options"
|
6
|
+
|
7
|
+
module ActionMailer
|
8
|
+
class Collector
|
9
|
+
include AbstractController::Collector
|
10
|
+
attr_reader :responses
|
11
|
+
|
12
|
+
def initialize(context, &block)
|
13
|
+
@context = context
|
14
|
+
@responses = []
|
15
|
+
@default_render = block
|
16
|
+
end
|
17
|
+
|
18
|
+
def any(*args, &block)
|
19
|
+
options = args.extract_options!
|
20
|
+
raise ArgumentError, "You have to supply at least one format" if args.empty?
|
21
|
+
args.each { |type| send(type, options.dup, &block) }
|
22
|
+
end
|
23
|
+
alias :all :any
|
24
|
+
|
25
|
+
def custom(mime, options = {})
|
26
|
+
options.reverse_merge!(content_type: mime.to_s)
|
27
|
+
@context.formats = [mime.to_sym]
|
28
|
+
options[:body] = block_given? ? yield : @default_render.call
|
29
|
+
@responses << options
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tmpdir"
|
4
|
+
|
5
|
+
module ActionMailer
|
6
|
+
# = Action Mailer \DeliveryMethods
|
7
|
+
#
|
8
|
+
# This module handles everything related to mail delivery, from registering
|
9
|
+
# new delivery methods to configuring the mail object to be sent.
|
10
|
+
module DeliveryMethods
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# Do not make this inheritable, because we always want it to propagate
|
15
|
+
cattr_accessor :raise_delivery_errors, default: true
|
16
|
+
cattr_accessor :perform_deliveries, default: true
|
17
|
+
|
18
|
+
class_attribute :delivery_methods, default: {}.freeze
|
19
|
+
class_attribute :delivery_method, default: :smtp
|
20
|
+
|
21
|
+
add_delivery_method :smtp, Mail::SMTP,
|
22
|
+
address: "localhost",
|
23
|
+
port: 25,
|
24
|
+
domain: "localhost.localdomain",
|
25
|
+
user_name: nil,
|
26
|
+
password: nil,
|
27
|
+
authentication: nil,
|
28
|
+
enable_starttls_auto: true
|
29
|
+
|
30
|
+
add_delivery_method :file, Mail::FileDelivery,
|
31
|
+
location: defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
|
32
|
+
|
33
|
+
add_delivery_method :sendmail, Mail::Sendmail,
|
34
|
+
location: "/usr/sbin/sendmail",
|
35
|
+
arguments: %w[-i]
|
36
|
+
|
37
|
+
add_delivery_method :test, Mail::TestMailer
|
38
|
+
end
|
39
|
+
|
40
|
+
# Helpers for creating and wrapping delivery behavior, used by DeliveryMethods.
|
41
|
+
module ClassMethods
|
42
|
+
# Provides a list of emails that have been delivered by Mail::TestMailer
|
43
|
+
delegate :deliveries, :deliveries=, to: Mail::TestMailer
|
44
|
+
|
45
|
+
# Adds a new delivery method through the given class using the given
|
46
|
+
# symbol as alias and the default options supplied.
|
47
|
+
#
|
48
|
+
# add_delivery_method :sendmail, Mail::Sendmail,
|
49
|
+
# location: '/usr/sbin/sendmail',
|
50
|
+
# arguments: %w[ -i ]
|
51
|
+
def add_delivery_method(symbol, klass, default_options = {})
|
52
|
+
class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
|
53
|
+
public_send(:"#{symbol}_settings=", default_options)
|
54
|
+
self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
|
55
|
+
end
|
56
|
+
|
57
|
+
def wrap_delivery_behavior(mail, method = nil, options = nil) # :nodoc:
|
58
|
+
method ||= delivery_method
|
59
|
+
mail.delivery_handler = self
|
60
|
+
|
61
|
+
case method
|
62
|
+
when NilClass
|
63
|
+
raise "Delivery method cannot be nil"
|
64
|
+
when Symbol
|
65
|
+
if klass = delivery_methods[method]
|
66
|
+
mail.delivery_method(klass, (send(:"#{method}_settings") || {}).merge(options || {}))
|
67
|
+
else
|
68
|
+
raise "Invalid delivery method #{method.inspect}"
|
69
|
+
end
|
70
|
+
else
|
71
|
+
mail.delivery_method(method)
|
72
|
+
end
|
73
|
+
|
74
|
+
mail.perform_deliveries = perform_deliveries
|
75
|
+
mail.raise_delivery_errors = raise_delivery_errors
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def wrap_delivery_behavior!(*args) # :nodoc:
|
80
|
+
self.class.wrap_delivery_behavior(message, *args)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
# = Action Mailer Form Builder
|
5
|
+
#
|
6
|
+
# Override the default form builder for all views rendered by this
|
7
|
+
# mailer and any of its descendants. Accepts a subclass of
|
8
|
+
# ActionView::Helpers::FormBuilder.
|
9
|
+
#
|
10
|
+
# While emails typically will not include forms, this can be used
|
11
|
+
# by views that are shared between controllers and mailers.
|
12
|
+
#
|
13
|
+
# For more information, see +ActionController::FormBuilder+.
|
14
|
+
module FormBuilder
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
included do
|
18
|
+
class_attribute :_default_form_builder, instance_accessor: false
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
# Set the form builder to be used as the default for all forms
|
23
|
+
# in the views rendered by this mailer and its subclasses.
|
24
|
+
#
|
25
|
+
# ==== Parameters
|
26
|
+
# * <tt>builder</tt> - Default form builder, an instance of ActionView::Helpers::FormBuilder
|
27
|
+
def default_form_builder(builder)
|
28
|
+
self._default_form_builder = builder
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Default form builder for the mailer
|
33
|
+
def default_form_builder
|
34
|
+
self.class._default_form_builder
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
# Returns the currently loaded version of Action Mailer as a +Gem::Version+.
|
5
|
+
def self.gem_version
|
6
|
+
Gem::Version.new VERSION::STRING
|
7
|
+
end
|
8
|
+
|
9
|
+
module VERSION
|
10
|
+
MAJOR = 8
|
11
|
+
MINOR = 0
|
12
|
+
TINY = 0
|
13
|
+
PRE = "alpha2"
|
14
|
+
|
15
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
module ActionMailer
|
6
|
+
# = Action Mailer \InlinePreviewInterceptor
|
7
|
+
#
|
8
|
+
# Implements a mailer preview interceptor that converts image tag src attributes
|
9
|
+
# that use inline cid: style URLs to data: style URLs so that they are visible
|
10
|
+
# when previewing an HTML email in a web browser.
|
11
|
+
#
|
12
|
+
# This interceptor is enabled by default. To disable it, delete it from the
|
13
|
+
# <tt>ActionMailer::Base.preview_interceptors</tt> array:
|
14
|
+
#
|
15
|
+
# ActionMailer::Base.preview_interceptors.delete(ActionMailer::InlinePreviewInterceptor)
|
16
|
+
#
|
17
|
+
class InlinePreviewInterceptor
|
18
|
+
PATTERN = /src=(?:"cid:[^"]+"|'cid:[^']+')/i
|
19
|
+
|
20
|
+
include Base64
|
21
|
+
|
22
|
+
def self.previewing_email(message) # :nodoc:
|
23
|
+
new(message).transform!
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(message) # :nodoc:
|
27
|
+
@message = message
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform! # :nodoc:
|
31
|
+
return message if html_part.blank?
|
32
|
+
|
33
|
+
html_part.body = html_part.decoded.gsub(PATTERN) do |match|
|
34
|
+
if part = find_part(match[9..-2])
|
35
|
+
%[src="#{data_url(part)}"]
|
36
|
+
else
|
37
|
+
match
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
message
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
attr_reader :message
|
46
|
+
|
47
|
+
def html_part
|
48
|
+
@html_part ||= message.html_part
|
49
|
+
end
|
50
|
+
|
51
|
+
def data_url(part)
|
52
|
+
"data:#{part.mime_type};base64,#{strict_encode64(part.body.raw_source)}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_part(cid)
|
56
|
+
message.all_parts.find { |p| p.attachment? && p.cid == cid }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/log_subscriber"
|
4
|
+
|
5
|
+
module ActionMailer
|
6
|
+
# = Action Mailer \LogSubscriber
|
7
|
+
#
|
8
|
+
# Implements the ActiveSupport::LogSubscriber for logging notifications when
|
9
|
+
# email is delivered or received.
|
10
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
11
|
+
# An email was delivered.
|
12
|
+
def deliver(event)
|
13
|
+
info do
|
14
|
+
if exception = event.payload[:exception_object]
|
15
|
+
"Failed delivery of mail #{event.payload[:message_id]} error_class=#{exception.class} error_message=#{exception.message.inspect}"
|
16
|
+
elsif event.payload[:perform_deliveries]
|
17
|
+
"Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)"
|
18
|
+
else
|
19
|
+
"Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
debug { event.payload[:mail] }
|
24
|
+
end
|
25
|
+
subscribe_log_level :deliver, :debug
|
26
|
+
|
27
|
+
# An email was generated.
|
28
|
+
def process(event)
|
29
|
+
debug do
|
30
|
+
mailer = event.payload[:mailer]
|
31
|
+
action = event.payload[:action]
|
32
|
+
"#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
subscribe_log_level :process, :debug
|
36
|
+
|
37
|
+
# Use the logger configured for ActionMailer::Base.
|
38
|
+
def logger
|
39
|
+
ActionMailer::Base.logger
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ActionMailer::LogSubscriber.attach_to :action_mailer
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_job"
|
4
|
+
|
5
|
+
module ActionMailer
|
6
|
+
# = Action Mailer \MailDeliveryJob
|
7
|
+
#
|
8
|
+
# The +ActionMailer::MailDeliveryJob+ class is used when you
|
9
|
+
# want to send emails outside of the request-response cycle. It supports
|
10
|
+
# sending either parameterized or normal mail.
|
11
|
+
#
|
12
|
+
# Exceptions are rescued and handled by the mailer class.
|
13
|
+
class MailDeliveryJob < ActiveJob::Base # :nodoc:
|
14
|
+
queue_as do
|
15
|
+
mailer_class = arguments.first.constantize
|
16
|
+
mailer_class.deliver_later_queue_name
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue_from StandardError, with: :handle_exception_with_mailer_class
|
20
|
+
|
21
|
+
def perform(mailer, mail_method, delivery_method, args:, kwargs: nil, params: nil)
|
22
|
+
mailer_class = params ? mailer.constantize.with(params) : mailer.constantize
|
23
|
+
message = if kwargs
|
24
|
+
mailer_class.public_send(mail_method, *args, **kwargs)
|
25
|
+
else
|
26
|
+
mailer_class.public_send(mail_method, *args)
|
27
|
+
end
|
28
|
+
message.send(delivery_method)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
# "Deserialize" the mailer class name by hand in case another argument
|
33
|
+
# (like a Global ID reference) raised DeserializationError.
|
34
|
+
def mailer_class
|
35
|
+
if mailer = Array(@serialized_arguments).first || Array(arguments).first
|
36
|
+
mailer.constantize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_exception_with_mailer_class(exception)
|
41
|
+
if klass = mailer_class
|
42
|
+
klass.handle_exception exception
|
43
|
+
else
|
44
|
+
raise exception
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
# = Action Mailer \MailHelper
|
5
|
+
#
|
6
|
+
# Provides helper methods for ActionMailer::Base that can be used for easily
|
7
|
+
# formatting messages, accessing mailer or message instances, and the
|
8
|
+
# attachments list.
|
9
|
+
module MailHelper
|
10
|
+
# Take the text and format it, indented two spaces for each line, and
|
11
|
+
# wrapped at 72 columns:
|
12
|
+
#
|
13
|
+
# text = <<-TEXT
|
14
|
+
# This is
|
15
|
+
# the paragraph.
|
16
|
+
#
|
17
|
+
# * item1 * item2
|
18
|
+
# TEXT
|
19
|
+
#
|
20
|
+
# block_format text
|
21
|
+
# # => " This is the paragraph.\n\n * item1\n * item2\n"
|
22
|
+
def block_format(text)
|
23
|
+
formatted = text.split(/\n\r?\n/).collect { |paragraph|
|
24
|
+
format_paragraph(paragraph)
|
25
|
+
}.join("\n\n")
|
26
|
+
|
27
|
+
# Make list points stand on their own line
|
28
|
+
formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { " #{$1} #{$2.strip}\n" }
|
29
|
+
formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { " #{$1} #{$2.strip}\n" }
|
30
|
+
|
31
|
+
formatted
|
32
|
+
end
|
33
|
+
|
34
|
+
# Access the mailer instance.
|
35
|
+
def mailer
|
36
|
+
@_controller
|
37
|
+
end
|
38
|
+
|
39
|
+
# Access the message instance.
|
40
|
+
def message
|
41
|
+
@_message
|
42
|
+
end
|
43
|
+
|
44
|
+
# Access the message attachments list.
|
45
|
+
def attachments
|
46
|
+
mailer.attachments
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
|
50
|
+
# By default column length +len+ equals 72 characters and indent
|
51
|
+
# +indent+ equal two spaces.
|
52
|
+
#
|
53
|
+
# my_text = 'Here is a sample text with more than 40 characters'
|
54
|
+
#
|
55
|
+
# format_paragraph(my_text, 25, 4)
|
56
|
+
# # => " Here is a sample text with\n more than 40 characters"
|
57
|
+
def format_paragraph(text, len = 72, indent = 2)
|
58
|
+
sentences = [[]]
|
59
|
+
|
60
|
+
text.split.each do |word|
|
61
|
+
if sentences.first.present? && (sentences.last + [word]).join(" ").length > len
|
62
|
+
sentences << [word]
|
63
|
+
else
|
64
|
+
sentences.last << word
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
indentation = " " * indent
|
69
|
+
sentences.map! { |sentence|
|
70
|
+
"#{indentation}#{sentence.join(' ')}"
|
71
|
+
}.join "\n"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module ActionMailer
|
6
|
+
# = Action Mailer \MessageDelivery
|
7
|
+
#
|
8
|
+
# The +ActionMailer::MessageDelivery+ class is used by
|
9
|
+
# ActionMailer::Base when creating a new mailer.
|
10
|
+
# <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
|
11
|
+
# created +Mail::Message+. You can get direct access to the
|
12
|
+
# +Mail::Message+, deliver the email or schedule the email to be sent
|
13
|
+
# through Active Job.
|
14
|
+
#
|
15
|
+
# Notifier.welcome(User.first) # an ActionMailer::MessageDelivery object
|
16
|
+
# Notifier.welcome(User.first).deliver_now # sends the email
|
17
|
+
# Notifier.welcome(User.first).deliver_later # enqueue email delivery as a job through Active Job
|
18
|
+
# Notifier.welcome(User.first).message # a Mail::Message object
|
19
|
+
class MessageDelivery < Delegator
|
20
|
+
def initialize(mailer_class, action, *args) # :nodoc:
|
21
|
+
@mailer_class, @action, @args = mailer_class, action, args
|
22
|
+
|
23
|
+
# The mail is only processed if we try to call any methods on it.
|
24
|
+
# Typical usage will leave it unloaded and call deliver_later.
|
25
|
+
@processed_mailer = nil
|
26
|
+
@mail_message = nil
|
27
|
+
end
|
28
|
+
ruby2_keywords(:initialize)
|
29
|
+
|
30
|
+
# Method calls are delegated to the Mail::Message that's ready to deliver.
|
31
|
+
def __getobj__ # :nodoc:
|
32
|
+
@mail_message ||= processed_mailer.message
|
33
|
+
end
|
34
|
+
|
35
|
+
# Unused except for delegator internals (dup, marshalling).
|
36
|
+
def __setobj__(mail_message) # :nodoc:
|
37
|
+
@mail_message = mail_message
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the resulting Mail::Message
|
41
|
+
def message
|
42
|
+
__getobj__
|
43
|
+
end
|
44
|
+
|
45
|
+
# Was the delegate loaded, causing the mailer action to be processed?
|
46
|
+
def processed?
|
47
|
+
@processed_mailer || @mail_message
|
48
|
+
end
|
49
|
+
|
50
|
+
# Enqueues the email to be delivered through Active Job. When the
|
51
|
+
# job runs it will send the email using +deliver_now!+. That means
|
52
|
+
# that the message will be sent bypassing checking +perform_deliveries+
|
53
|
+
# and +raise_delivery_errors+, so use with caution.
|
54
|
+
#
|
55
|
+
# Notifier.welcome(User.first).deliver_later!
|
56
|
+
# Notifier.welcome(User.first).deliver_later!(wait: 1.hour)
|
57
|
+
# Notifier.welcome(User.first).deliver_later!(wait_until: 10.hours.from_now)
|
58
|
+
# Notifier.welcome(User.first).deliver_later!(priority: 10)
|
59
|
+
#
|
60
|
+
# Options:
|
61
|
+
#
|
62
|
+
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay
|
63
|
+
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time
|
64
|
+
# * <tt>:queue</tt> - Enqueue the email on the specified queue
|
65
|
+
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
66
|
+
#
|
67
|
+
# By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
|
68
|
+
# the default queue. Mailer classes can customize the queue name used for the default
|
69
|
+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
|
70
|
+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
|
71
|
+
#
|
72
|
+
# class AccountRegistrationMailer < ApplicationMailer
|
73
|
+
# self.delivery_job = RegistrationDeliveryJob
|
74
|
+
# end
|
75
|
+
def deliver_later!(options = {})
|
76
|
+
enqueue_delivery :deliver_now!, options
|
77
|
+
end
|
78
|
+
|
79
|
+
# Enqueues the email to be delivered through Active Job. When the
|
80
|
+
# job runs it will send the email using +deliver_now+.
|
81
|
+
#
|
82
|
+
# Notifier.welcome(User.first).deliver_later
|
83
|
+
# Notifier.welcome(User.first).deliver_later(wait: 1.hour)
|
84
|
+
# Notifier.welcome(User.first).deliver_later(wait_until: 10.hours.from_now)
|
85
|
+
# Notifier.welcome(User.first).deliver_later(priority: 10)
|
86
|
+
#
|
87
|
+
# Options:
|
88
|
+
#
|
89
|
+
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay.
|
90
|
+
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time.
|
91
|
+
# * <tt>:queue</tt> - Enqueue the email on the specified queue.
|
92
|
+
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
93
|
+
#
|
94
|
+
# By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
|
95
|
+
# the default queue. Mailer classes can customize the queue name used for the default
|
96
|
+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
|
97
|
+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
|
98
|
+
#
|
99
|
+
# class AccountRegistrationMailer < ApplicationMailer
|
100
|
+
# self.delivery_job = RegistrationDeliveryJob
|
101
|
+
# end
|
102
|
+
def deliver_later(options = {})
|
103
|
+
enqueue_delivery :deliver_now, options
|
104
|
+
end
|
105
|
+
|
106
|
+
# Delivers an email without checking +perform_deliveries+ and +raise_delivery_errors+,
|
107
|
+
# so use with caution.
|
108
|
+
#
|
109
|
+
# Notifier.welcome(User.first).deliver_now!
|
110
|
+
#
|
111
|
+
def deliver_now!
|
112
|
+
processed_mailer.handle_exceptions do
|
113
|
+
processed_mailer.run_callbacks(:deliver) do
|
114
|
+
message.deliver!
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Delivers an email:
|
120
|
+
#
|
121
|
+
# Notifier.welcome(User.first).deliver_now
|
122
|
+
#
|
123
|
+
def deliver_now
|
124
|
+
processed_mailer.handle_exceptions do
|
125
|
+
processed_mailer.run_callbacks(:deliver) do
|
126
|
+
message.deliver
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
# Returns the processed Mailer instance. We keep this instance
|
133
|
+
# on hand so we can run callbacks and delegate exception handling to it.
|
134
|
+
def processed_mailer
|
135
|
+
@processed_mailer ||= @mailer_class.new.tap do |mailer|
|
136
|
+
mailer.process @action, *@args
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def enqueue_delivery(delivery_method, options = {})
|
141
|
+
if processed?
|
142
|
+
::Kernel.raise "You've accessed the message before asking to " \
|
143
|
+
"deliver it later, so you may have made local changes that would " \
|
144
|
+
"be silently lost if we enqueued a job to deliver it. Why? Only " \
|
145
|
+
"the mailer method *arguments* are passed with the delivery job! " \
|
146
|
+
"Do not access the message in any way if you mean to deliver it " \
|
147
|
+
"later. Workarounds: 1. don't touch the message before calling " \
|
148
|
+
"#deliver_later, 2. only touch the message *within your mailer " \
|
149
|
+
"method*, or 3. use a custom Active Job instead of #deliver_later."
|
150
|
+
else
|
151
|
+
@mailer_class.delivery_job.set(options).perform_later(
|
152
|
+
@mailer_class.name, @action.to_s, delivery_method.to_s, args: @args)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|