diff options
Diffstat (limited to 'actionmailer')
28 files changed, 316 insertions, 509 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 57af4ee6a4..ed8ee89617 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,449 +1,25 @@ -## Rails 3.1.0 (August 30, 2011) ## +## Rails 4.0.0 (unreleased) ## -* No changes +* Allow delivery method options to be set per mail instance *Aditya Sanghi* + If your smtp delivery settings are dynamic, + you can now override settings per mail instance for e.g. -## Rails 3.0.7 (April 18, 2011) ## + def my_mailer(user,company) + mail to: user.email, subject: "Welcome!", + delivery_method_options: {user_name: company.smtp_user, + password: company.smtp_password} + end -* remove AM delegating register_observer and register_interceptor to Mail *Josh Kalderimis* + This will ensure that your default SMTP settings will be overridden + by the company specific ones. You only have to override the settings + that are dynamic and leave the static setting in your environment + configuration file (e.g. config/environments/production.rb) +* Allow to set default Action Mailer options via `config.action_mailer.default_options=` *Robert Pankowecki* -* Rails 3.0.6 (April 5, 2011) +* Raise an `ActionView::MissingTemplate` exception when no implicit template could be found. *Damien Mathieu* -* Don't allow i18n to change the minor version, version now set to ~> 0.5.0 *Santiago Pastorino* +* Asynchronously send messages via the Rails Queue *Brian Cardarella* - -## Rails 3.0.5 (February 26, 2011) ## - -* No changes. - - -## Rails 3.0.4 (February 8, 2011) ## - -* No changes. - - -## Rails 3.0.3 (November 16, 2010) ## - -* No changes. - - -## Rails 3.0.2 (November 15, 2010) ## - -* No changes - - -## Rails 3.0.1 (October 15, 2010) ## - -* No Changes, just a version bump. - - -## Rails 3.0.0 (August 29, 2010) ## - -* subject is automatically looked up on I18n using mailer_name and action_name as scope as in t(".subject") *JK* - -* Changed encoding behaviour of mail, so updated tests in actionmailer and bumped mail version to 2.2.1 *ML* - -* Added ability to pass Proc objects to the defaults hash *ML* - -* Removed all quoting.rb type files from ActionMailer and put Mail 2.2.0 in instead *ML* - -* Lot of updates to various test cases that now work better with the new Mail and so have different expectations - -* Added interceptors and observers from Mail *ML* - - ActionMailer::Base.register_interceptor calls Mail.register_interceptor - ActionMailer::Base.register_observer calls Mail.register_observer - -* Mail::Part now no longer has nil as a default charset, it is always set to something, and defaults to UTF-8 - -* Added explict setting of charset in set_fields! method to make sure Mail has the user defined default - -* Removed quoting.rb and refactored for Mail to take responsibility of all quoting and auto encoding requirements for the header. - -* Fixed several tests which had incorrect encoding. - -* Changed all utf-8 to UTF-8 for consistency - -* Whole new API added with tests. See base.rb for full details. Old API is deprecated. - -* The Mail::Message class has helped methods for all the field types that return 'common' defaults for the common use case, so to get the subject, mail.subject will give you a string, mail.date will give you a DateTime object, mail.from will give you an array of address specs (mikel@test.lindsaar.net) etc. If you want to access the field object itself, call mail[:field_name] which will return the field object you want, which you can then chain, like mail[:from].formatted - -* Mail#content_type now returns the content_type field as a string. If you want the mime type of a mail, then you call Mail#mime_type (eg, text/plain), if you want the parameters of the content type field, you call Mail#content_type_parameters which gives you a hash, eg {'format' => 'flowed', 'charset' => 'utf-8'} - -* ActionMailer::Base :default_implicit_parts_order now is in the sequence of the order you want, no reversing of ordering takes place. The default order now is text/plain, then text/enriched, then text/html and then any other part that is not one of these three. - -* Mail does not have "quoted_body", "quoted_subject" etc. All of these are accessed via body.encoded, subject.encoded etc - -* Every object in a Mail object returns an object, never a string. So Mail.body returns a Mail::Body class object, need to call #encoded or #decoded to get the string you want. -* Mail::Message#set_content_type does not exist, it is simply Mail::Message#content_type - -* Every mail message gets a unique message_id unless you specify one, had to change all the tests that check for equality with expected.encoded == actual.encoded to first replace their message_ids with control values - -* Mail now has a proper concept of parts, remove the ActionMailer::Part and ActionMailer::PartContainer classes - -* Calling #encoded on any object returns it as a string ready to go into the output stream of an email, this means it includes the \r\n at the end of the lines and the object is pre-wrapped with \r\n\t if it is a header field. Also, the "encoded" value includes the field name if it is a header field. - -* Attachments are only the actual attachment, with filename etc. A part contains an attachment. The part has the content_type etc. So attachments.last.content_type is invalid. But parts.last.content_type - -* There is no idea of a "sub_head" in Mail. A part is just a Message with some extra functionality, so it just has a "header" like a normal mail message - - -## 2.3.2 Final (March 15, 2009) ## - -* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 *Matt Jones* - -* Fixed RFC-2045 quoted-printable bug #1421 *squadette* - -* Fixed that no body charset would be set when there are attachments present #740 *Paweł Kondzior* - - -## 2.2.1 RC2 (November 14th, 2008) ## - -* Turn on STARTTLS if it is available in Net::SMTP (added in Ruby 1.8.7) and the SMTP server supports it (This is required for Gmail's SMTP server) #1336 *Grant Hollingworth* - - -## 2.2.0 RC1 (October 24th, 2008) ## - -* Add layout functionality to mailers *Pratik Naik* - - Mailer layouts behaves just like controller layouts, except layout names need to - have '_mailer' postfix for them to be automatically picked up. - - -## 2.1.0 (May 31st, 2008) ## - -* Fixed that a return-path header would be ignored #7572 *joost* - -* Less verbose mail logging: just recipients for :info log level; the whole email for :debug only. #8000 *iaddict, Tarmo Tänav* - -* Updated TMail to version 1.2.1 *Mikel Lindsaar* - -* Fixed that you don't have to call super in ActionMailer::TestCase#setup #10406 *jamesgolick* - - -## 2.0.2 (December 16th, 2007) ## - -* Included in Rails 2.0.2 - - -## 2.0.1 (December 7th, 2007) ## - -* Update ActionMailer so it treats ActionView the same way that ActionController does. Closes #10244 *Rick Olson* - - * Pass the template_root as an array as ActionView's view_path - * Request templates with the "#{mailer_name}/#{action}" as opposed to just "#{action}" - -* Fixed that partials would be broken when using text.plain.erb as the extension #10130 *java* - -* Update README to use new smtp settings configuration API. Closes #10060 *psq* - -* Allow ActionMailer subclasses to individually set their delivery method (so two subclasses can have different delivery methods) #10033 *Zach Dennis* - -* Update TMail to v1.1.0. Use an updated version of TMail if available. *Mikel Lindsaar* - -* Introduce a new base test class for testing Mailers. ActionMailer::TestCase *Michael Koziarski* - -* Fix silent failure of rxml templates. #9879 *jstewart* - -* Fix attachment decoding when using the TMail C extension. #7861 *orangechicken* - -* Increase mail delivery test coverage. #8692 *Kamal Fariz Mahyuddin* - -* Register alternative template engines using ActionMailer::Base.register_template_extension('haml'). #7534 *cwd, Josh Peek* - -* Only load ActionController::UrlWriter if ActionController is present *Rick Olson* - -* Make sure parsed emails recognized attachments nested inside multipart parts. #6714 *Jamis Buck* - -* Allow mailer actions named send by using __send__ internally. #6467 *iGEL* - -* Add assert_emails and assert_no_emails to test the number of emails delivered. #6479 *Jonathan Viney* - # Assert total number of emails delivered: - assert_emails 0 - ContactMailer.deliver_contact - assert_emails 1 - - # Assert number of emails delivered within a block: - assert_emails 1 do - post :signup, :name => 'Jonathan' - end - - -## 1.3.3 (March 12th, 2007) ## - -* Depend on Action Pack 1.13.3 - - -## 1.3.2 (February 5th, 2007) ## - -* Deprecate server_settings renaming it to smtp_settings, add sendmail_settings to allow you to override the arguments to and location of the sendmail executable. *Michael Koziarski* - - -## 1.3.1 (January 16th, 2007) ## - -* Depend on Action Pack 1.13.1 - - -## 1.3.0 (January 16th, 2007) ## - -* Make mime version default to 1.0. closes #2323 *ror@andreas-s.net* - -* Make sure quoted-printable text is decoded correctly when only portions of the text are encoded. closes #3154. *jon@siliconcircus.com* - -* Make sure DOS newlines in quoted-printable text are normalized to unix newlines before unquoting. closes #4166 and #4452. *Jamis Buck* - -* Fixed that iconv decoding should catch InvalidEncoding #3153 *jon@siliconcircus.com* - -* Tighten rescue clauses. #5985 *james@grayproductions.net* - -* Automatically included ActionController::UrlWriter, such that URL generation can happen within ActionMailer controllers. *David Heinemeier Hansson* - -* Replace Reloadable with Reloadable::Deprecated. *Nicholas Seckar* - -* Mailer template root applies to a class and its subclasses rather than acting globally. #5555 *somekool@gmail.com* - -* Resolve action naming collision. #5520 *ssinghi@kreeti.com* - -* ActionMailer::Base documentation rewrite. Closes #4991 *Kevin Clark, Marcel Molina Jr.* - -* Replace alias method chaining with Module#alias_method_chain. *Marcel Molina Jr.* - -* Replace Ruby's deprecated append_features in favor of included. *Marcel Molina Jr.* - -* Correct spurious documentation example code which results in a SyntaxError. *Marcel Molina Jr.* - - -## 1.2.1 (April 6th, 2006) ## - -* Be part of Rails 1.1.1 - - -## 1.2.0 (March 27th, 2006) ## - -* Nil charset caused subject line to be improperly quoted in implicitly multipart messages #2662 *ehalvorsen+rails@runbox.com* - -* Parse content-type apart before using it so that sub-parts of the header can be set correctly #2918 *Jamis Buck* - -* Make custom headers work in subparts #4034 *elan@bluemandrill.com* - -* Template paths with dot chars in them no longer mess up implicit template selection for multipart messages #3332 *Chad Fowler* - -* Make sure anything with content-disposition of "attachment" is passed to the attachment presenter when parsing an email body *Jamis Buck* - -* Make sure TMail#attachments includes anything with content-disposition of "attachment", regardless of content-type *Jamis Buck* - - -## 1.1.5 (December 13th, 2005) ## - -* Become part of Rails 1.0 - - -## 1.1.4 (December 7th, 2005) ## - -* Rename Version constant to VERSION. #2802 *Marcel Molina Jr.* - -* Stricter matching for implicitly multipart filenames excludes files ending in unsupported extensions (such as foo.rhtml.bak) and without a two-part content type (such as foo.text.rhtml or foo.text.really.plain.rhtml). #2398 *Dave Burt <dave@burt.id.au>, Jeremy Kemper* - - -## 1.1.3 (November 7th, 2005) ## - -* Allow Mailers to have custom initialize methods that set default instance variables for all mail actions #2563 *mrj@bigpond.net.au* - - -## 1.1.2 (October 26th, 2005) ## - -* Upgraded to Action Pack 1.10.2 - - -## 1.1.1 (October 19th, 2005) ## - -* Upgraded to Action Pack 1.10.1 - - -## 1.1.0 (October 16th, 2005) ## - -* Update and extend documentation (rdoc) - -* Minero Aoki made TMail available to Rails/ActionMailer under the MIT license (instead of LGPL) *RubyConf '05* - -* Austin Ziegler made Text::Simple available to Rails/ActionMailer under a MIT-like licens *See rails ML, subject "Text::Format Licence Exception" on Oct 15, 2005* - -* Fix vendor require paths to prevent files being required twice - -* Don't add charset to content-type header for a part that contains subparts (for AOL compatibility) #2013 *John Long* - -* Preserve underscores when unquoting message bodies #1930 - -* Encode multibyte characters correctly #1894 - -* Multipart messages specify a MIME-Version header automatically #2003 *John Long* - -* Add a unified render method to ActionMailer (delegates to ActionView::Base#render) - -* Move mailer initialization to a separate (overridable) method, so that subclasses may alter the various defaults #1727 - -* Look at content-location header (if available) to determine filename of attachments #1670 - -* ActionMailer::Base.deliver(email) had been accidentally removed, but was documented in the Rails book #1849 - -* Fix problem with sendmail delivery where headers should be delimited by \n characters instead of \r\n, which confuses some mail readers #1742 *Kent Sibilev* - - -## 1.0.1 (11 July, 2005) ## - -* Bind to Action Pack 1.9.1 - - -## 1.0.0 (6 July, 2005) ## - -* Avoid adding nil header values #1392 - -* Better multipart support with implicit multipart/alternative and sorting of subparts *John Long* - -* Allow for nested parts in multipart mails #1570 *Flurin Egger* - -* Normalize line endings in outgoing mail bodies to "\n" #1536 *John Long* - -* Allow template to be explicitly specified #1448 *tuxie@dekadance.se* - -* Allow specific "multipart/xxx" content-type to be set on multipart messages #1412 *Flurin Egger* - -* Unquoted @ characters in headers are now accepted in spite of RFC 822 #1206 - -* Helper support (borrowed from ActionPack) - -* Silently ignore Errno::EINVAL errors when converting text. - -* Don't cause an error when parsing an encoded attachment name #1340 *lon@speedymac.com* - -* Nested multipart message parts are correctly processed in TMail::Mail#body - -* BCC headers are removed when sending via SMTP #1402 - -* Added 'content_type' accessor, to allow content type to be set on a per-message basis. content_type defaults to "text/plain". - -* Silently ignore Iconv::IllegalSequence errors when converting text #1341 *lon@speedymac.com* - -* Support attachments and multipart messages. - -* Added new accessors for the various mail properties. - -* Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 *Jamis Buck* - -* Fix attachments and content-type problems #1276 *Jamis Buck* - -* Fixed the TMail#body method to look at the content-transfer-encoding header and unquote the body according to the rules it specifies #1265 *Jamis Buck* - -* Added unquoting even if the iconv lib can't be loaded--in that case, only the charset conversion is skipped #1265 *Jamis Buck* - -* Added automatic decoding of base64 bodies #1214 *Jamis Buck* - -* Added that delivery errors are caught in a way so the mail is still returned whether the delivery was successful or not - -* Fixed that email address like "Jamis Buck, M.D." <wild.medicine@example.net> would cause the quoter to generate emails resulting in "bad address" errors from the mail server #1220 *Jamis Buck* - - -## 0.9.1 (20th April, 2005) ## - -* Depend on Action Pack 1.8.1 - - -## 0.9.0 (19th April, 2005) ## - -* Added that deliver_* will now return the email that was sent - -* Added that quoting to UTF-8 only happens if the characters used are in that range #955 *Jamis Buck* - -* Fixed quoting for all address headers, not just to #955 *Jamis Buck* - -* Fixed unquoting of emails that doesn't have an explicit charset #1036 *wolfgang@stufenlos.net* - - -## 0.8.1 (27th March, 2005) ## - -* Fixed that if charset was found that the end of a mime part declaration TMail would throw an error #919 *lon@speedymac.com* - -* Fixed that TMail::Unquoter would fail to recognize quoting method if it was in lowercase #919 *lon@speedymac.com* - -* Fixed that TMail::Encoder would fail when it attempts to parse e-mail addresses which are encoded using something other than the messages encoding method #919 *lon@speedymac.com* - -* Added rescue for missing iconv library and throws warnings if subject/body is called on a TMail object without it instead - - -## 0.8.0 (22th March, 2005) ## - -* Added framework support for processing incoming emails with an Action Mailer class. See example in README. - - -## 0.7.1 (7th March, 2005) ## - -* Bind to newest Action Pack (1.5.1) - - -## 0.7.0 (24th February, 2005) ## - -* Added support for charsets for both subject and body. The default charset is now UTF-8 #673 [Jamis Buck]. Examples: - - def iso_charset(recipient) - @recipients = recipient - @subject = "testing iso charsets" - @from = "system@loudthinking.com" - @body = "Nothing to see here." - @charset = "iso-8859-1" - end - - def unencoded_subject(recipient) - @recipients = recipient - @subject = "testing unencoded subject" - @from = "system@loudthinking.com" - @body = "Nothing to see here." - @encode_subject = false - @charset = "iso-8859-1" - end - - -## 0.6.1 (January 18th, 2005) ## - -* Fixed sending of emails to use Tmail#from not the deprecated Tmail#from_address - - -## 0.6 (January 17th, 2005) ## - -* Fixed that bcc and cc should be settable through @bcc and @cc -- not just @headers["Bcc"] and @headers["Cc"] #453 *Eric Hodel* - -* Fixed Action Mailer to be "warnings safe" so you can run with ruby -w and not get framework warnings #453 *Eric Hodel* - - -## 0.5 ## - -* Added access to custom headers, like cc, bcc, and reply-to #268 [Andreas Schwarz]. Example: - - def post_notification(recipients, post) - @recipients = recipients - @from = post.author.email_address_with_name - @headers["bcc"] = SYSTEM_ADMINISTRATOR_EMAIL - @headers["reply-to"] = "notifications@example.com" - @subject = "[#{post.account.name} #{post.title}]" - @body["post"] = post - end - -## 0.4 (5) ## - -* Consolidated the server configuration options into Base#server_settings= and expanded that with controls for authentication and more *Marten* - NOTE: This is an API change that could potentially break your application if you used the old application form. Please do change! - -* Added Base#deliveries as an accessor for an array of emails sent out through that ActionMailer class when using the :test delivery option. *Jeremy Kemper* - -* Added Base#perform_deliveries= which can be set to false to turn off the actual delivery of the email through smtp or sendmail. - This is especially useful for functional testing that shouldn't send off real emails, but still trigger delivery_* methods. - -* Added option to specify delivery method with Base#delivery_method=. Default is :smtp and :sendmail is currently the only other option. - Sendmail is assumed to be present at "/usr/sbin/sendmail" if that option is used. *Kent Sibilev* - -* Dropped "include TMail" as it added to much baggage into the default namespace (like Version) *Chad Fowler* - - -## 0.3 ## - -* First release +Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/actionmailer/CHANGELOG.md) for previous changes. diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc index 755717cfba..cf10bfffdb 100644 --- a/actionmailer/README.rdoc +++ b/actionmailer/README.rdoc @@ -22,12 +22,12 @@ the email. This can be as simple as: class Notifier < ActionMailer::Base - delivers_from 'system@loudthinking.com' + default from: 'system@loudthinking.com' def welcome(recipient) @recipient = recipient - mail(:to => recipient, - :subject => "[Signed up] Welcome #{recipient}") + mail(to: recipient, + subject: "[Signed up] Welcome #{recipient}") end end diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index 8f5aeb9603..c1c4171cdf 100755..100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -1,4 +1,3 @@ -#!/usr/bin/env rake require 'rake/testtask' require 'rake/packagetask' require 'rubygems/package_task' diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index c605f1ff04..0c669e2e91 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -7,6 +7,7 @@ Gem::Specification.new do |s| s.summary = 'Email composition, delivery, and receiving framework (part of Rails).' s.description = 'Email on Rails. Compose, deliver, receive, and test emails using the familiar controller/view pattern. First-class support for multipart email and attachments.' s.required_ruby_version = '>= 1.9.3' + s.license = 'MIT' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' @@ -17,5 +18,5 @@ Gem::Specification.new do |s| s.requirements << 'none' s.add_dependency('actionpack', version) - s.add_dependency('mail', '~> 2.4.1') + s.add_dependency('mail', '~> 2.4.4') end diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 1045dd58ef..cfbe2f1cbd 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -21,25 +21,24 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -actionpack_path = File.expand_path('../../../actionpack/lib', __FILE__) -$:.unshift(actionpack_path) if File.directory?(actionpack_path) && !$:.include?(actionpack_path) - require 'abstract_controller' require 'action_view' require 'action_mailer/version' # Common Active Support usage in Action Mailer +require 'active_support/rails' require 'active_support/core_ext/class' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/module/attr_internal' -require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/string/inflections' require 'active_support/lazy_load_hooks' module ActionMailer extend ::ActiveSupport::Autoload - autoload :Collector + eager_autoload do + autoload :Collector + end + autoload :Base autoload :DeliveryMethods autoload :MailHelper diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 1800ff5839..a96cbd7871 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -1,8 +1,10 @@ require 'mail' +require 'action_mailer/queued_message' require 'action_mailer/collector' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/module/anonymous' +require 'active_support/queueing' require 'action_mailer/log_subscriber' module ActionMailer #:nodoc: @@ -14,15 +16,15 @@ module ActionMailer #:nodoc: # # $ rails generate mailer Notifier # - # The generated model inherits from <tt>ActionMailer::Base</tt>. Emails are defined by creating methods - # within the model which are then used to set variables to be used in the mail template, to - # change options on the mail, or to add attachments. + # The generated model inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods + # used to generate an email message. In these methods, you can setup variables to be used in + # the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments. # # Examples: # # class Notifier < ActionMailer::Base # default :from => 'no-reply@example.com', - # :return_path => 'system@example.com' + # :return_path => 'system@example.com' # # def welcome(recipient) # @account = recipient @@ -183,6 +185,16 @@ module ActionMailer #:nodoc: # and the second being a <tt>application/pdf</tt> with a Base64 encoded copy of the file.pdf book # with the filename +free_book.pdf+. # + # If you need to send attachments with no content, you need to create an empty view for it, + # or add an empty body parameter like this: + # + # class ApplicationMailer < ActionMailer::Base + # def welcome(recipient) + # attachments['free_book.pdf'] = File.read('path/to/file.pdf') + # mail(:to => recipient, :subject => "New account information", :body => "") + # end + # end + # # = Inline Attachments # # You can also specify that a file should be displayed inline with other HTML. This is useful @@ -267,6 +279,38 @@ module ActionMailer #:nodoc: # set something in the defaults using a proc, and then set the same thing inside of your # mailer method, it will get over written by the mailer method. # + # It is also possible to set these default options that will be used in all mailers through + # the <tt>default_options=</tt> configuration in <tt>config/application.rb</tt>: + # + # config.action_mailer.default_options = { from: "no-reply@example.org" } + # + # = Callbacks + # + # You can specify callbacks using before_filter and after_filter for configuring your messages. + # This may be useful, for example, when you want to add default inline attachments for all + # messages sent out by a certain mailer class: + # + # class Notifier < ActionMailer::Base + # before_filter :add_inline_attachment! + # + # def welcome + # mail + # end + # + # private + # + # def add_inline_attachment! + # attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg') + # end + # end + # + # Callbacks in ActionMailer are implemented using AbstractController::Callbacks, so you + # can define and configure callbacks in the same manner that you would use callbacks in + # classes that inherit from ActionController::Base. + # + # Note that unless you have a specific reason to do so, you should prefer using before_filter + # rather than after_filter in your ActionMailer classes so that headers are parsed properly. + # # = Configuration options # # These options are specified on the class level, like @@ -310,7 +354,7 @@ module ActionMailer #:nodoc: # # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), # <tt>:sendmail</tt>, <tt>:test</tt>, and <tt>:file</tt>. Or you may provide a custom delivery method - # object eg. MyOwnDeliveryMethodClass.new. See the Mail gem documentation on the interface you need to + # object e.g. MyOwnDeliveryMethodClass. See the Mail gem documentation on the interface you need to # implement for a custom delivery agent. # # * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you @@ -320,6 +364,9 @@ module ActionMailer #:nodoc: # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with # <tt>delivery_method :test</tt>. Most useful for unit and functional testing. # + # * <tt>queue</> - The queue that will be used to deliver the mail. The queue should expect a job that + # responds to <tt>run</tt> + # class Base < AbstractController::Base include DeliveryMethods abstract! @@ -330,10 +377,11 @@ module ActionMailer #:nodoc: include AbstractController::Helpers include AbstractController::Translation include AbstractController::AssetPaths + include AbstractController::Callbacks self.protected_instance_variables = [:@_action_has_layout] - helper ActionMailer::MailHelper + helper ActionMailer::MailHelper private_class_method :new #:nodoc: @@ -345,6 +393,9 @@ module ActionMailer #:nodoc: :parts_order => [ "text/plain", "text/enriched", "text/html" ] }.freeze + class_attribute :queue + self.queue = ActiveSupport::SynchronousQueue.new + class << self # Register one or more Observers which will be notified when mail is delivered. def register_observers(*observers) @@ -373,7 +424,7 @@ module ActionMailer #:nodoc: end def mailer_name - @mailer_name ||= name.underscore + @mailer_name ||= anonymous? ? "anonymous" : name.underscore end attr_writer :mailer_name alias :controller_path :mailer_name @@ -382,6 +433,10 @@ module ActionMailer #:nodoc: self.default_params = default_params.merge(value).freeze if value default_params end + # Allows to set defaults through app configuration: + # + # config.action_mailer.default_options = { from: "no-reply@example.org" } + alias :default_options= :default # Receives a raw email, parses it into an email object, decodes it, # instantiates a new mailer, and passes the email object to the mailer @@ -431,9 +486,12 @@ module ActionMailer #:nodoc: payload[:mail] = mail.encoded end - def method_missing(method, *args) #:nodoc: - return super unless respond_to?(method) - new(method, *args).message + def method_missing(method_name, *args) + if action_methods.include?(method_name.to_s) + QueuedMessage.new(queue, self, method_name, *args) + else + super + end end end @@ -458,7 +516,7 @@ module ActionMailer #:nodoc: self.class.mailer_name end - # Allows you to pass random and unusual headers to the new +Mail::Message+ object + # Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> object # which will add them to itself. # # headers['X-Special-Domain-Specific-Header'] = "SecretValue" @@ -469,7 +527,7 @@ module ActionMailer #:nodoc: # headers 'X-Special-Domain-Specific-Header' => "SecretValue", # 'In-Reply-To' => incoming.message_id # - # The resulting Mail::Message will have the following in it's header: + # The resulting Mail::Message will have the following in its header: # # X-Special-Domain-Specific-Header: SecretValue def headers(args=nil) @@ -569,8 +627,10 @@ module ActionMailer #:nodoc: # end # end # - # Will look for all templates at "app/views/notifier" with name "welcome". However, those - # can be customized: + # Will look for all templates at "app/views/notifier" with name "welcome". + # If no welcome template exists, it will raise an ActionView::MissingTemplate error. + # + # However, those can be customized: # # mail(:template_path => 'notifications', :template_name => 'another') # @@ -621,7 +681,7 @@ module ActionMailer #:nodoc: m.charset = charset = headers[:charset] # Set configure delivery behavior - wrap_delivery_behavior!(headers.delete(:delivery_method)) + wrap_delivery_behavior!(headers.delete(:delivery_method),headers.delete(:delivery_method_options)) # Assign all headers except parts_order, content_type and body assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path) @@ -668,7 +728,7 @@ module ActionMailer #:nodoc: # If it does not find a translation for the +subject+ under the specified scope it will default to a # humanized version of the <tt>action_name</tt>. def default_i18n_subject #:nodoc: - mailer_scope = self.class.mailer_name.gsub('/', '.') + mailer_scope = self.class.mailer_name.tr('/', '.') I18n.t(:subject, :scope => [mailer_scope, action_name], :default => action_name.humanize) end @@ -694,7 +754,7 @@ module ActionMailer #:nodoc: responses << { :body => render(:template => template), - :content_type => template.mime_type.to_s + :content_type => template.type.to_s } end end @@ -704,7 +764,11 @@ module ActionMailer #:nodoc: def each_template(paths, name, &block) #:nodoc: templates = lookup_context.find_all(name, Array(paths)) - templates.uniq { |t| t.formats }.each(&block) + if templates.empty? + raise ActionView::MissingTemplate.new([paths], name, [paths], false, 'mailer') + else + templates.uniq { |t| t.formats }.each(&block) + end end def create_parts_from_responses(m, responses) #:nodoc: @@ -729,4 +793,3 @@ module ActionMailer #:nodoc: ActiveSupport.run_load_hooks(:action_mailer, self) end end - diff --git a/actionmailer/lib/action_mailer/collector.rb b/actionmailer/lib/action_mailer/collector.rb index 17b22aea2a..b8d1db9558 100644 --- a/actionmailer/lib/action_mailer/collector.rb +++ b/actionmailer/lib/action_mailer/collector.rb @@ -15,7 +15,7 @@ module ActionMailer #:nodoc: def any(*args, &block) options = args.extract_options! - raise "You have to supply at least one format" if args.empty? + raise ArgumentError, "You have to supply at least one format" if args.empty? args.each { |type| send(type, options.dup, &block) } end alias :all :any diff --git a/actionmailer/lib/action_mailer/delivery_methods.rb b/actionmailer/lib/action_mailer/delivery_methods.rb index d1467fb526..b795d4f80a 100644 --- a/actionmailer/lib/action_mailer/delivery_methods.rb +++ b/actionmailer/lib/action_mailer/delivery_methods.rb @@ -57,7 +57,7 @@ module ActionMailer self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze end - def wrap_delivery_behavior(mail, method=nil) #:nodoc: + def wrap_delivery_behavior(mail, method=nil, options=nil) #:nodoc: method ||= self.delivery_method mail.delivery_handler = self @@ -65,8 +65,8 @@ module ActionMailer when NilClass raise "Delivery method cannot be nil" when Symbol - if klass = delivery_methods[method.to_sym] - mail.delivery_method(klass, send(:"#{method}_settings")) + if klass = delivery_methods[method] + mail.delivery_method(klass,(send(:"#{method}_settings") || {}).merge!(options || {})) else raise "Invalid delivery method #{method.inspect}" end diff --git a/actionmailer/lib/action_mailer/queued_message.rb b/actionmailer/lib/action_mailer/queued_message.rb new file mode 100644 index 0000000000..8d200617c4 --- /dev/null +++ b/actionmailer/lib/action_mailer/queued_message.rb @@ -0,0 +1,37 @@ +require 'delegate' + +module ActionMailer + class QueuedMessage < ::Delegator + attr_reader :queue + + def initialize(queue, mailer_class, method_name, *args) + @queue = queue + @job = DeliveryJob.new(mailer_class, method_name, args) + end + + def __getobj__ + @job.message + end + + # Queues the message for delivery. + def deliver + tap { @queue.push @job } + end + + class DeliveryJob + def initialize(mailer_class, method_name, args) + @mailer_class = mailer_class + @method_name = method_name + @args = args + end + + def message + @message ||= @mailer_class.send(:new, @method_name, *@args).message + end + + def run + message.deliver + end + end + end +end diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 5c03a29f0f..1fa689de5b 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -5,6 +5,7 @@ require "abstract_controller/railties/routes_helpers" module ActionMailer class Railtie < Rails::Railtie config.action_mailer = ActiveSupport::OrderedOptions.new + config.eager_load_namespaces << ActionMailer initializer "action_mailer.logger" do ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger } @@ -18,6 +19,8 @@ module ActionMailer options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first + options.queue ||= app.queue + # make sure readers methods get compiled options.asset_path ||= app.config.asset_path options.asset_host ||= app.config.asset_host diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index 529140dfad..108969ed4c 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -1,5 +1,4 @@ require 'active_support/test_case' -require 'active_support/core_ext/class/attribute' module ActionMailer class NonInferrableMailerError < ::StandardError diff --git a/actionmailer/lib/rails/generators/mailer/templates/mailer.rb b/actionmailer/lib/rails/generators/mailer/templates/mailer.rb index aaa1f79732..edcfb4233d 100644 --- a/actionmailer/lib/rails/generators/mailer/templates/mailer.rb +++ b/actionmailer/lib/rails/generators/mailer/templates/mailer.rb @@ -1,17 +1,17 @@ <% module_namespacing do -%> class <%= class_name %> < ActionMailer::Base - default <%= key_value :from, '"from@example.com"' %> + default from: "from@example.com" <% actions.each do |action| -%> # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # - # en.<%= file_path.gsub("/",".") %>.<%= action %>.subject + # en.<%= file_path.tr("/",".") %>.<%= action %>.subject # def <%= action %> @greeting = "Hi" - mail <%= key_value :to, '"to@example.org"' %> + mail to: "to@example.org" end <% end -%> end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 3a519253f9..4b38d4bd31 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -1,16 +1,4 @@ -# Pathname has a warning, so require it first while silencing -# warnings to shut it up. -# -# Also, in 1.9, Bundler creates warnings due to overriding -# Rubygems methods -begin - old, $VERBOSE = $VERBOSE, nil - require 'pathname' - require File.expand_path('../../../load_paths', __FILE__) -ensure - $VERBOSE = old -end - +require File.expand_path('../../../load_paths', __FILE__) require 'active_support/core_ext/kernel/reporting' # These are the normal settings that will be set up by Railties @@ -20,12 +8,10 @@ silence_warnings do Encoding.default_external = "UTF-8" end -lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) - require 'minitest/autorun' require 'action_mailer' require 'action_mailer/test_case' +require 'active_support/queueing' silence_warnings do # These external dependencies have warnings :/ diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 65550ab505..4f2af50fdd 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -1,10 +1,15 @@ # encoding: utf-8 require 'abstract_unit' +require 'set' + +require 'action_dispatch' +require 'active_support/queueing' require 'active_support/time' require 'mailers/base_mailer' require 'mailers/proc_mailer' require 'mailers/asset_mailer' +require 'mailers/async_mailer' class BaseTest < ActiveSupport::TestCase def teardown @@ -407,7 +412,7 @@ class BaseTest < ActiveSupport::TestCase BaseMailer.deliveries.clear BaseMailer.expects(:deliver_mail).once mail = BaseMailer.welcome.deliver - assert_instance_of Mail::Message, mail + assert_equal 'The first email on new API!', mail.subject end test "calling deliver on the action should increment the deliveries collection if using the test mailer" do @@ -417,6 +422,17 @@ class BaseTest < ActiveSupport::TestCase assert_equal(1, BaseMailer.deliveries.length) end + test "delivering message asynchronously" do + AsyncMailer.delivery_method = :test + AsyncMailer.deliveries.clear + + AsyncMailer.welcome.deliver + assert_equal 0, AsyncMailer.deliveries.length + + AsyncMailer.queue.drain + assert_equal 1, AsyncMailer.deliveries.length + end + test "calling deliver, ActionMailer should yield back to mail to let it call :do_delivery on itself" do mail = Mail::Message.new mail.expects(:do_delivery).once @@ -431,6 +447,14 @@ class BaseTest < ActiveSupport::TestCase assert_equal("TEXT Implicit Multipart", mail.text_part.body.decoded) end + test "should raise if missing template in implicit render" do + BaseMailer.deliveries.clear + assert_raises ActionView::MissingTemplate do + BaseMailer.implicit_different_template('missing_template').deliver + end + assert_equal(0, BaseMailer.deliveries.length) + end + test "you can specify a different template for explicit render" do mail = BaseMailer.explicit_different_template('explicit_multipart_templates').deliver assert_equal("HTML Explicit Multipart Templates", mail.html_part.body.decoded) @@ -461,14 +485,18 @@ class BaseTest < ActiveSupport::TestCase end test "assets tags should use a Mailer's asset_host settings when available" do - ActionMailer::Base.config.asset_host = "global.com" - ActionMailer::Base.config.assets_dir = "global/" + begin + ActionMailer::Base.config.asset_host = "http://global.com" + ActionMailer::Base.config.assets_dir = "global/" - AssetMailer.asset_host = "http://local.com" + AssetMailer.asset_host = "http://local.com" - mail = AssetMailer.welcome + mail = AssetMailer.welcome - assert_equal(%{<img alt="Dummy" src="http://local.com/images/dummy.png" />}, mail.body.to_s.strip) + assert_equal(%{<img alt="Dummy" src="http://local.com/images/dummy.png" />}, mail.body.to_s.strip) + ensure + AssetMailer.asset_host = ActionMailer::Base.config.asset_host + end end # Before and After hooks @@ -538,11 +566,11 @@ class BaseTest < ActiveSupport::TestCase end test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do - mail1 = ProcMailer.welcome + mail1 = ProcMailer.welcome['X-Proc-Method'] yesterday = 1.day.ago Time.stubs(:now).returns(yesterday) - mail2 = ProcMailer.welcome - assert(mail1['X-Proc-Method'].to_s.to_i > mail2['X-Proc-Method'].to_s.to_i) + mail2 = ProcMailer.welcome['X-Proc-Method'] + assert(mail1.to_s.to_i > mail2.to_s.to_i) end test "we can call other defined methods on the class as needed" do @@ -550,6 +578,52 @@ class BaseTest < ActiveSupport::TestCase assert_equal("Thanks for signing up this afternoon", mail.subject) end + test "modifying the mail message with a before_filter" do + class BeforeFilterMailer < ActionMailer::Base + before_filter :add_special_header! + + def welcome ; mail ; end + + private + def add_special_header! + headers('X-Special-Header' => 'Wow, so special') + end + end + + assert_equal('Wow, so special', BeforeFilterMailer.welcome['X-Special-Header'].to_s) + end + + test "modifying the mail message with an after_filter" do + class AfterFilterMailer < ActionMailer::Base + after_filter :add_special_header! + + def welcome ; mail ; end + + private + def add_special_header! + headers('X-Special-Header' => 'Testing') + end + end + + assert_equal('Testing', AfterFilterMailer.welcome['X-Special-Header'].to_s) + end + + test "adding an inline attachment using a before_filter" do + class DefaultInlineAttachmentMailer < ActionMailer::Base + before_filter :add_inline_attachment! + + def welcome ; mail ; end + + private + def add_inline_attachment! + attachments.inline["footer.jpg"] = 'hey there' + end + end + + mail = DefaultInlineAttachmentMailer.welcome + assert_equal('image/jpeg; filename=footer.jpg', mail.attachments.inline.first['Content-Type'].to_s) + end + test "action methods should be refreshed after defining new method" do class FooMailer < ActionMailer::Base # this triggers action_methods @@ -559,7 +633,33 @@ class BaseTest < ActiveSupport::TestCase end end - assert_equal ["notify"], FooMailer.action_methods + assert_equal Set.new(["notify"]), FooMailer.action_methods + end + + test "mailer can be anonymous" do + mailer = Class.new(ActionMailer::Base) do + def welcome + mail + end + end + + assert_equal "anonymous", mailer.mailer_name + + assert_equal "Welcome", mailer.welcome.subject + assert_equal "Anonymous mailer body", mailer.welcome.body.encoded.strip + end + + test "default_from can be set" do + class DefaultFromMailer < ActionMailer::Base + default :to => 'system@test.lindsaar.net' + self.default_options = {from: "robert.pankowecki@gmail.com"} + + def welcome + mail(subject: "subject", body: "hello world") + end + end + + assert_equal ["robert.pankowecki@gmail.com"], DefaultFromMailer.welcome.from end protected diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb index 08f84dbf3b..7109f23e4c 100644 --- a/actionmailer/test/delivery_methods_test.rb +++ b/actionmailer/test/delivery_methods_test.rb @@ -4,6 +4,13 @@ require 'mail' class MyCustomDelivery end +class MyOptionedDelivery + attr_reader :options + def initialize(options) + @options = options + end +end + class BogusDelivery def initialize(*) end @@ -115,6 +122,38 @@ class MailDeliveryTest < ActiveSupport::TestCase assert_instance_of Mail::TestMailer, email.delivery_method end + test "delivery method options default to class level options" do + default_options = {a: "b"} + ActionMailer::Base.add_delivery_method :optioned, MyOptionedDelivery, default_options + mail_instance = DeliveryMailer.welcome(:delivery_method => :optioned) + assert_equal default_options, mail_instance.delivery_method.options + end + + test "delivery method options can be overridden per mail instance" do + default_options = {a: "b"} + ActionMailer::Base.add_delivery_method :optioned, MyOptionedDelivery, default_options + overridden_options = {a: "a"} + mail_instance = DeliveryMailer.welcome(:delivery_method => :optioned, :delivery_method_options => overridden_options) + assert_equal overridden_options, mail_instance.delivery_method.options + end + + test "default delivery options can be overridden per mail instance" do + settings = { :address => "localhost", + :port => 25, + :domain => 'localhost.localdomain', + :user_name => nil, + :password => nil, + :authentication => nil, + :enable_starttls_auto => true } + assert_equal settings, ActionMailer::Base.smtp_settings + overridden_options = {user_name: "overridden", :password => "somethingobtuse"} + mail_instance = DeliveryMailer.welcome(:delivery_method_options => overridden_options) + delivery_method_instance = mail_instance.delivery_method + assert_equal "overridden", delivery_method_instance.settings[:user_name] + assert_equal "somethingobtuse", delivery_method_instance.settings[:password] + assert_equal delivery_method_instance.settings.merge(overridden_options), delivery_method_instance.settings + end + test "non registered delivery methods raises errors" do DeliveryMailer.delivery_method = :unknown assert_raise RuntimeError do diff --git a/actionmailer/test/fixtures/anonymous/welcome.erb b/actionmailer/test/fixtures/anonymous/welcome.erb new file mode 100644 index 0000000000..8361da62c4 --- /dev/null +++ b/actionmailer/test/fixtures/anonymous/welcome.erb @@ -0,0 +1 @@ +Anonymous mailer body diff --git a/actionmailer/test/fixtures/async_mailer/welcome.erb b/actionmailer/test/fixtures/async_mailer/welcome.erb new file mode 100644 index 0000000000..01f3f00c63 --- /dev/null +++ b/actionmailer/test/fixtures/async_mailer/welcome.erb @@ -0,0 +1 @@ +Welcome
\ No newline at end of file diff --git a/actionmailer/test/fixtures/base_mailer/attachment_with_hash.html.erb b/actionmailer/test/fixtures/base_mailer/attachment_with_hash.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_mailer/attachment_with_hash.html.erb diff --git a/actionmailer/test/fixtures/base_mailer/attachment_with_hash_default_encoding.html.erb b/actionmailer/test/fixtures/base_mailer/attachment_with_hash_default_encoding.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_mailer/attachment_with_hash_default_encoding.html.erb diff --git a/actionmailer/test/fixtures/base_mailer/welcome_with_headers.html.erb b/actionmailer/test/fixtures/base_mailer/welcome_with_headers.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_mailer/welcome_with_headers.html.erb diff --git a/actionmailer/test/fixtures/base_test/after_filter_mailer/welcome.html.erb b/actionmailer/test/fixtures/base_test/after_filter_mailer/welcome.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_test/after_filter_mailer/welcome.html.erb diff --git a/actionmailer/test/fixtures/base_test/before_filter_mailer/welcome.html.erb b/actionmailer/test/fixtures/base_test/before_filter_mailer/welcome.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_test/before_filter_mailer/welcome.html.erb diff --git a/actionmailer/test/fixtures/base_test/default_inline_attachment_mailer/welcome.html.erb b/actionmailer/test/fixtures/base_test/default_inline_attachment_mailer/welcome.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/base_test/default_inline_attachment_mailer/welcome.html.erb diff --git a/actionmailer/test/fixtures/mail_delivery_test/delivery_mailer/welcome.html.erb b/actionmailer/test/fixtures/mail_delivery_test/delivery_mailer/welcome.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/mail_delivery_test/delivery_mailer/welcome.html.erb diff --git a/actionmailer/test/fixtures/proc_mailer/welcome.html.erb b/actionmailer/test/fixtures/proc_mailer/welcome.html.erb new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/actionmailer/test/fixtures/proc_mailer/welcome.html.erb diff --git a/actionmailer/test/i18n_with_controller_test.rb b/actionmailer/test/i18n_with_controller_test.rb index 7040ae6f8d..68ed86e0d4 100644 --- a/actionmailer/test/i18n_with_controller_test.rb +++ b/actionmailer/test/i18n_with_controller_test.rb @@ -24,7 +24,7 @@ end class ActionMailerI18nWithControllerTest < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new Routes.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end def app diff --git a/actionmailer/test/mailers/async_mailer.rb b/actionmailer/test/mailers/async_mailer.rb new file mode 100644 index 0000000000..c21a464f38 --- /dev/null +++ b/actionmailer/test/mailers/async_mailer.rb @@ -0,0 +1,3 @@ +class AsyncMailer < BaseMailer + self.queue = ActiveSupport::TestQueue.new +end diff --git a/actionmailer/test/url_test.rb b/actionmailer/test/url_test.rb index 0536e83098..2ea1723434 100644 --- a/actionmailer/test/url_test.rb +++ b/actionmailer/test/url_test.rb @@ -57,8 +57,8 @@ class ActionMailerUrlTest < ActionMailer::TestCase UrlTestMailer.delivery_method = :test AppRoutes.draw do - match ':controller(/:action(/:id))' - match '/welcome' => "foo#bar", :as => "welcome" + get ':controller(/:action(/:id))' + get '/welcome' => "foo#bar", :as => "welcome" end expected = new_mail |