Ruby Mail 库使用教程

Ruby Mail 库使用教程

【免费下载链接】mail A Really Ruby Mail Library 【免费下载链接】mail 项目地址: https://gitcode.com/gh_mirrors/ma/mail

概述

Ruby Mail 是一个功能强大的纯 Ruby 邮件处理库,专为简化电子邮件生成、解析和发送而设计。它完全兼容 RFC5322 和 RFC6532 标准,支持多部分邮件、附件处理、多种编码方式,并提供了灵活的配置选项。

本教程将带你全面了解 Ruby Mail 的核心功能和使用方法,从基础配置到高级特性,帮助你轻松处理各种邮件相关任务。

目录

  1. 安装与配置
  2. 创建邮件
  3. 邮件发送
  4. 邮件接收
  5. 附件处理
  6. 多部分邮件
  7. 编码与解码
  8. 错误处理与测试
  9. 高级特性
  10. 最佳实践

安装与配置

安装 Gem

# 在 Gemfile 中添加
gem 'mail'

# 或者直接安装
gem install mail

基本配置

require 'mail'

# 设置默认配置
Mail.defaults do
  # SMTP 发送配置
  delivery_method :smtp, {
    address:              'smtp.example.com',
    port:                 587,
    domain:               'example.com',
    user_name:            'your_username',
    password:             'your_password',
    authentication:       'plain',
    enable_starttls_auto: true
  }

  # POP3 接收配置
  retriever_method :pop3, {
    address:    'pop.example.com',
    port:       995,
    user_name:  'your_username',
    password:   'your_password',
    enable_ssl: true
  }
end

支持的传输方法

传输方法描述适用场景
:smtpSMTP 协议发送标准邮件发送
:sendmail使用系统 sendmailUnix/Linux 系统
:file保存到文件测试和调试
:logger记录到日志开发和测试
:test测试模式单元测试

创建邮件

基本邮件创建

# 方法1: 使用块语法
mail = Mail.new do
  from    'sender@example.com'
  to      'recipient@example.com'
  subject '测试邮件主题'
  body    '这是邮件正文内容'
end

# 方法2: 使用哈希参数
mail = Mail.new(
  from:    'sender@example.com',
  to:      'recipient@example.com',
  subject: '测试邮件主题',
  body:    '这是邮件正文内容'
)

# 方法3: 逐步设置
mail = Mail.new
mail.from = 'sender@example.com'
mail.to = 'recipient@example.com'
mail.subject = '测试邮件主题'
mail.body = '这是邮件正文内容'

邮件头字段操作

mail = Mail.new

# 设置标准头字段
mail['From'] = 'sender@example.com'
mail[:to] = 'recipient@example.com'
mail.subject = '邮件主题'

# 添加自定义头字段
mail['X-Custom-Header'] = '自定义值'
mail['X-Priority'] = '1'

# 设置多个收件人
mail.to = ['user1@example.com', 'user2@example.com']
mail.cc = 'cc_user@example.com'
mail.bcc = 'bcc_user@example.com'

# 设置回复地址
mail.reply_to = 'reply@example.com'

日期和消息ID

# 自动生成消息ID
mail = Mail.new do
  to   'recipient@example.com'
  body '邮件内容'
end
puts mail.message_id # => <随机生成的ID>

# 自定义消息ID
mail.message_id = '<custom-id@example.com>'

# 设置日期
mail.date = Time.now

邮件发送

基本发送方式

# 直接发送
Mail.deliver do
  from     'sender@example.com'
  to       'recipient@example.com'
  subject  '测试邮件'
  body     '这是一封测试邮件'
end

# 创建后发送
mail = Mail.new do
  from    'sender@example.com'
  to      'recipient@example.com'
  subject '测试邮件'
  body    '邮件内容'
end
mail.deliver!

使用不同传输方法

# SMTP 发送
mail.delivery_method :smtp, address: 'smtp.gmail.com', port: 587

