假设你有一个正在运行的Ruby应用程序,并需要在其中添加一个电子邮件交付功能。这可能与用户认证有关,也可能是任何其他类型的交易性电子邮件,这没有什么区别。本教程的目的是帮助你实现用Ruby发送电子邮件。
在Ruby中发送电子邮件的选项
大多数情况下,你可以从三个选项中选择一个。
最简单的一个是使用Net::SMTP类。它提供了通过SMTP发送电子邮件的功能。这个选项的缺点是Net::SMTP缺乏编写电子邮件的功能。你总是可以自己创建它们,但这需要时间。
第二个选择是使用一个专门的Ruby gem,如Mail、Pony或其他。这些解决方案可以让你以简单而有效的方式处理电子邮件活动。Action Mailer是一个通过Rails棱镜的完美电子邮件解决方案。而且,很有可能,这将是你的选择。
第三个选择是 Socket类 。大多数情况下,这个类允许你在进程之间或在一个进程内设置通信。所以,电子邮件的发送也可以用它来实现。然而,事实是,Socket并没有为你提供广泛的功能,你不太可能想用它。
现在,让我们试着用每个描述的解决方案来发送电子邮件。
如何在Ruby中通过Net::SMTP发送邮件
根据我的经验,在普通的网络应用中使用该选项是不常见的。然而,如果你在一些物联网设备上使用mruby(Ruby语言的轻量级实现),通过Net::SMTP发送电子邮件可能是适合的。另外,如果在无服务器计算中使用,例如 AWS Lambda,它也可以做到。先看看这个脚本例子,然后我们再详细介绍。
require 'net/smtp'
message = <<END_OF_MESSAGE
From: YourRubyApp <info@yourrubyapp.com>
To: BestUserEver <your@bestuserever.com>
Subject: Any email subject you want
Date: Tue, 02 Jul 2019 15:00:34 +0800
Lorem Ipsum
END_OF_MESSAGE
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message message,
'info@yourrubyapp.com',
'your@bestuserever.com'
end
这是一个通过SMTP发送文本邮件的简单例子(官方文档可以在这里找到。你可以看到四个标题。发件人,收件人,主题,和日期。请记住,你必须用一个空行将它们与邮件正文分开。同样重要的是连接到SMTP服务器。
Net::SMTP.start('your.smtp.server', 25) do |smtp|
当然,这里会出现你的数据,而不是‘your.smtp.server‘ ,25是一个默认的端口号。如果需要,你可以指定其他细节,如用户名、密码或认证方案(:plain, :login, and :cram_md5)。它可能看起来如下。
`Net::SMTP.start('your.smtp.server', 25, ‘localhost’, ‘username’, ‘password’ :plain) do |smtp|`
在这里,你将使用纯文本格式的用户名和密码连接到SMTP服务器,而客户的主机名将被识别为localhost。
之后,你可以使用send_message方法,并指定发件人和收件人的地址作为参数。SMTP.start的块状形式(`Net::SMTP.start('your.smtp.server', 2`` 5) do |smtp|` ``)自动关闭SMTP会话。
在Ruby Cookbook中,用Net::SMTP库发送电子邮件被称为极简主义,因为你必须手动建立电子邮件字符串。尽管如此,它并不像你想象的那样毫无希望。让我们看看你如何用HTML内容来增强你的电子邮件,甚至添加一个附件。
在Net::SMTP中发送一个HTML电子邮件
请看这个提到消息部分的脚本例子:
message = <<END_OF_MESSAGE
From: YourRubyApp <info@yourrubyapp.com>
To: BestUserEver <your@bestuserever.com>
MIME-Version: 1.0
Content-type: text/html
Subject: Any email subject you want
Date: Tue, 02 Jul 2019 15:00:34 +0800
A bit of plain text.
<strong>The beginning of your HTML content.</strong>
<h1>And some headline, as well.</h1>
END_OF_MESSAGE
除了邮件正文中的HTML标签外,我们还有两个额外的标头:MIME-Version 和Content-type 。 MIME指的是多用途互联网邮件扩展(Multipurpose Internet Mail Extensions)。它是互联网电子邮件协议的一个扩展,允许你在一个信息体中结合不同的内容类型。MIME-Version 的值通常为1.0。它表示一个消息是MIME格式的。
至于Content-type 标头,一切都很清楚。在我们的例子中,我们有两种类型--HTML和纯文本。另外,要确保使用定义边界来分隔这些内容类型。
除了MIME-Version和Content-type,你可以使用其他MIME头。
-Content-Disposition - 指定展示风格(内联或附件)。
-Content-Transfer-Encoding - 表示二进制到文本的编码方案(7bit, quoted-printable, base64, 8bit, or binary)。
在 Net::SMTP 中发送带有附件的电子邮件
让我们添加一个附件,比如说一个PDF文件。在这种情况下,我们需要将Content-type 更新为 multipart/mixed。另外,使用pack("m") 函数对附件文件进行base64编码。
require 'net/smtp'
filename = "/tmp/Attachment.pdf"
file_content = File.read(filename)
encoded_content = [file_content].pack("m") # base64
marker = "AUNIQUEMARKER"
之后,你需要定义你的电子邮件的三个部分:
第1部分 - 主要头文件
part1 = <<END_OF_MESSAGE
From: YourRubyApp <info@yourrubyapp.com>
To: BestUserEver <your@bestuserever.com>
Subject: Adding attachment to email
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary = #{marker}
--#{marker}
END_OF_MESSAGE
第2部分 - 消息动作
part2 = <<END_OF_MESSAGE
Content-Type: text/html
Content-Transfer-Encoding:8bit
A bit of plain text.
<strong>The beginning of your HTML content.</strong>
<h1>And some headline, as well.</h1>
--#{marker}
END_OF_MESSAGE
第3部分 - 附件
part3 = <<END_OF_MESSAGE
Content-Type: multipart/mixed; name = "#{filename}"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename = "#{filename}"
#{encoded_content}
--#{marker}--
END_OF_MESSAGE
现在,我们可以把所有的部分放在一起,最后完成脚本。这将是它的样子:
require 'net/smtp'
filename = "/tmp/Attachment.pdf"
file_content = File.read(filename)
encoded_content = [file_content].pack("m") # base64
marker = "AUNIQUEMARKER"
part1 = <<END_OF_MESSAGE
From: YourRubyApp <info@yourrubyapp.com>
To: BestUserEver <your@bestuserever.com>
Subject: Adding attachment to email
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary = #{marker}
--#{marker}
END_OF_MESSAGE
part2 = <<END_OF_MESSAGE
Content-Type: text/html
Content-Transfer-Encoding:8bit
A bit of plain text.
<strong>The beginning of your HTML content.</strong>
<h1>And some headline, as well.</h1>
--#{marker}
END_OF_MESSAGE
part3 = <<END_OF_MESSAGE
Content-Type: multipart/mixed; name = "#{filename}"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename = "#{filename}"
#{encoded_content}
--#{marker}--
END_OF_MESSAGE
message = part1 + part2 + part3
begin
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message message,
'info@yourrubyapp.com',
'your@bestuserever.com'
end
我可以在Net::SMTP中向多个收件人发送一封邮件吗?
当然可以,send_message希望第二个和随后的参数都包含收件人的电子邮件。例如,这样:
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message message,
'info@yourrubyapp.com',
'your@bestuserever1.com',
‘your@bestuserever2.com’,
‘your@bestuserever3.com
end
用于发送电子邮件的最佳Ruby Gems
在Ruby生态系统中,你可以找到特定的电子邮件宝石,可以改善你的电子邮件发送体验。
Ruby Mail
这个库的目的是提供一个单一的访问点来管理所有与电子邮件相关的活动,包括发送和接收电子邮件。
Pony
你可能听说过一个关于用一个命令发送电子邮件的童话故事。请抓紧你的帽子,因为它是真实的,由Ponygem提供。
ActionMailer
这是在Rails上发送电子邮件的最流行的宝石。如果你的应用程序是写在它上面的,ActionMailer肯定会出现。它可以让你使用邮件类和视图来发送邮件。
使用Mailtrap测试使用Net::SMTP发送邮件的情况
设置非常简单。一旦你进入了你的演示收件箱,复制SMTP设置标签上的SMTP凭证并将其插入你的代码中。或者你可以在集成部分获得一个现成的简单信息模板。只要选择你的应用所使用的编程语言或框架。
Ruby
require 'net/smtp'
message = <<END_OF_MESSAGE
From: YourRubyApp <info@yourrubyapp.com>
To: BestUserEver <your@bestuserever.com>
Subject: Any email subject you want
Date: Tue, 02 Jul 2019 15:00:34 +0800
Lorem Ipsum
END_OF_MESSAGE
Net::SMTP.start('smtp.mailtrap.io', 587, '<username>', '<password>', :cram_md5) do |smtp|
smtp.send_message message,
'info@yourrubyapp.com',
'your@bestuserever.com'
end
如果一切正常,你会在Mailtrap演示版收件箱中看到你的信息。另外,你可以尝试检查你的带有HTML内容和附件的邮件。
你刚刚阅读了关于如何在Ruby中测试和发送邮件的完整教程。希望你喜欢它!