Ruby 发送邮件 – SMTP

在 Ruby 中,通过 SMTP(Simple Mail Transfer Protocol) 发送电子邮件是一个常见需求。Ruby 提供了内置的 net/smtp 库来实现 SMTP 邮件发送,简单高效,适合发送纯文本、HTML 或带附件的邮件。以下是对 Ruby 使用 SMTP 发送邮件的中文讲解,涵盖核心功能、配置、发送邮件的步骤、示例代码及注意事项,力求简洁清晰。


1. SMTP 简介

SMTP 是用于发送电子邮件的标准协议。Ruby 的 net/smtp 库允许通过 SMTP 服务器(如 Gmail、SendGrid)发送邮件,支持身份验证、TLS/SSL 加密等功能。

特点

  • 轻量,直接与 SMTP 服务器交互。
  • 支持多种邮件格式(文本、HTML、附件)。
  • 需要 SMTP 服务器的配置信息(如主机、端口、用户名、密码)。

2. 安装与准备

net/smtp 是 Ruby 标准库的一部分,无需额外安装。直接在代码中引入:

require 'net/smtp'

先决条件

  • SMTP 服务器:如 Gmail、SendGrid 或企业邮箱服务器。
  • 账户信息:需要 SMTP 服务器的主机地址、端口、用户名和密码。
  • Gmail 示例
    • 主机:smtp.gmail.com
    • 端口:587(TLS)或 465(SSL)
    • 用户名:你的 Gmail 地址
    • 密码:应用专用密码(需启用两步验证后生成,详见注意事项)。

3. 发送简单邮件

使用 Net::SMTP 类直接发送邮件,需要构造符合 SMTP 协议的邮件内容。

基本示例

require 'net/smtp'

# 邮件内容
message = <<~MESSAGE
  From: Sender Name <sender@example.com>
  To: Receiver Name <receiver@example.com>
  Subject: Test Email

  This is a test email sent from Ruby!
MESSAGE

# SMTP 配置
smtp = Net::SMTP.new('smtp.gmail.com', 587)
smtp.enable_starttls  # 启用 TLS
smtp.start('gmail.com', 'sender@example.com', 'your_app_password', :login) do |smtp|
  smtp.send_message(message, 'sender@example.com', 'receiver@example.com')
end

说明

  • Net::SMTP.new(host, port):创建 SMTP 连接。
  • enable_starttls:启用 TLS 加密(Gmail 要求)。
  • start(domain, user, password, auth_type):启动 SMTP 会话,auth_type 通常为 :login
  • send_message(message, from, to):发送邮件,message 是格式化的邮件内容。

4. 发送复杂邮件(HTML、附件)

对于 HTML 邮件或带附件的邮件,需要构造 MIME 格式的邮件内容。推荐使用 mail 库(需安装 gem install mail),它是对 net/smtp 的封装,简化复杂邮件的处理。

安装 Mail 库

gem install mail

发送 HTML 邮件

require 'mail'

Mail.defaults do
  delivery_method :smtp, {
    address: 'smtp.gmail.com',
    port: 587,
    domain: 'gmail.com',
    user_name: 'sender@example.com',
    password: 'your_app_password',
    authentication: :login,
    enable_starttls_auto: true
  }
end

mail = Mail.new do
  from    'sender@example.com'
  to      'receiver@example.com'
  subject 'Test HTML Email'
  html_part do
    content_type 'text/html; charset=UTF-8'
    body '<h1>Hello!</h1><p>This is an <b>HTML</b> email sent from Ruby.</p>'
  end
end

mail.deliver

说明

  • Mail.defaults:设置全局 SMTP 配置。
  • html_part:定义 HTML 内容部分。
  • deliver:发送邮件。

发送带附件的邮件

require 'mail'

Mail.defaults do
  delivery_method :smtp, {
    address: 'smtp.gmail.com',
    port: 587,
    user_name: 'sender@example.com',
    password: 'your_app_password',
    authentication: :login,
    enable_starttls_auto: true
  }
end