# Sendmail 发送
mail.delivery_method :sendmail

# 保存到文件
mail.delivery_method :file, location: '/path/to/emails'

# 记录到日志
mail.delivery_method :logger

# 测试模式
mail.delivery_method :test

批量发送配置

# 配置多个SMTP服务器
smtp_settings = {
  address:              'smtp.example.com',
  port:                 587,
  domain:               'example.com',
  user_name:            'username',
  password:             'password',
  authentication:       'plain',
  enable_starttls_auto: true
}

Mail.defaults do
  delivery_method :smtp, smtp_settings
end

# 批量发送邮件
recipients = ['user1@example.com', 'user2@example.com', 'user3@example.com']

recipients.each do |recipient|
  Mail.deliver do
    from    'sender@example.com'
    to      recipient
    subject "个性化主题 - #{recipient}"
    body    "尊敬的 #{recipient}, 这是您的个性化邮件"
  end
end

邮件接收

POP3 邮件接收

# 配置POP3
Mail.defaults do
  retriever_method :pop3, {
    address:    'pop.gmail.com',
    port:       995,
    user_name:  'your_email@gmail.com',
    password:   'your_password',
    enable_ssl: true
  }
end

# 接收邮件
emails = Mail.all
puts "总共收到 #{emails.length} 封邮件"

# 获取第一封邮件
first_email = Mail.first
puts "发件人: #{first_email.from}"
puts "主题: #{first_email.subject}"
puts "正文: #{first_email.body.decoded}"

# 获取最后10封邮件
recent_emails = Mail.find(what: :first, count: 10, order: :desc)

IMAP 邮件接收

# 配置IMAP
Mail.defaults do
  retriever_method :imap, {
    address:    'imap.gmail.com',
    port:       993,
    user_name:  'your_email@gmail.com',
    password:   'your_password',
    enable_ssl: true
  }
end

# 搜索特定条件的邮件
emails = Mail.find(what: :first, count: 5, keys: ['SUBJECT', '重要'])

邮件解析和处理

# 从文件读取邮件
mail = Mail.read('/path/to/email.eml')

# 从字符串解析
mail_string = "From: sender@example.com\nTo: recipient@example.com\nSubject: Test\n\nBody"
mail = Mail.new(mail_string)

# 获取邮件信息
puts "发件人: #{mail.from}"
puts "收件人: #{mail.to}"
puts "主题: #{mail.subject}"
puts "日期: #{mail.date}"
puts "消息ID: #{mail.message_id}"

# 检查邮件属性
puts "是否多部分: #{mail.multipart?}"
puts "是否有附件: #{mail.attachments.any?}"

附件处理

添加附件

# 方法1: 使用文件路径
mail.add_file('/path/to/file.pdf')

# 方法2: 指定内容和文件名
mail.attachments['document.pdf'] = File.read('/path/to/document.pdf')

# 方法3: 详细配置
mail.attachments['image.jpg'] = {
  mime_type: 'image/jpeg',
  content: File.read('/path/to/image.jpg')
}

# 方法4: 使用add_file方法
mail.add_file(
  filename: 'report.pdf',
  content: File.read('/path/to/report.pdf')
)

处理接收的附件

mail = Mail.read('email_with_attachments.eml')

# 遍历所有附件
mail.attachments.each do |attachment|
  puts "附件名称: #{attachment.filename}"
  puts "MIME类型: #{attachment.content_type}"
  puts "文件大小: #{attachment.decoded.bytesize} bytes"
  
  # 保存附件
  if attachment.content_type.start_with?('image/')
    File.open("images/#{attachment.filename}", 'wb') do |f|
      f.write(attachment.decoded)
    end
  elsif attachment.content_type == 'application/pdf'
    File.open("documents/#{attachment.filename}", 'wb') do |f|
      f.write(attachment.decoded)
    end
  end
end

附件类型检测

