How to Send Email in Ruby: Complete Developer Guide

Editorial Note: We may earn a commission when you visit links on our website.
How to send emails in Ruby

Do you need to add email functionality to your Ruby application?

Whether you’re building user authentication, notification systems, or contact forms, sending emails is a fundamental feature that every developer needs to master.

In this comprehensive Ruby email tutorial, I’ll show you 2 ways to send email in Ruby app.

How to Send Email with Ruby

There are different ways to send emails using Ruby. If you’re using Ruby on Rails, you can integrate quickly with the ActionMailer gem. This guide will focus on sending methods for vanilla Ruby applications.

Prerequisites

Before diving into the email implementations, make sure you have:

  • Basic Ruby programming knowledge
  • A text editor or IDE of your choice
  • An email service provider

You can use any email service provider you want. However, for this tutorial, I’ll use SendLayer’s SMTP credentials when implementing the email function.

SendLayer is one of the leading email service providers that lets you send emails easily and integrates with any application.

One of the standout features I like is the domain reputation protection. SendLayer automatically creates a subdomain to handle email sending activities. This thereby protects your main domain from any deliverability issues.

SendLayer offers a free account that allows users to send up to 200 emails per month. The pricing plan is also flexible, starting at $5 monthly.

  • 200 Free Emails
  • Easy Setup
  • 5 Star Support

How to Send Emails in Ruby Using the Mail Gem

The Ruby Mail gem is a customizable library that gives you control over your email implementation. It is perfect for Ruby applications outside of Rails. Here’s how to get started with the Mail gem.

Installation and Setup

To start, you’ll need to install the Mail gem as a dependency to your project. To install it, open a terminal window and run the command below:

gem install mail

Tip: Prefix the command with sudo if you encounter permission issues when installing the Mail Ruby gem.

Once the installation completes, you should see a success notification in your terminal window.

Ruby Mail gem installation in terminal

Basic Email Configuration

Before you can send an email, you’ll need to configure your SMTP server. Here’s how to configure the Mail gem with SendLayer SMTP. Start by creating an email_service.rb file in your project’s directory.

touch email_service.rb

Then open the file with a code editor. Once open, copy and paste the code below to the email service file:

require 'mail'

Mail.defaults do
  delivery_method :smtp, {
    address: 'smtp.sendlayer.net',
    port: 587,
    user_name: 'your_sendlayer_username',
    password: 'your_sendlayer_password',
    authentication: 'plain',
    enable_starttls_auto: true
  }
end

You’ll need to retrieve your SMTP credentials from the email provider you chose. In SendLayer, you’ll be able to access these details from your account area.

Once logged in, navigate to the Settings sidebar menu. Then select the SMTP Credentials tab.

SendLayer SMTP credentials

You’ll see the SMTP credentials required to use SendLayer’s SMTP server. The Host and Port number are the same for all users. However, the Username and Password details are unique to your SendLayer account.

Go ahead and replace user_name and password in the snippet above with your actual credentials.

Pro Tip: Never commit sensitive credentials to version control platforms. Always use environment variables.

After updating your SMTP credentials, you’re ready to start sending emails.

Sending Plain Text Emails

Here’s a basic implementation for sending text emails:

require 'mail'

class EmailService
  def self.configure_smtp
    Mail.defaults do
      delivery_method :smtp, {
        address: 'smtp.sendlayer.net',
        port: 587,
        user_name: ENV['SENDLAYER_USERNAME'],
        password: ENV['SENDLAYER_PASSWORD'],
        authentication: 'plain',
        enable_starttls_auto: true
      }
    end
  end

  def self.send_welcome_email(user_email, user_name)
    welcome_message = generate_welcome_message(user_name)

    mail = Mail.new do
      from     '[email protected]'
      to       user_email
      subject  'Welcome to Our Platform!'
      body     welcome_message
    end

    mail.deliver!
    puts "Welcome email sent to #{user_email}"
  rescue Mail::SMTPError => e
    puts "Failed to send email: #{e.message}"
  end

  private

  def self.generate_welcome_message(name)
    <<~MESSAGE
      Hello #{name},

      Welcome to our platform! We're excited to have you join our community.

      You can log in to your account at: https://yourdomain.com/login

      If you have any questions, please don't hesitate to contact our support team.

      Best regards,
      The Team
    MESSAGE
  end
