aboutsummaryrefslogtreecommitdiffstats
path: root/actionmailer/lib/action_mailer/base.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionmailer/lib/action_mailer/base.rb')
-rw-r--r--actionmailer/lib/action_mailer/base.rb56
1 files changed, 46 insertions, 10 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 135cf35ac0..1ab68d2953 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -138,9 +138,20 @@ module ActionMailer
# Once a mailer action and template are defined, you can deliver your message or create it and save it
# for delivery later:
#
- # Notifier.welcome(david).deliver # sends the email
- # mail = Notifier.welcome(david) # => a Mail::Message object
- # mail.deliver # sends the email
+ # Notifier.welcome(User.first).deliver_now # sends the email
+ # mail = Notifier.welcome(User.first) # => an ActionMailer::MessageDelivery object
+ # mail.deliver_now # sends the email
+ #
+ # The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a <tt>Mail::Message</tt> object. If
+ # you want direct access to the <tt>Mail::Message</tt> object you can call the <tt>message</tt> method on
+ # the <tt>ActionMailer::MessageDelivery</tt> object.
+ #
+ # Notifier.welcome(User.first).message # => a Mail::Message object
+ #
+ # Action Mailer is nicely integrated with Active Job so you can send emails in the background (example: outside
+ # of the request-response cycle, so the user doesn't have to wait on it):
+ #
+ # Notifier.welcome(User.first).deliver_later # enqueue the email sending to Active Job
#
# You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.
#
@@ -322,8 +333,8 @@ module ActionMailer
# end
#
# Methods must return a <tt>Mail::Message</tt> object which can be generated by calling the mailer
- # method without the additional <tt>deliver</tt>. The location of the mailer previews
- # directory can be configured using the <tt>preview_path</tt> option which has a default
+ # method without the additional <tt>deliver_now</tt> / <tt>deliver_later</tt>. The location of the
+ # mailer previews directory can be configured using the <tt>preview_path</tt> option which has a default
# of <tt>test/mailers/previews</tt>:
#
# config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
@@ -394,7 +405,7 @@ module ActionMailer
# implement for a custom delivery agent.
#
# * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you
- # call <tt>.deliver</tt> on an mail message or on an Action Mailer method. This is on by default but can
+ # call <tt>.deliver</tt> on an email message or on an Action Mailer method. This is on by default but can
# be turned off to aid in functional testing.
#
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with
@@ -548,8 +559,8 @@ module ActionMailer
end
def method_missing(method_name, *args) # :nodoc:
- if respond_to?(method_name)
- new(method_name, *args).message
+ if action_methods.include?(method_name.to_s)
+ MessageDelivery.new(self, method_name, *args)
else
super
end
@@ -586,6 +597,10 @@ module ActionMailer
class NullMail #:nodoc:
def body; '' end
+ def respond_to?(string, include_all=false)
+ true
+ end
+
def method_missing(*args)
nil
end
@@ -649,7 +664,22 @@ module ActionMailer
# mail.attachments[0] # => Mail::Part (first attachment)
#
def attachments
- @_message.attachments
+ if @_mail_was_called
+ LateAttachmentsProxy.new(@_message.attachments)
+ else
+ @_message.attachments
+ end
+ end
+
+ class LateAttachmentsProxy < SimpleDelegator
+ def inline; _raise_error end
+ def []=(_name, _content); _raise_error end
+
+ private
+ def _raise_error
+ raise RuntimeError, "Can't add attachments after `mail` was called.\n" \
+ "Make sure to use `attachments[]=` before calling `mail`."
+ end
end
# The main method that creates the message and renders the email templates. There are
@@ -745,7 +775,6 @@ module ActionMailer
def mail(headers = {}, &block)
return @_message if @_mail_was_called && headers.blank? && !block
- @_mail_was_called = true
m = @_message
# At the beginning, do not consider class default for content_type
@@ -773,6 +802,8 @@ module ActionMailer
# Render the templates and blocks
responses = collect_responses(headers, &block)
+ @_mail_was_called = true
+
create_parts_from_responses(m, responses)
# Setup content type, reapply charset and handle parts order
@@ -882,6 +913,11 @@ module ActionMailer
container.add_part(part)
end
+ # Emails do not support relative path links.
+ def self.supports_path?
+ false
+ end
+
ActiveSupport.run_load_hooks(:action_mailer, self)
end
end