# 检查特定类型的附件
image_attachments = mail.attachments.select do |attachment|
  attachment.content_type.start_with?('image/')
end

pdf_attachments = mail.attachments.select do |attachment|
  attachment.content_type == 'application/pdf'
end

# 获取附件信息
mail.attachments.each do |attachment|
  puts "文件名: #{attachment.filename}"
  puts "Content-Type: #{attachment.content_type}"
  puts "Content-Disposition: #{attachment.content_disposition}"
  puts "Content-Transfer-Encoding: #{attachment.content_transfer_encoding}"
end

多部分邮件

创建多部分邮件

# 创建文本和HTML双版本邮件
mail = Mail.new do
  from    'sender@example.com'
  to      'recipient@example.com'
  subject '多部分测试邮件'
  
  text_part do
    body '这是纯文本版本的内容'
  end
  
  html_part do
    content_type 'text/html; charset=UTF-8'
    body '<h1>这是HTML版本</h1><p>包含格式化的内容</p>'
  end
end

复杂多部分结构

# 创建包含内联图片的多部分邮件
mail = Mail.new do
  from    'sender@example.com'
  to      'recipient@example.com'
  subject '包含内联图片的邮件'
  
  text_part do
    body '这是纯文本内容,包含图片引用: [图片1]'
  end
  
  html_part do
    content_type 'text/html; charset=UTF-8'
    body <<-HTML
      <h1>HTML内容</h1>
      <p>这是HTML版本,包含内联图片:</p>
      <img src="cid:image1" alt="图片1">
    HTML
  end
  
  # 添加内联图片
  attachments.inline['image1.jpg'] = File.read('/path/to/image1.jpg')
end

邮件部分操作

mail = Mail.read('multipart_email.eml')

# 检查邮件结构
puts "是否多部分: #{mail.multipart?}"
puts "部分数量: #{mail.parts.length}"

# 遍历所有部分
mail.parts.each_with_index do |part, index|
  puts "部分 #{index + 1}:"
  puts "  Content-Type: #{part.content_type}"
  puts "  是否有附件: #{part.attachment?}"
  puts "  内容大小: #{part.body.decoded.bytesize} bytes"
end

# 获取特定类型的内容
text_part = mail.text_part
html_part = mail.html_part

puts "纯文本内容: #{text_part.body.decoded}" if text_part
puts "HTML内容: #{html_part.body.decoded}" if html_part

编码与解码

字符编码处理

# 设置邮件编码
mail = Mail.new do
  from    'sender@example.com'
  to      'recipient@example.com'
  subject '测试中文主题'.encode('UTF-8')
  body    '中文内容测试'.encode('UTF-8')
end

# 自动编码处理
mail.charset = 'UTF-8'

# 手动编码内容
subject = '中文主题'.encode('UTF-8')
body = '中文内容'.encode('UTF-8')

mail.subject = subject
mail.body = body

传输编码

# Base64 编码
mail.body = '需要编码的内容'
mail.body.encoding = 'base64'

# Quoted-Printable 编码
mail.body.encoding = 'quoted-printable'

# 7bit 编码 (默认)
mail.body.encoding = '7bit'

# 8bit 编码
mail.body.encoding = '8bit'

# 二进制编码
mail.body.encoding = 'binary'

编码转换示例

# 处理不同编码的邮件
mail = Mail.read('email_with_different_encoding.eml')

# 获取解码后的内容
decoded_subject = mail.subject
decoded_body = mail.body.decoded

# 检查编码信息
puts "主题编码: #{mail.charset}"
puts "正文编码: #{mail.body.charset}"

# 强制转换编码
if mail.body.charset != 'UTF-8'
  converted_body = mail.body.decoded.force_encoding('UTF-8')
  puts "转换后内容: #{converted_body}"
end

错误处理与测试

异常处理

begin
  mail = Mail.new do
    from    'sender@example.com'
    to      'recipient@example.com'
    subject '测试邮件'
    body    '内容'
  end
  
  mail.deliver!
  
