Sending Email using Ruby - SMTP


Simple Mail Transfer Protocol (SMTP) is a protocol which handles sending e-mail and routing e-mail between mail servers.

Ruby provides Net::SMTP class for Simple Mail Transfer Protocol (SMTP) client-side connection and provides two class methods new and start.

An SMTP object has an instance method called sendmail, which will typically be used to do the work of mailing a message. It takes three parameters:

 

Example:

Here is a simple way to send one email using Ruby script. Try it once:

      require 'net/smtp'
      
      message = <<MESSAGE_END
      From: Private Person <me@fromdomain.com>
      To: A Test User <test@todomain.com>
      Subject: SMTP e-mail test
      
      This is a test e-mail message.
      MESSAGE_END
      
      Net::SMTP.start('localhost') do |smtp|
        smtp.send_message message, 'me@fromdomain.com', 
                                   'test@todomain.com'
      end
      

Here you have placed a basic e-mail in message, using a here document, taking care to format the headers correctly. An e-mails requires a From, To, and Subject header, separated from the body of the e-mail with a blank line.

To send the mail you use Net::SMTP to connect to the SMTP server on the local machine and then use the send_message method along with the message, the from address, and the destination address as parameters (even though the from and to addresses are within the e-mail itself, these aren't always used to route mail).

If you're not running an SMTP server on your machine, you can use Net::SMTP to communicate with a remote SMTP server. Unless you're using a webmail service (such as Hotmail or Yahoo! Mail), your e-mail provider will have provided you with outgoing mail server details that you can supply to Net::SMTP, as follows:

      Net::SMTP.start('mail.your-domain.com')
      

This line of code connects to the SMTP server on port 25 of mail.your-domain.com without using any username or password. If you need to, though, you can specify port number and other details. For example:

      Net::SMTP.start('mail.your-domain.com', 
                      25, 
                      'localhost', 
                      'username', 'password' :plain)
      

This example connects to the SMTP server at mail.your-domain.com using a username and password in plain text format. It identifies the client's hostname as localhost.

 

Sending an HTML email using Ruby:

When you send a text message using Ruby then all the content will be treated as simple text. Even if you will include HTML tags in a text message, it will be displayed as simple text and HTML tags will not be formatted according to HTML syntax. But Ruby Net::SMTP provides option to send an HTML message as actual HTML message.

While sending an email message you can specify a Mime version, content type and character set to send an HTML email.

 

Example:

Following is the example to send HTML content as an email. Try it once:

      require 'net/smtp'
      
      message = <<MESSAGE_END
      From: Private Person <me@fromdomain.com>
      To: A Test User <test@todomain.com>
      MIME-Version: 1.0
      Content-type: text/html
      Subject: SMTP e-mail test
      
      This is an e-mail message to be sent in HTML format
      
      
      <b>This is HTML message.</b>
      <h1>This is headline.</h1>
      MESSAGE_END
      
      Net::SMTP.start('localhost') do |smtp|
        smtp.send_message message, 'me@fromdomain.com', 
                                   'test@todomain.com'
      end
      

 

Sending Attachements as an e-mail:

To send an email with mixed content requires to set Content-type header to multipart/mixed. Then text and attachment sections can be specified within boundaries.

A boundary is started with two hyphens followed by a unique number which can not appear in the message part of the email. A final boundary denoting the email's final section must also end with two hyphens.

Attached files should be encoded with the pack("m") function to have base64 encoding before transmission.

 

Example:

Following is the example which will send a file /tmp/test.txt as an attachment. Try it once:

      require 'net/smtp'
      
      filename = "/tmp/test.txt"
      # Read a file and encode it into base64 format
      filecontent = File.read(filename)
      encodedcontent = [filecontent].pack("m")   # base64
      
      marker = "AUNIQUEMARKER"
      
      body =<<EOF
      This is a test email to send an attachement.
      EOF
      
      # Define the main headers.
      part1 =<<EOF
      From: Private Person <me@fromdomain.net>
      
      To: A Test User <test@todmain.com>
      Subject: Sending Attachement
      MIME-Version: 1.0
      Content-Type: multipart/mixed; boundary=#{marker}
      --#{marker}
      EOF
      
      # Define the message action
      part2 =<<EOF
      Content-Type: text/plain
      Content-Transfer-Encoding:8bit
      
      #{body}
      --#{marker}
      EOF
      
      # Define the attachment section
      part3 =<<EOF
      Content-Type: multipart/mixed; name=\"#{filename}\"
      Content-Transfer-Encoding:base64
      Content-Disposition: attachment; filename="#{filename}"
      
      #{encodedcontent}
      --#{marker}--
      EOF
      
      mailtext = part1 + part2 + part3
      
      # Let's put our code in safe area
      begin 
        Net::SMTP.start('localhost') do |smtp|
           smtp.sendmail(mailtext, 'me@fromdomain.net',
                                ['test@todmain.com'])
        end
      rescue Exception => e  
        print "Exception occured: " + e  
      end  
      

NOTE: You can specify multiple destinations inside the array but they should be separated by comma.