mail = Mail.new do
  from    'sender@example.com'
  to      'receiver@example.com'
  subject 'Email with Attachment'
  text_part { body 'See the attached file.' }
  add_file 'path/to/file.pdf'  # 添加附件
end

mail.deliver

说明

  • text_part:添加纯文本部分(多部分邮件)。
  • add_file:添加附件,文件路径需有效。

5. 异常处理

发送邮件可能因网络、认证失败等原因抛出异常,需妥善处理。

require 'net/smtp'

begin
  smtp = Net::SMTP.new('smtp.gmail.com', 587)
  smtp.enable_starttls
  smtp.start('gmail.com', 'sender@example.com', 'wrong_password', :login) do |smtp|
    smtp.send_message("From: sender@example.com\nTo: receiver@example.com\nSubject: Test\n\nHello!", 'sender@example.com', 'receiver@example.com')
  end
rescue Net::SMTPAuthenticationError => e
  puts "认证失败: #{e.message}"
rescue Net::SMTPServerBusy => e
  puts "服务器忙: #{e.message}"
rescue => e
  puts "其他错误: #{e.message}"
end

常见异常

  • Net::SMTPAuthenticationError:用户名或密码错误。
  • Net::SMTPServerBusy:服务器拒绝连接。
  • Errno::ECONNREFUSED:无法连接到 SMTP 服务器。

6. 注意事项

  • Gmail 应用专用密码
  • Gmail 要求两步验证,需生成应用专用密码:
    1. 登录 Google 账户 → 安全 → 两步验证 → 应用专用密码。
    2. 生成密码(如 abcd efgh ijkl mnop),用于 password 参数。
  • 编码:邮件内容默认 UTF-8,确保 SMTP 服务器支持。
  • 安全性
  • 使用 enable_starttlsenable_starttls_auto 确保加密传输。
  • 不要硬编码密码,推荐使用环境变量:
    ruby password = ENV['SMTP_PASSWORD']
  • 性能net/smtp 适合简单任务,大量邮件发送推荐使用邮件服务(如 SendGrid)或队列(如 Sidekiq)。
  • 调试
  • 启用调试输出:
    ruby smtp = Net::SMTP.new('smtp.gmail.com', 587) smtp.set_debug_output($stderr)
  • 检查邮件服务器日志或服务商控制台。
  • 现代替代:Rails 的 Action Mailer 或 mail 库提供更高级的功能,简化复杂邮件处理。

7. 综合示例

以下示例结合 mail 库发送带附件和 HTML 内容的邮件,包含错误处理。

require 'mail'

Mail.defaults do
  delivery_method :smtp, {
    address: 'smtp.gmail.com',
    port: 587,
    domain: 'gmail.com',
    user_name: 'sender@example.com',
    password: ENV['SMTP_PASSWORD'] || 'your_app_password',
    authentication: :login,
    enable_starttls_auto: true
  }
end

begin
  mail = Mail.new do
    from    'sender@example.com'
    to      'receiver@example.com'
    subject 'Welcome Email'
    text_part { body 'This is a plain text version.' }
    html_part do
      content_type 'text/html; charset=UTF-8'
      body '<h1>Welcome!</h1><p>This is an <b>HTML</b> email.</p>'
    end
    add_file 'example.pdf'  # 假设文件存在
  end

  mail.deliver
  puts "邮件发送成功"
rescue StandardError => e
  puts "发送失败: #{e.message}"
end

功能

  • 发送包含文本和 HTML 部分的邮件。
  • 添加附件(example.pdf)。
  • 使用环境变量存储密码,增强安全性。

8. 总结

Ruby 的 net/smtp 库提供了直接的 SMTP 邮件发送功能,适合简单邮件任务。结合 mail 库,可以轻松发送 HTML 邮件和附件,支持 TLS 加密和身份验证。注意配置正确的 SMTP 参数(如 Gmail 的应用专用密码),使用异常处理确保健壮性,优先选择 mail 库简化复杂邮件处理。现代应用可结合 Rails 的 Action Mailer 或第三方服务(如 SendGrid)提升效率。

如果你需要更复杂的功能(如批量发送、邮件模板)或有其他问题,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注