Chapter 10. Mailers

Many applications need to send email. Merb Mailers allow you to do this easily with the same controller and view conventions the rest of your application follows. The Mailer class is thus a subclass of AbstractController, and the relevant templates are standardly placed in app/mailers/views. In this chapter we’ll configure, generate, describe, and test mailers used in Merb applications.

10.1 Configuration

If you don’t configure Merb otherwise, it tries to use SMTP locally when asked to deliver mail. In most cases these exact defaults do not suffice, but alternative configurations are as simple as a few extra lines in either config/init.rb or one of the environment config files in a before_app_loads block. Below we describe the various configuration options available, separated by delivery method.

10.1.1 SMTP

Though SMTP is the default for the Merb Mailer, chances are you’ll need to configure it more explicitly. This may involve specifying the host, port, user, password, authentication method, and HELO domain. Below we do this by setting various hash values for Merb::Mailer.config.

image

Note that if you are using the Gmail SMTP servers or some other TLS-required SMTP service, you will need Anatol Pomozov’s gem smtp_tls in order to enhance some of the net_smtp methods.

10.1.2 Sendmail

In order to use sendmail, you must specify the mailer delivery method in a configuration file. This overrides the default of :net_smtp. You may also need to alter the default sendmail path from /usr/sbin/sendmail. Here we do both:

image

10.1.3 Test send

A third option, perfect for both test and possibly development environments, is the test_send delivery method. This method does not actually send email but instead pushes the message into the array Merb::Mailer.deliveries:

Merb::Mailer.delivery_method = :test_send

10.1.4 Custom delivery methods

You can also create custom delivery methods for your applications. For instance, if the SMTP gateway you’re using severely penalizes attempts to send messages above the daily quota, you may want to construct a custom delivery method that first checks to make sure you haven’t surpassed your limit. By adding a couple of methods within Merb::Mailer, we can do just this:

image

Note that in the example above, we haven’t included the actual methods for checking and increasing quota usage. This is because implementation will indubitably differ with the circumstances. One warning, though: Make sure the implementation is thread-safe. Otherwise, despite all your efforts, you may go beyond your quota anyway.

10.2 Using mailers directly

Though it’s not advisable, you can use mailers directly to send out messages. In most cases we recommend the use of the Merb Mail Controller, which is covered in the next section. However, because you may come across a scenario where you need to send out mail from inside some other noncontroller class, let’s cover its use directly.

Internally, Merb::Mailer interfaces to David Powers’s MailFactory. Passing in a hash during initialization, you construct the email just as if you were using MailFactory itself and set the attributes of a message. Below we create and send a new message by first initializing a mailer object and then calling the Mailer#deliver! method.

image

Some email clients are capable of also rendering HTML email. The Merb Mailer allows you to send HTML emails by simply setting the :html key instead of the :text key. However, it is standard practice to also include a text-only version whenever sending out HTML messages. Such dual-formatted messages are called multipart messages.

Constructing a multipart message with the Merb Mailer is as simple as setting both the :text and :html keys at initialization:

image

Let’s take a look at the code behind Merb::Mailer to understand how it interfaces with MailFactory:

image

image

10.3 Mail controllers

Mail controllers provide an MVC way of sending out email with Merb. In other words, they are intended to separate your message logic and presentation layers using controllers and views. To accomplish this, MailController subclasses from Abstract-Controller, inheriting, among other things, filtering and rendering capabilities.

Mail controllers are standardly located in app/mailers. By convention their class names are singular words with the word Mailer appended. The actions of the controller represent various types of messages that can be sent. The convention is to name these actions according to the event that sparks them, for example, notify_on_invite. If, however, there is only one action in the controller, it is often simply named notify.

Each mail controller instance initializes with a MailFactory object, @mail. We can consequently construct the message from within the action similarly to the way we did before, using the Merb Mailer directly. Note, however, that if both @mail.html and @mail.text are empty by the completion of the action, no message will be sent.

image

10.3.1 Invoking actions

Mail controllers have been designed to be called from inside standard Merb controllers. Thus a subtle characteristic of the mail controller is its reliance on the controller that called it. This dependence allows for the accessing of the original request and session data as well as the use of URL helpers.

The sending of mail from a standard controller is invoked using Controller#send_mail, a method mixed into Merb::Controller when the merb-mailer dependency is included. This method takes three parameters: the mail controller class name, the method name, and a hash of message parameters used during the initialization of @mail. Below we present the invoking of an invite mailer.

image

We recommend that you send mail out of sync with the construction of responses since SMTP gateways can hold you up at times. The easiest way to do this is with a run_later block. Here we use run_later in a slightly more complex controller action:

image

10.3.2 Parameters

Mail controllers by default have access to invoking a controller’s parameters. To access them with the mail controller, we simply use the params mash as we would in a standard mail controller. We can, however, override the value of params by using a fourth parameter on the action Controller#send_mail. Below we pass in a custom hash of parameters to be used from within the mail controller.

image

10.3.3 Attaching files

Files can be attached to messages using the method MailController#attach. This method takes either one or two parameters. When you use it to attach a single file, the first parameter should be the file. Optionally, the second parameter may be an alternate filename used when the message is actually sent. This may be useful if you are personalizing documents. Below we attach two documents, one at a time. Both will be included in the final email.

image

Instead of passing in an array to the attach method, we can attach multiple documents at once:

attach([first_file, second_file])

Finally, we can also manually specify the MIME type and final filename using arrays of arrays:

image

10.3.4 Templates

Of course the principal attraction of using mail controllers is the rendering of mail message views. These are not stored in the same location as standard views but instead in /app/mailers/views. Each mail controller should have its own subdirectory within this directory just like a standard controller. This subdirectory should be a snake-cased version of the mail controller’s own name in full, such as invite_mailer/ for the InviteMailer. Mailer templates are rendered just the same as regular templates, so you should encounter no other complications.

10.4 Testing

Testing mailers can seem tricky since they’re not part of the standard request-response cycle. However, using a few extra methods alongside the :test_method delivery method makes testing mailer behavior no problem at all.

image

In the code above we use the array Merb::Mailer.deliveries, the array to which test delivery pushes, to test the results of the mailer against our expectations.

10.5 Generation

Finally, application developers should be aware that they can quickly generate the numerous files that mailers typically entail using merb-gen. Below we create the invite mailer.

image

10.6 Conclusion

Merb Mailers are an excellent example of the intelligence of the Merb architecture. Subclassing off of the abstract controller base class, the Merb mail controller inherits standard controller functionality, allowing the application developer to deal with the sending of email through the same best practices used for the rest of the app.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.203.146