end

Code breakdown

The configure_smtp method sets up the mail delivery configuration using Mail.defaults. We specify the SMTP details, including the address (smtp.sendlayer.net), port (587 for TLS), authentication credentials from environment variables, and enable STARTTLS for secure transmission.

The send_welcome_email method creates a new Mail object using a block syntax. We set the sender address with from, recipient with to, email subject, and generate the email body by calling a private helper method.

The mail.deliver! method actually sends the email through the configured SMTP server. The exclamation mark indicates this method will raise an exception if delivery fails.

Error handling is implemented using a rescue block that catches Mail::SMTPError exceptions. When an SMTP error occurs during delivery, it prints a failure message instead of crashing the application.

The private generate_welcome_message method uses Ruby’s heredoc syntax (<<~MESSAGE) to create a multi-line string template. The ~ removes leading whitespace, making the code more readable while preserving the email formatting.

Send a Test Email

The next step after implementing the email function is to call the class. Let’s create a main.rb file that’ll send the message. After that, copy and paste the code below into the file:

# importing the email service
require_relative 'email_service'

# configure SMTP settings
EmailService.configure_smtp

# send welcome email
EmailService.send_welcome_email('[email protected]', 'Pattie Paloma')

In the snippet above, we first import the email service file. Then call the configure_smtp() method to initialize the SMTP connection. Finally, we call the send_welcome_email() method to send the email. This method accepts 2 parameters: the recipient’s email address and name.

To run the script, open a terminal window and run the command:

ruby main.rb

You should see a welcome email delivered to the specified email address with personalized content.

Send email in ruby Gmail example

Sending an HTML Email

The Mail gem also supports HTML content with embedded CSS. This is ideal for brands looking to send newsletter content to users. To send HTML emails, you’ll need to use the html_part property when defining the mail object. Within the property, you’ll need to pass the content_type and body attributes.

Here’s the code to implement this logic. You can add this as an additional class within the email_service.rb file

require 'mail'

