Specifying a Template and a Layout through Action Mailer's mail function
Tags: ruby, rails, tutorial
Published: 2020-04-13 14:52:51

_Originally published on [https://ali-ilman.com/blog/specifying-a-template-and-a-layout-through-action-mailer-mail-function](https://ali-ilman.com/blog/specifying-a-template-and-a-layout-through-action-mailer-mail-function)._
_Photo by [Mikaela Wiedenhoff](https://unsplash.com/photos/AwmCuTXL97Q)._

In this article, we'll take a look at one of the lesser-known features within Action Mailer, that is specifying a template and a layout through the `mail` function. This can come in handy if we want to display specific content for certain emails without creating unnecessary mailers. 🧠

## Specifying a template
There are a few ways to specify a template through the `mail` function. The `mail` function accepts keyword arguments called `template_path` and `template_name`.

### `template_path`
`template_path` is for telling Action Mailer which folder to use to look for a template. `template_path` can either be a string or an array.
Action Mailer will start looking for the specified `template_path` from within **`app/views`** folder. Let's say, our `template_path` is set to `invitations`. Then, Action Mailer will look for **`app/views/invitations`** folder.

### `template_name`
`template_name` is for telling Action Mailer the name of the template that we want to use.

### Examples
The first example here shows how we can use a template called `welcome` that sits inside of **`app/views/mailers/user_mailer/special`** folder. The `template_path` here is a string.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(to: email, template_path: 'mailers/user_mailer/special')
  end
end
```

The second example here is similar to the above, but `template_path` is an array. It's an array of path to folders. Action Mailer will look for the `welcome` template by starting on the first folder, **`app/views/mailers/user_mailer/non-special`**. If the template is not found, Action Mailer will move onto the next folder, **`app/views/mailers/user_mailer/special`**, which is where our template sits. Here, Action Mailer will stop looking for the template folder and send the email.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(
      to: email,
      template_path: ['mailers/user_mailer/non-special', 'mailers/user_mailer/special', 'mailers']
    )
  end
end
```

The third example here shows how we can use a template called `special_welcome` instead of `welcome`. `special_welcome` sits inside of **`app/views/mailers/user_mailer`** folder
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(to: email, template_name: 'special_welcome')
  end
end
```

The fourth example here shows that we can specify both `template_name` and `template_path`! This will look for a template called `special_welcome` inside of **`app/views/mailers/user_mailer/international_launch`** folder.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(
      to: email,
      template_name: 'special_welcome',
      template_path: 'mailers/user_mailer/international_launch'
    )
  end
end
```

The fifth and last example here shows that we can specify the name and location of the template by passing a block to the `mail` function. Within the block, we can determine what to render for `html`, which is basically the content of the email.  
One of the keyword arguments accepted by `render` is `template`.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(to: email) do |format|
      format.html do
        render template: 'mailers/user_mailer/international_launch/special-welcome'
      end
    end
  end
end
```

## Specifying a Layout
Another keyword argument accepted by `render` is `layout`.
### Example
The example here shows how we can use a layout called `yet-another-layout`. Action Mailer will look for the layout from within **`app/layouts`** folder.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(to: email) do |format|
      format.html { render layout: 'yet-another-layout' }
    end
  end
end
```

## Specifying both the layout and template at once
Yup! We can specify both of them. 😉

### Example
The example here will use a layout called `yet-another-layout` in **`app/layouts`** folder and a template called `yet-another-template` in **`app/views/mailers`** folder.
```ruby
class UserMailer < ApplicationMailer
  def welcome(user)
    email = user.email

    mail(to: email) do |format|
      format.html do
        render layout: 'yet-another-layout', template: 'mailers/yet-another-template'
      end
    end
  end
end
```

Cheers for reading! 🤓