rescue Net::SMTPAuthenticationError => e
  puts "SMTP认证失败: #{e.message}"
  
rescue Net::SMTPServerBusy => e
  puts "SMTP服务器繁忙: #{e.message}"
  
rescue Net::SMTPUnknownError => e
  puts "未知SMTP错误: #{e.message}"
  
rescue => e
  puts "其他错误: #{e.message}"
end

测试模式

# 配置测试模式
Mail.defaults do
  delivery_method :test
end

# 发送测试邮件
Mail.deliver do
  from    'test@example.com'
  to      'recipient@example.com'
  subject '测试邮件'
  body    '测试内容'
end

# 检查发送的邮件
deliveries = Mail::TestMailer.deliveries
puts "已发送邮件数量: #{deliveries.length}"

if deliveries.any?
  last_email = deliveries.last
  puts "最后发送的邮件主题: #{last_email.subject}"
  puts "收件人: #{last_email.to}"
end

# 清空测试邮件
Mail::TestMailer.deliveries.clear

RSpec 测试示例

# spec/mail_spec.rb
require 'spec_helper'
require 'mail'

RSpec.describe '邮件发送' do
  include Mail::Matchers
  
  before do
    Mail.defaults do
      delivery_method :test
    end
    Mail::TestMailer.deliveries.clear
  end
  
  it '发送欢迎邮件' do
    Mail.deliver do
      from    'welcome@example.com'
      to      'newuser@example.com'
      subject '欢迎加入'
      body    '欢迎使用我们的服务!'
    end
    
    expect(Mail).to have_sent_email
    expect(Mail).to have_sent_email.from('welcome@example.com')
    expect(Mail).to have_sent_email.to('newuser@example.com')
    expect(Mail).to have_sent_email.with_subject('欢迎加入')
    expect(Mail).to have_sent_email.with_body('欢迎使用我们的服务!')
  end
  
  it '发送带附件的邮件' do
    Mail.deliver do
      from    'admin@example.com'
      to      'user@example.com'
      subject '重要文档'
      body    '请查收附件'
      add_file '/path/to/document.pdf'
    end
    
    expect(Mail).to have_sent_email.with_any_attachments
    expect(Mail).to have_sent_email.with_attachments(an_attachment_with_filename('document.pdf'))
  end
end

高级特性

观察者和拦截器

# 邮件发送观察者
class EmailLogger
  def delivered_email(mail)
    puts "邮件已发送: #{mail.subject} 给 #{mail.to}"
    puts "发送时间: #{Time.now}"
  end
end

# 邮件发送拦截器
class EmailInterceptor
  def delivering_email(mail)
    # 修改邮件内容
    mail.subject = "[TEST] #{mail.subject}"
    
    # 重定向到测试地址
    if Rails.env.development?
      mail.to = 'test@example.com'
      mail.cc = nil
      mail.bcc = nil
    end
  end
end

# 注册观察者和拦截器
Mail.register_observer(EmailLogger.new)
Mail.register_interceptor(EmailInterceptor.new)

自定义传输方法

# 创建自定义传输方法
class CustomDeliveryMethod
  def initialize(settings = {})
    @settings = settings
  end
  
  def deliver!(mail)
    # 自定义发送逻辑
    puts "发送邮件: #{mail.subject}"
    puts "收件人: #{mail.to}"
    puts "正文长度: #{mail.body.to_s.length}"
    
    # 这里可以集成第三方服务
    # 例如: API调用、消息队列等
    
    true # 返回成功
  end
end

# 使用自定义传输方法
mail.delivery_method CustomDeliveryMethod, api_key: 'your_api_key'

邮件模板系统

# 邮件模板类
class

【免费下载链接】mail A Really Ruby Mail Library 【免费下载链接】mail 项目地址: https://gitcode.com/gh_mirrors/ma/mail

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值