class HtmlEmailService
    def self.configure_smtp
        Mail.defaults do
          delivery_method :smtp, {
            address: 'smtp.sendlayer.net',
            port: 587,
            user_name: ENV['SENDLAYER_USERNAME'],
            password: ENV['SENDLAYER_PASSWORD'],
            authentication: 'plain',
            enable_starttls_auto: true
          }
        end
    end

    def self.send_newsletter(recipient_email, newsletter_data)

      newsletter_message = generate_html_content(newsletter_data)
      text_message = generate_text_content(newsletter_data)

      mail = Mail.new do
        from     '[email protected]'
        to       recipient_email
        subject  'Monthly Newsletter - Ruby Tips & Tricks'
        
        html_part do
          content_type 'text/html; charset=UTF-8'
          body newsletter_message
        end
        
        text_part do
          body text_message
        end
      end
  
      mail.deliver!
    end
  
    private
  
    def self.generate_html_content(data)
      <<~HTML
        <!DOCTYPE html>
        <html>
          <head>
            <style>
              body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
              .header { background: #2c3e50; color: white; padding: 20px; text-align: center; }
              .content { padding: 20px; background: #f9f9f9; }
              .article { margin-bottom: 20px; padding: 15px; background: white; border-radius: 5px; }
              .footer { text-align: center; padding: 20px; font-size: 12px; color: #666; }
            </style>
          </head>
          <body>
            <div class="header">
              <h1>#{data[:title]}</h1>
            </div>
            <div class="content">
              #{data[:articles].map { |article| format_article(article) }.join}
            </div>
            <div class="footer">
              <p>© 2024 Your Company. All rights reserved.</p>
            </div>
          </body>
        </html>
      HTML
    end
  
    def self.format_article(article)
      <<~ARTICLE
        <div class="article">
          <h2>#{article[:title]}</h2>
          <p>#{article[:summary]}</p>
          <a href="#{article[:url]}">Read More</a>
        </div>
      ARTICLE
    end
  
    def self.generate_text_content(data)
      content = "#{data[:title]}\n\n"
      data[:articles].each do |article|
        content += "#{article[:title]}\n#{article[:summary]}\nRead more: #{article[:url]}\n\n"
      end
      content += "© 2024 Your Company. All rights reserved."
      content
    end
  end

Code Breakdown

The Mail object uses multipart structure with separate html_part and text_part blocks. The HTML part explicitly sets the content type to 'text/html; charset=UTF-8' to ensure proper rendering, while the text part uses the default plain text format. This approach ensures email clients can display either version based on their capabilities.

The generate_html_content method uses Ruby’s heredoc syntax to create a complete HTML email template. It includes inline CSS styling for better email client compatibility and uses string interpolation (#{data[:title]}) to insert dynamic content from the newsletter data hash.

The helper method format_article generates individual article HTML blocks using the same heredoc approach. It takes an article hash and formats it with title, summary, and read-more link within styled div containers.

The generate_text_content method creates a plain text fallback version by iterating through the articles array using each and building a simple text format. This ensures users with text-only email clients can still read the newsletter content.

While Rails mailer includes built-in mailer views for template management, in vanilla Ruby, we handle HTML templates directly.

Send a Test HTML email in Ruby

Here’s how you’ll use the HTMLEmailService class we created. In your main.rb file, copy and paste the code snippet below:

# importing the email service
require_relative 'email_service'

# configure SMTP settings
HtmlEmailService.configure_smtp

# create newsletter data
newsletter_data = {
    title: "This Month in SendLayer",
    articles: [
      {
        title: "New Ruby SDK Launched",
        summary: "Discover the latest improvements in SendLayer API",
        url: "https://example.com/features"
      }
    ]
  }
 
# send HTML email
HtmlEmailService.send_newsletter('[email protected]', newsletter_data)

When you test this implementation, email clients will automatically select the HTML or text version based on user preferences and client capabilities. Providing the best possible experience for all recipients.

Test HTML email in ruby

Send Bulk Emails in Ruby

By default, the Mail gem doesn’t include support for sending emails to multiple recipients. However, you can implement support to send emails in batches using Ruby loops. Here’s how to handle bulk emails efficiently:

class BulkEmailService
    MAX_BATCH_SIZE = 50
    DELAY_BETWEEN_BATCHES = 1 # seconds

    def self.configure_smtp
        Mail.defaults do
          delivery_method :smtp, {
            address: 'smtp.sendlayer.net',
            port: 587,
            user_name: ENV['SENDLAYER_USERNAME'],
            password: ENV['SENDLAYER_PASSWORD'],
            authentication: 'plain',
            enable_starttls_auto: true
          }
        end
      end
  
    def self.send_bulk_emails(recipients, subject, message)
      recipients.each_slice(MAX_BATCH_SIZE) do |batch|
        batch.each do |recipient|
          send_single_email(recipient[:email], subject, message, recipient[:name])
          sleep(0.1) # Small delay to prevent overwhelming server
        end
        
        puts "Processed batch of #{batch.size} emails"
        sleep(DELAY_BETWEEN_BATCHES)
      end
    end
  
    private
  
    def self.send_single_email(email, subject, message, name = nil)
      personalized_message = name ? message.gsub('{{name}}', name) : message
      
      mail = Mail.new do
        from     '[email protected]'
        to       email
        subject  subject
        body     personalized_message
      end
  
      mail.deliver!
      puts "Email sent to #{email}"
    rescue StandardError => e
      puts "Failed to send email to #{email}: #{e.message}"
    end
  end

Code Breakdown

In the code above, we first define two important constants: MAX_BATCH_SIZE = 50 sets the maximum number of emails to process in each batch, and DELAY_BETWEEN_BATCHES = 1 specifies a one-second pause between batches. These help prevent overwhelming the server and avoid rate limiting or blacklisting.

The send_bulk_emails method uses Ruby’s each_slice method to divide the recipients array into smaller batches of the specified size.

Within each batch, we iterate through recipients and call send_single_email for each one. The sleep(0.1) adds a 100-millisecond delay between individual emails.

After processing each batch, the method prints a status message and pauses for the specified DELAY_BETWEEN_BATCHES duration.

The private send_single_email method handles personalization by using gsub('{{name}}', name) to replace placeholder text with the recipient’s actual name. If no name is provided, it uses the original message unchanged.

Send a Test Email

After setting up the email service, you can import and use it in another file. Let’s continue using the main.rb file. Here’s an example snippet showing how to use the bulk email class.

# importing the email service
require_relative 'email_service'

# configure SMTP settings
BulkEmailService.configure_smtp 

  recipients = [
    { email: '[email protected]', name: 'Alice' },
    { email: '[email protected]', name: 'Bob' },
    # ... more recipients
  ]
  
  message = <<~MESSAGE
    Hello {{name}},
  
    We have an important update to share with you...
  MESSAGE
  
  BulkEmailService.send_bulk_emails(recipients, 'Important Update', message)

Send Email with Attachments

The Mail gem includes support for attaching files to emails. To send an email with an attachment, you’ll need to include the add_file property when specifying the email parameters. Here’s an example:

require 'mail'

def send_email_with_attachment(recipient, attachment_path)
  mail = Mail.new do
    from     '[email protected]'
    to       recipient
    subject  'Document Attached'
    body     'Please find the attached document.'
    
    add_file attachment_path
  end

  mail.deliver!
end

The value of the add_file property should be the path to the file you wish to attach. The Mail gem handles encoding and also tries to guess the file type.

To send multiple attachments, use Ruby’s foreach syntax to map each attachment file to the add_file property. Here is an example:

# For multiple attachments
def send_email_with_multiple_attachments(recipient, attachment_paths)
  mail = Mail.new do
    from     '[email protected]'
    to       recipient
    subject  'Multiple Documents Attached'
    body     'Please find the attached documents.'
    
    attachment_paths.each { |path| add_file path }
  end

  mail.deliver!
end

That’s it! You’ve now learned how to send emails in Ruby using SMTP.

How to Send Emails in Ruby Using Email API

Sending emails through SMTP works well for smaller projects. However, it is less secure and slower when compared to using an email API.

Fortunately, platforms like SendLayer also include an API for sending emails and tracking events such as open and bounce rates. I’ll show you how to set up a program that uses the SendLayer API to send emails.

  • 200 Free Emails
  • Easy Setup
  • 5 Star Support

Send Emails With SendLayer API

To send an email using SendLayer API, you’ll need 3 parameters:

  • Base URL: This is the API endpoint for sending emails. For SendLayer, this endpoint is available at https://console.sendlayer.com/api/v1/email
  • Headers: This is where you’ll define the format for the request and also authenticate your connection
  • Payload: This contains the JSON object with details for sending an email, like the sender and recipient email addresses

Ruby provides a default net/http library for making HTTP requests. I’ll use this gem to make the HTTP request to SendLayer’s email endpoint. Here’s the snippet to send emails with the SendLayer API.

require 'uri'
require 'net/http'

url = URI("https://console.sendlayer.com/api/v1/email")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = {
  "From": {
    "name": "Paulie Paloma",
    "email": "[email protected]"
  },
  "To": [
    {
      "name": "Pattie Paloma",
      "email": "[email protected]"
    }
  ],
  "Subject": "Test email with Ruby and SendLayer API",
  "ContentType": "HTML",
  "HTMLContent": "<html><body><p>This is a test email sent with the <a href="https://sendlayer.com">SendLayer</a> API and Ruby!</p></body></html>",
}.to_json

response = http.request(request)
puts response.read_body

Code Breakdown

In the snippet above, we first create a URI object from the SendLayer API endpoint and initialize an HTTP connection. We call http.use_ssl = true to enable SSL/TLS encryption for secure communication with the API server.

Next, we create a POST request object and set the required headers. The Authorization header uses Bearer token authentication with 'Bearer <token>', and we set the Content-Type to 'application/json' since we’re sending JSON data.

Note: Remember to replace <token> with your actual SendLayer API token and update the email addresses to valid ones for testing.

The request body contains a Ruby hash with the email data structure that SendLayer expects. This hash is then converted to JSON format using .to_json before being assigned to request.body. This ensures the data is properly serialized for the API request.

Finally, we execute the request using http.request(request) and print the API response with response.read_body. The response will typically contain information about the delivery status or any error messages from the SendLayer service.

Retrieving SendLayer API Key

To get your API key, log in to your SendLayer account. Once you’re logged in, click the Settings menu and select the API Keys tab.

Click API keys tab

Then click the copy icon next to Default API key to copy it.

Copy SendLayer API key to send email with python

Sending Email to Multiple Recipients

SendLayer’s API allows you to send emails to multiple recipients, including CC and BCC email addresses. To send an email to multiple recipients in Ruby, update the To array in the email body with the additional recipient(s) you want to add. Here’s an example:

# other code snippets...

request.body = {
  "From": {
    "name": "Paulie Paloma",
    "email": "[email protected]"
  },
  "To": [
    {
      "name": "Pattie Paloma",
      "email": "[email protected]"
    },
   {
      "name": "John Doe",
      "email": "[email protected]"
    }
  ],
  "CC": [
    {
      "name": "Pattie Paloma CC",
      "email": "[email protected]"
    }
  ],
  "BCC": [
    {
      "name": "Pattie Paloma BCC",
      "email": "[email protected]"
    }
  ],
  "ReplyTo": [
    {
      "name": "Pattie Paloma ReplyTo",
      "email": "[email protected]"
    }
  ],
  "Subject": "This is the email to multiple recipients",
  "ContentType": "HTML",
  "HTMLContent": "<html><body><p>This is a test email sent with the <a href="https://sendlayer.com">SendLayer</a> API and Ruby!</p></body></html>",
}.to_json

# ... other code

SendLayer API also lets you attach files to your email messages. See our developer guide for more details on sending emails through an email API.

FAQs – Send Emails With Ruby

What’s the difference between Action Mailer and the Mail gem in Ruby?

Action Mailer is a built-in email framework providing seamless integration with Ruby on Rails applications. It includes templating, testing helpers, and background job integration. The Mail gem, on the other hand, is a standalone library that works in any Ruby application. It offers more low-level control over email creation and delivery.

How do I handle bounced emails and delivery failures?

The best way to handle delivery failures is by implementing proper error handling with try-catch blocks. You can also use webhook endpoints provided by your SMTP service to handle bounce notifications. Services like SendLayer provide detailed delivery reports and bounce handling.

How do I configure SMTP settings for production?

Proper mailer configuration is crucial for production environments. Always use environment variables for SMTP Ruby credentials and ensure your SMTP class implementation includes proper error handling and connection pooling.

What are the security best practices for email delivery in Ruby?

Below, we’ve highlighted some of the best practices for handling email in Ruby applications:

  • Always use environment variables for credentials
  • Enable TLS/SSL connections
  • Validate email addresses before sending
  • Implement rate limiting
  • Use reputable SMTP providers with proper authentication.
  • Never expose API keys or passwords in your source code

That’s it! Now you know how to send emails in Ruby.

Next, would you like to learn about the difference between different sending methods? Check out our tutorial on SMTP vs API for more information.

  • 200 Free Emails
  • Easy Setup
  • 5 Star Support

Ready to send your emails in the fastest and most reliable way? Get started today with the most user-friendly and powerful SMTP email delivery service. SendLayer Business includes 5,000 emails a month with premium support.