Ruby Mail 库使用教程
【免费下载链接】mail A Really Ruby Mail Library 项目地址: https://gitcode.com/gh_mirrors/ma/mail
概述
Ruby Mail 是一个功能强大的纯 Ruby 邮件处理库,专为简化电子邮件生成、解析和发送而设计。它完全兼容 RFC5322 和 RFC6532 标准,支持多部分邮件、附件处理、多种编码方式,并提供了灵活的配置选项。
本教程将带你全面了解 Ruby Mail 的核心功能和使用方法,从基础配置到高级特性,帮助你轻松处理各种邮件相关任务。
目录
安装与配置
安装 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
支持的传输方法
| 传输方法 | 描述 | 适用场景 |
|---|---|---|
:smtp | SMTP 协议发送 | 标准邮件发送 |
:sendmail | 使用系统 sendmail | Unix/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 项目地址: https://gitcode.com/gh_mirrors/ma/mail
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



