Mails in Ruby on Rails – Complete Guide
📌 What are Mails in Rails?
In Ruby on Rails, sending emails is handled by a component called Action Mailer. It’s a powerful module that allows your application to send emails using SMTP, APIs, or third-party services. You can use it to notify users, reset passwords, confirm orders, send invoices, and much more.
Action Mailer works just like a controller. You define a mailer class and methods inside it, then use views to create email content (both plain text and HTML). It supports background delivery with Active Job (e.g. Sidekiq), file attachments, email previews in development, and even custom layouts.
Rails abstracts all the complexity of email configuration and gives you a clean way to create and send dynamic and styled emails. You can use it for everything from user account actions to marketing.
Use Cases:
- 🔐 Password reset links
- 👋 Welcome emails after signup
- 📩 Order confirmations with tracking info
- 🧾 Invoice attachments
- 📢 Admin notifications or newsletters
Overall, Action Mailer makes it extremely easy for Rails developers to integrate email functionality into any type of application without writing low-level code.
🧩 Different Types of Email Templates in Rails
In Rails, email templates are written just like views. Each mailer method has corresponding templates which can be in multiple formats:
Template Type | File Extension | Description | Example File |
---|---|---|---|
HTML Email | .html.erb | Rich HTML content for modern email clients | welcome_email.html.erb |
Plain Text Email | .text.erb | Fallback for clients that don’t support HTML | welcome_email.text.erb |
Multipart Email | Both | Rails automatically picks both HTML and text if both templates exist | welcome_email.html.erb + welcome_email.text.erb |
Partial Templates | _*.html.erb | Reusable template blocks (e.g. signature, header) | _footer.html.erb |
Layout Templates | layouts/mailer.html.erb | Shared email layout for branding (wrapper with styles) | mailer.html.erb |
📄 Example: Welcome Email Template
# app/views/user_mailer/welcome_email.html.erb
<h1>Welcome, <%= @user.name %>!</h1>
<p>Thanks for signing up with us. You can now enjoy our services.</p>
<%= render 'shared/footer' %>
✅ Best Practices
- Use multipart templates to support both HTML and plain text clients.
- Separate common components (e.g., signature, branding) into partials.
- Use layouts to keep a consistent design across emails.
- Keep templates clean and test rendering with Mailer Previews.
- Avoid heavy CSS — stick to inline styles for maximum compatibility.
⚙️ Full Implementation Cycle of Mail Templates in Rails
Here’s a step-by-step implementation flow for using email templates effectively with Action Mailer.
1️⃣ Generate the Mailer
rails generate mailer UserMailer
This creates:
app/mailers/user_mailer.rb
app/views/user_mailer/
test/mailers/user_mailer_test.rb
2️⃣ Define a Mail Method
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
def welcome_email(user)
@user = user
mail(to: @user.email, subject: "Welcome to Our App!")
end
end
3️⃣ Create HTML and Text Templates
# app/views/user_mailer/welcome_email.html.erb
<h1>Welcome, <%= @user.name %>!</h1>
<p>Thank you for joining. Start exploring now!</p>
# app/views/user_mailer/welcome_email.text.erb
Welcome, <%= @user.name %>!
Thank you for joining. Start exploring now!
4️⃣ Create a Layout (Optional)
Use a layout to wrap your emails with consistent branding.
# app/views/layouts/mailer.html.erb
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<div style="padding: 20px; font-family: sans-serif;">
<%= yield %>
<hr>
<p style="font-size: 12px;">This is an automated message.</p>
</div>
</body>
</html>
5️⃣ Add a Partial (Reusable Footer)
# app/views/user_mailer/_footer.html.erb
<p>Thanks,<br>The Support Team</p>
# In your main template
<%= render 'footer' %>
6️⃣ Trigger Mail from Controller or Background Job
In controller:
UserMailer.welcome_email(@user).deliver_now
Or with background job:
UserMailer.welcome_email(@user).deliver_later
7️⃣ Preview Emails in Development
# app/mailers/previews/user_mailer_preview.rb
class UserMailerPreview < ActionMailer::Preview
def welcome_email
user = User.first
UserMailer.welcome_email(user)
end
end
Then visit http://localhost:3000/rails/mailers
to preview the email!
8️⃣ SMTP Settings for Sending
# config/environments/development.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.sendgrid.net",
port: 587,
authentication: :plain,
user_name: ENV["SMTP_USER"],
password: ENV["SMTP_PASSWORD"],
domain: "yourdomain.com",
enable_starttls_auto: true
}
✅ Summary of the Template Lifecycle
- Create a mailer
- Add mail methods
- Create HTML and plain views
- Add layout and partials
- Trigger email via controller/job
- Use
deliver_later
for background jobs - Test with Mailer Preview
- Deploy with SMTP config
This cycle makes it easy to build beautiful, testable, and scalable email systems in Rails.
📚 Key Terms and Concepts in Rails Mailer
Term | Description |
---|---|
ActionMailer | Rails component responsible for sending emails using SMTP or API services. |
Mailer Class | A Ruby class that defines email methods (e.g., UserMailer ). |
mail() | Rails method to construct an email — sets to , from , subject . |
.html.erb | Template for HTML content in emails (rich formatting). |
.text.erb | Plain text version of the email for fallback clients. |
layouts/mailer.html.erb | Shared layout template applied to all emails (branding, wrappers). |
Partial | Reusable snippet used in templates, e.g. _footer.html.erb . |
deliver_now | Sends the email immediately (synchronous). |
deliver_later | Sends the email asynchronously using Active Job and a background processor. |
Mailer Preview | Tool in development to preview emails in browser at /rails/mailers . |
SMTP | Simple Mail Transfer Protocol – the default protocol used for sending email. |
Sidekiq | A background job processor often used with deliver_later . |
ENV[] | Used to access environment variables for securing credentials like SMTP user/password. |
rails generate mailer | Rails CLI command to create a new mailer class with test and view files. |
🌐 Different Platforms to Send Emails in Rails
You can integrate Rails with various platforms for reliable and scalable email delivery. Here’s a comparison:
Platform | Type | Description | Best For |
---|---|---|---|
SendGrid | API / SMTP | Popular, reliable email service with APIs and dashboards. Free tier available. | Transactional & marketing emails, scalable apps |
Mailgun | API / SMTP | Developer-friendly email service with advanced analytics and inbound routing. | High-volume transactional emails, dev automation |
Postmark | API / SMTP | Fast, reliable transactional email service focused on deliverability. | Important user notifications (password resets, invoices) |
Amazon SES | SMTP / API | Highly scalable and cost-effective from AWS. Requires domain verification. | Large-scale apps needing low cost |
Gmail SMTP | SMTP | Use your Gmail account to send mail via SMTP. Good for personal or small projects. | Testing, small apps, internal tools |
Outlook/Office365 SMTP | SMTP | Microsoft’s SMTP service for business-level email accounts. | Corporate tools, admin notifications |
Brevo (ex-Sendinblue) | SMTP / API | Email marketing & transactional delivery service. Offers automation workflows. | Newsletter + system alerts |
Zoho Mail | SMTP | Zoho Mail provides SMTP for apps with domain-linked inboxes. | Business mail + app notifications |
SMTP2GO | SMTP | Globally distributed SMTP delivery system with detailed logs and bounce handling. | Remote apps, distributed teams |
Tip: For production apps, use API-based services like SendGrid or Postmark with background job delivery to ensure better deliverability and tracking.
🧾 Using Templates from Email Platforms in Rails
Most modern email services like SendGrid, Mailgun, Postmark, Brevo (Sendinblue), and Amazon SES offer
hosted templates that you can create and manage directly on their dashboard.
Instead of designing email content inside Rails views (.html.erb
), you offload the layout and formatting to the platform.
💡 What Are Hosted Templates?
Hosted templates are reusable email layouts stored and rendered on the email provider’s side. These templates support:
- 📄 Visual builders (drag & drop or WYSIWYG)
- 📦 Reusable layout and design
- 🧠 Dynamic variables (e.g., user name, order ID)
- 📈 Analytics like opens, clicks, bounce tracking
- 🪄 A/B testing, version control, automation triggers
🔗 Integration Flow from Rails
- Create your email template in the provider dashboard (SendGrid, Mailgun, etc.)
- Get the
template_id
(or slug) - Inject dynamic values using the provider’s API (e.g., name, code, links)
- Send the email via HTTP request (not using ActionMailer views)
📊 Template Feature Comparison
Platform | Visual Builder | Dynamic Variables | API Sending | Rails SDK/Gem |
---|---|---|---|---|
SendGrid | ✅ Drag & Drop | ✅ Handlebars {{name}} | ✅ via v3/mail/send | sendgrid-ruby |
Mailgun | ⚠️ Code or upload | ✅ via %recipient.name% | ✅ via /messages | mailgun-ruby |
Postmark | ✅ HTML + editor | ✅ via {{name}} | ✅ via /email/withTemplate | postmark-rails |
Amazon SES | ⚠️ JSON-based | ✅ via JSON input | ✅ SendTemplatedEmail | aws-sdk-ses |
Brevo (Sendinblue) | ✅ Drag & Drop | ✅ {{contact.FIRSTNAME}} | ✅ via /smtp/email | sib-api-v3-sdk |
🛠️ Example: SendGrid Email Template Integration in Rails
# Gemfile
gem 'sendgrid-ruby'
# app/jobs/send_promotional_email_job.rb
class SendPromotionalEmailJob < ApplicationJob
queue_as :default
def perform(user)
data = {
personalizations: [
{
to: [{ email: user.email }],
dynamic_template_data: {
name: user.name,
discount: "25% OFF",
cta_link: "https://yourapp.com/deals"
}
}
],
from: { email: "no-reply@yourapp.com" },
template_id: ENV["SENDGRID_TEMPLATE_ID"]
}
sg = SendGrid::API.new(api_key: ENV["SENDGRID_API_KEY"])
sg.client.mail._("send").post(request_body: data)
end
end
🔁 Now you can update your email design in the SendGrid dashboard without changing any code in Rails.
✅ Best Practices
- Use
deliver_later
or background jobs for sending platform-based emails - Keep
template_id
inENV
variables - Use versioning or naming convention for templates (e.g.,
welcome_v2
) - Use the email provider’s built-in test and preview tools before activating in production
- Monitor delivery, bounce, and open rates via dashboard or webhook callbacks
Tip: This approach is ideal for high-conversion transactional or marketing emails. It also makes it easier for designers or marketing teams to update content without developer involvement.
📬 How to Send HTML, Text, or Multipart Emails in Rails
Ruby on Rails supports three common formats when sending emails:
plain text, HTML, or multipart (both). You don’t need to configure anything special—Rails automatically chooses the right format
based on which templates you provide in the app/views/mailer_name/
folder.
1️⃣ Plain Text Only Email
If you only provide a .text.erb
file, Rails will send a plain email with no styling or HTML tags.
# app/views/user_mailer/welcome_email.text.erb
Hello <%= @user.name %>,
Thanks for joining our app!
Best,
The Team
Use Case: Minimalist systems, CLI emails, fallback-only systems.
2️⃣ HTML Only Email
If you only create a .html.erb
template, Rails will send the email as HTML.
# app/views/user_mailer/welcome_email.html.erb
<h1>Welcome, <%= @user.name %>!</h1>
<p>Thanks for signing up.</p>
<p><a href="https://yourapp.com">Click here</a> to get started.</p>
Use Case: Styled content, links, buttons, visual branding.
3️⃣ Multipart Email (HTML + Text)
This is the most recommended setup. Just create both templates:
app/views/user_mailer/welcome_email.text.erb
app/views/user_mailer/welcome_email.html.erb
Rails will automatically send a multipart email that contains both formats. Email clients (like Gmail, Apple Mail, Outlook) decide which version to display depending on user preferences or compatibility.
📁 File Structure Example
app/
└── views/
└── user_mailer/
├── welcome_email.html.erb
└── welcome_email.text.erb
✅ Best Practices
- Always provide both versions when possible (HTML + Text)
- Use tools like Litmus or Mailtrap to preview both formats
- Use inline styles in HTML (avoid CSS files—many email clients ignore them)
- Keep the text version simple and readable
- Test both formats in multiple mail clients (Gmail, Apple Mail, Outlook)
By following the multipart approach, you ensure better **accessibility**, **spam score compliance**, and **user experience** across all devices and clients.
📎 How to Attach Files and Images in Rails Emails
Rails makes it easy to send attachments (like PDFs or images) with your emails using attachments[]
in your mailer method. You can also embed inline images (e.g., company logos) inside the email body.
📄 1. Attaching a File (e.g. PDF Invoice)
# app/mailers/user_mailer.rb
def invoice_email(user)
@user = user
pdf_path = Rails.root.join("public", "invoices", "invoice_#{user.id}.pdf")
attachments["invoice.pdf"] = File.read(pdf_path)
mail(to: @user.email, subject: "Your Invoice is Ready")
end
Note: You can dynamically generate files (e.g. with Prawn or WickedPDF) before attaching them.
🖼️ 2. Embedding Inline Images (e.g. Logo)
To display an image inside the email content:
# app/mailers/user_mailer.rb
def welcome_email(user)
@user = user
attachments.inline['logo.png'] = File.read(Rails.root.join("app/assets/images/logo.png"))
mail(to: @user.email, subject: "Welcome to Our App")
end
<!-- app/views/user_mailer/welcome_email.html.erb -->
<h1>Welcome, <%= @user.name %></h1>
<img src="cid:logo.png" alt="Company Logo" />
<p>We’re glad to have you!</p>
📦 3. Sending Multiple Attachments
Loop through a list of files and attach each one:
["report1.pdf", "report2.pdf"].each do |filename|
attachments[filename] = File.read(Rails.root.join("reports", filename))
end
⚠️ Common Pitfalls
- ✅ Ensure the file path exists and is readable in production
- 📁 Don’t store sensitive files publicly—use private locations or signed URLs
- 📧 Large attachments (over 5MB) may fail depending on SMTP limits
- 💡 Use background jobs when generating and attaching dynamic files
✅ Best Practices
- Generate PDFs on the fly using
Prawn
orWickedPDF
- Use inline attachments for branding images (e.g., company logo)
- Preview emails locally to confirm attachments appear correctly
- For marketing emails with many images, consider external hosted images with CDN
File and image attachments improve email UX—just make sure they’re used carefully to avoid bloated emails or delivery issues.
❓ 10 In-Depth Questions & Answers on Mails in Ruby on Rails
- Q1: What is Action Mailer in Ruby on Rails?
A: Action Mailer is a core framework in Rails used to send emails. It works much like controllers: you define mailer classes, methods (actions), and views (email templates). With Action Mailer, you can send both plain text and HTML emails, attach files, use layouts, and even preview emails in development. It supports sending via SMTP or external APIs like SendGrid, Mailgun, etc. - Q2: What’s the difference between
deliver_now
anddeliver_later
?
A:deliver_now
sends the email immediately during the request-response cycle, blocking the user until complete.deliver_later
adds the email to a background job queue (like Sidekiq or Active Job) and sends it asynchronously.
Example:
UserMailer.welcome_email(@user).deliver_later
– this won’t delay your web request. - Q3: How do I create and send a basic email in Rails?
A:- Generate a mailer:
rails generate mailer UserMailer
- Add a method:
def welcome_email(user); @user = user; mail(to: user.email, subject: "Welcome!"); end
- Create a template:
app/views/user_mailer/welcome_email.html.erb
- Call it:
UserMailer.welcome_email(@user).deliver_now
- Generate a mailer:
- Q4: How can I preview emails in development?
A: Rails supports mail previews. Create a preview file like this:
Then visit:# test/mailers/previews/user_mailer_preview.rb class UserMailerPreview < ActionMailer::Preview def welcome_email UserMailer.welcome_email(User.first) end end
http://localhost:3000/rails/mailers
to preview your emails. - Q5: Can I send both HTML and plain text emails?
A: Yes. Create two versions:welcome_email.html.erb
– for rich HTMLwelcome_email.text.erb
– fallback for email clients that don’t support HTML
- Q6: How do I attach a file to an email in Rails?
A: Use theattachments[]
syntax inside your mailer:
This works well for sending invoices, PDFs, or images.attachments["invoice.pdf"] = File.read("/path/to/invoice.pdf") mail(to: user.email, subject: "Your Invoice")
- Q7: How do I configure SMTP for production?
A: Configureconfig/environments/production.rb
like this:
Always store credentials inconfig.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "smtp.sendgrid.net", port: 587, user_name: ENV["SMTP_USERNAME"], password: ENV["SMTP_PASSWORD"], authentication: :plain, enable_starttls_auto: true }
ENV
or Rails encrypted credentials. - Q8: What happens if a background email fails?
A: If you’re usingdeliver_later
, Rails uses Active Job to enqueue the task. If the job fails:- It will retry automatically (depending on your queue adapter)
- You can use
rescue_from
to handle mail failures - Monitor it using tools like Sidekiq Web or Exception Tracking
- Q9: Can I use SendGrid or Mailgun templates instead of Rails views?
A: Yes. These platforms support hosted templates. In Rails, you send an API call with template ID and merge variables. Example using SendGrid:
This allows non-developers to manage the design on SendGrid dashboard.mail.template_id = "d-123abc456" dynamic_template_data: { name: "John" }
- Q10: What is the benefit of using a mailer layout?
A: A layout is like a shared wrapper around all emails. You can define headers, footers, and common branding (like logos or disclaimers) in:app/views/layouts/mailer.html.erb
Example:
This keeps your emails consistent and DRY.<html> <body> <%= yield %> <p>Thanks, The Team</p> </body> </html>
✅ Best Practices for Sending Emails in Ruby on Rails
- 📁 Organize your mailers by feature or role:
Use separate mailer classes likeAdminMailer
,UserMailer
,OrderMailer
for better separation of concerns. - 📄 Use multipart emails (HTML + Text):
Always create both.html.erb
and.text.erb
versions so clients can choose based on compatibility. - 🖼️ Use layouts and partials:
DRY your email templates with shared headers, footers, and branding via partials and a mailer layout (e.g.layouts/mailer.html.erb
). - 📤 Always use
deliver_later
in production:
Offload email delivery to background jobs using ActiveJob with Sidekiq/Resque to avoid blocking the request. - 🔒 Hide SMTP credentials:
Never hard-code SMTP usernames or passwords. Use Rails credentials (config/credentials.yml.enc
) orENV
variables. - 📬 Use a trusted provider:
Use platforms like SendGrid, Postmark, or Mailgun to improve deliverability, spam compliance, and analytics. - 📈 Monitor email success/failure:
Use dashboards and webhook callbacks (from your provider) to track bounces, opens, clicks, and failures. - 🧪 Test emails thoroughly:
Write mailer specs with RSpec or Minitest. Preview each mail using/rails/mailers
to confirm layout and data rendering. - 🛑 Avoid heavy attachments:
Keep attachments under 5 MB. For large files, consider sending links to signed downloads (e.g., from AWS S3). - 🕓 Delay non-critical emails:
For marketing or newsletters, delay delivery usingdeliver_later(wait: 10.minutes)
or schedule with cron/Sidekiq.
Following these best practices ensures your Rails email system is clean, efficient, reliable, and secure for users and developers alike.
🔗 External Resources & Further Reading
Here are some official docs, guides, and tools to help you dive deeper into sending emails with Rails:
- 📘 Official Rails Guide: Action Mailer Basics
Learn how to create mailers, views, previews, and send emails the Rails way. - 📚 SendGrid + Rails Integration Guide
Step-by-step tutorial on integrating SendGrid API with Action Mailer. - 🧰 sendgrid-ruby GitHub SDK
The official Ruby gem to send email via SendGrid API (dynamic templates supported). - 📬 Mailgun: Sending via SMTP or API
How to send emails using Mailgun SMTP or API from your Rails app. - 🧪 Rails API: ActionMailer::Base
Full reference to all methods, delivery options, and callbacks in ActionMailer. - 💡 GoRails: Sending Emails in Rails (Video)
Practical screencast tutorial for beginners using Action Mailer.
These resources will help you understand mail delivery, debugging, testing, and using external providers like SendGrid or Mailgun effectively with Rails.
Learn more about Rails
https://shorturl.fm/j3kEj
https://shorturl.fm/6539m
https://shorturl.fm/9fnIC
https://shorturl.fm/A5ni8
https://shorturl.fm/6539m
https://shorturl.fm/m8ueY
https://shorturl.fm/FIJkD
https://shorturl.fm/a0B2m
https://shorturl.fm/m8ueY
https://shorturl.fm/hevfE
https://shorturl.fm/DA3HU
https://shorturl.fm/0EtO1
https://shorturl.fm/I3T8M
https://shorturl.fm/VeYJe