Ruby Sending Email
Sending Email in Ruby using Net::SMTP
Section titled “Sending Email in Ruby using Net::SMTP”The Simple Mail Transfer Protocol (SMTP) is the standard internet protocol for sending electronic mail. Ruby’s standard library includes the Net::SMTP class, which provides a client-side interface for connecting to an SMTP server and sending emails.
Net::SMTP offers methods to establish a connection, authenticate (if required), and transmit email messages. The primary way to use it is via the Net::SMTP.start block form, which handles connection opening and closing automatically.
The Net::SMTP.start method accepts several parameters to configure the connection:
address: The hostname or IP address of the SMTP server (defaults to ‘localhost’).port: The port number of the SMTP server (defaults to 25, the standard SMTP port).helo_domain: The domain name your client identifies itself with (HELO/EHLO command, defaults to your system’s hostname).user: Username for SMTP authentication (if needed, defaults tonil).password: Password for SMTP authentication (if needed, defaults tonil).authtype: The authentication mechanism (e.g.,:plain,:login,:cram_md5, defaults to:cram_md5if user is provided).
Inside the block passed to start, the SMTP instance provides the send_message method, which takes:
message_string: The full email message content (headers and body) as a string.from_address: The sender’s email address (for the MAIL FROM SMTP command).to_addresses: A single recipient email address (string) or an array of recipient email addresses.
Sending a Basic Text Email
Section titled “Sending a Basic Text Email”Here’s a simple example of sending an email. This assumes an SMTP server is running on localhost without authentication. For real-world scenarios, you’ll likely use a remote SMTP server, often requiring authentication.
require 'net/smtp'
message_body = <<~MESSAGE_ENDFrom: Your Name <your_email@example.com>To: Recipient Name <recipient_email@example.com>Subject: Test Email from Ruby (Net::SMTP)
This is a test email message sent using Net::SMTP in Ruby.
Regards,Ruby ScriptMESSAGE_END
begin Net::SMTP.start('localhost', 25) do |smtp| smtp.send_message message_body, 'your_email@example.com', 'recipient_email@example.com' end puts "Email sent successfully!"rescue StandardError => e puts "Error sending email: #{e.message}"endNote: The <<~MESSAGE_END (squiggly heredoc) allows for indented heredocs, stripping leading whitespace. Email headers (From, To, Subject) are crucial and must be formatted correctly, separated from the body by a blank line.
Connecting to a Remote SMTP Server with Authentication:
To use a remote SMTP server (like Gmail, SendGrid, etc.), you’ll need its address, port, and your credentials.
# Example for a generic authenticated SMTP server# Replace with your actual server details and credentials# Net::SMTP.start('smtp.your_mail_provider.com',# 587, # Common port for TLS/STARTTLS# 'your_helo_domain.com', # Often your sending domain# 'your_username',# 'your_password',# :plain) do |smtp|# # ... smtp.send_message ...# end
# For Gmail, you might need to enable 'less secure app access' or use App Passwords.# Gmail's SMTP server: smtp.gmail.com, Port: 587 (TLS) or 465 (SSL - Net::SMTP.enable_ssl before start)# It's often better to use specific mailer gems for services like Gmail due to security and configuration nuances.Sending an HTML Email
Section titled “Sending an HTML Email”To send an email in HTML format, you need to set the Content-Type header to text/html and include a MIME-Version header.
require 'net/smtp'
html_message = <<~MESSAGE_ENDFrom: Your Name <your_email@example.com>To: Recipient Name <recipient_email@example.com>MIME-Version: 1.0Content-Type: text/html; charset=UTF-8Subject: HTML Test Email from Ruby
<html><body> <h1>Hello from Ruby!</h1> <p>This is an email message sent in **HTML format**.</p> <p><a href="https://www.ruby-lang.org">Visit Ruby's Official Website</a></p></body></html>MESSAGE_END
begin Net::SMTP.start('localhost', 25) do |smtp| smtp.send_message html_message, 'your_email@example.com', 'recipient_email@example.com' end puts "HTML Email sent successfully!"rescue StandardError => e puts "Error sending HTML email: #{e.message}"endSending Email with Attachments
Section titled “Sending Email with Attachments”Sending attachments requires constructing a multipart MIME message. This involves defining boundaries to separate different parts of the email (text body, HTML body, attachments). Each part has its own Content-Type and Content-Disposition headers. Attachments are typically Base64 encoded.
Manually constructing multipart emails with Net::SMTP can be complex. For robust attachment handling and multipart emails, using a dedicated mailer gem like Mail is highly recommended as it simplifies these tasks significantly. However, here’s a conceptual example of how it would look with raw Net::SMTP (simplified):
require 'net/smtp'require 'base64' # For Base64.strict_encode64
# --- Configuration ---from_email = 'your_email@example.com'to_email = 'recipient_email@example.com'subject = 'Email with Attachment from Ruby'text_body = "Please find the attached file."file_to_attach_path = './my_document.txt' # Create this file for testing
# Create a dummy file for testing if it doesn't existFile.write(file_to_attach_path, "This is a test document.") unless File.exist?(file_to_attach_path)
# --- Read and encode attachment ---begin file_content = File.read(file_to_attach_path) encoded_content = Base64.strict_encode64(file_content) attachment_filename = File.basename(file_to_attach_path)rescue Errno::ENOENT puts "Error: Attachment file not found at #{file_to_attach_path}" exitend
# --- Construct MIME message ---marker = "MAIL_BOUNDARY_#{Time.now.to_i}_#{rand(1000)}"
message_parts = []message_parts << "From: Your Name <#{from_email}>"message_parts << "To: Recipient Name <#{to_email}>"message_parts << "Subject: #{subject}"message_parts << "MIME-Version: 1.0"message_parts << "Content-Type: multipart/mixed; boundary=\"#{marker}\""message_parts << "\n--#{marker}"message_parts << "Content-Type: text/plain; charset=UTF-8"message_parts << "Content-Transfer-Encoding: 7bit"message_parts << "\n#{text_body}"message_parts << "\n--#{marker}"message_parts << "Content-Type: application/octet-stream; name=\"#{attachment_filename}\""message_parts << "Content-Transfer-Encoding: base64"message_parts << "Content-Disposition: attachment; filename=\"#{attachment_filename}\""message_parts << "\n#{encoded_content}"message_parts << "\n--#{marker}--"
full_message = message_parts.join("\r\n") # Use CRLF for line endings in email
# --- Send email ---begin Net::SMTP.start('localhost', 25) do |smtp| smtp.send_message full_message, from_email, to_email end puts "Email with attachment sent successfully!"rescue StandardError => e puts "Error sending email with attachment: #{e.message}"endImportant Considerations:
- Error Handling: Always include
begin...rescueblocks to catch potential errors like connection failures, authentication issues, or invalid addresses. - Security (TLS/SSL): For secure communication, especially with remote SMTP servers, ensure you are using TLS/STARTTLS (often on port 587) or SSL (often on port 465).
Net::SMTPsupportsenable_starttls_auto(if server supports it) orenable_ssl(for direct SSL connections). Forenable_sslyou might need to create theNet::SMTPobject withNet::SMTP.newthen callenable_ssland thenstartwithout a block, or use OpenSSL context options. Check theNet::SMTPdocumentation for details. - Mailer Gems: For anything beyond simple emails, or for features like templates, advanced attachment handling, and easier configuration for various email providers, consider using gems like
Mail(github.com/mikel/mail) or Action Mailer (if you are using Ruby on Rails). These gems abstract away many complexities ofNet::SMTP. - Email Headers and Formatting: Pay close attention to RFC standards for email headers and MIME formatting to ensure your emails are rendered correctly by various email clients.
For comprehensive details, refer to the official Ruby documentation for the Net::SMTP class.