EOFError 错误尝试通过带有 Rails 3.1.3 的 SMTP 使用 Amazon SES

Posted

技术标签:

【中文标题】EOFError 错误尝试通过带有 Rails 3.1.3 的 SMTP 使用 Amazon SES【英文标题】:EOFError error trying to use Amazon SES via SMTP with Rails 3.1.3 【发布时间】:2012-01-24 09:21:02 【问题描述】:

我有一个 Rails 应用程序配置为通过 SMTP 使用 Amazon SES。但是,当我尝试发送电子邮件时,它似乎在一分钟后超时,并且我收到了 EOFError。闻起来像是配置问题——电子邮件似乎构造良好,我可以从 AWS SES 控制台向自己发送测试电子邮件。这是在沙盒模式下,应用程序在开发模式下运行,但发送和接收电子邮件都已通过 SES 验证,并且 development.rb 是这样设置的:

config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp

我已经尝试了一百万种配置变体;这开始让我发疯了。任何帮助或指导将非常非常感激。更多详情:

我在初始化程序中的 smtp 配置:

ActionMailer::Base.smtp_settings = 
  :address        => "email-smtp.us-east-1.amazonaws.com",
  :port           => "465",
  :authentication => :plain,
  :enable_starttls_auto => true,
  :user_name      => "1234",
  :password       => "abcde"
 

有错误的日志,为简洁起见被截断:

Sent mail to john@phu.com (59929ms)
Date: Tue, 20 Dec 2011 03:08:37 -0800
From: contact@phu.com
To: john@phu.com
Message-ID: <4ef06cb5ed3c_d73c3fc604c34d4491943@Johns-MacBook-Pro.local.mail>
Subject: Your invitation to Phu
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE html>
....

Completed 500 Internal Server Error in 60564ms

EOFError (end of file reached):
  app/controllers/admin_controller.rb:61:in `block in send_invite'
  app/controllers/admin_controller.rb:46:in `send_invite'

【问题讨论】:

您的 ISP 是否允许端口 465 上的出站连接?您可以将您的亚马逊 smtp 凭证与普通邮件客户端一起使用吗? 你让它工作了吗?因为我有同样的问题... 还没有开始工作——最终通过 smpt 使用 Gmail,这暂时已经足够好了。我将在下面尝试 Mihir 的解决方案并报告(如果可行,请接受答案)。 Frederick,我可以在 Rails 之外使用 smtp——这是我自己的服务器实例,端口是开放的。 【参考方案1】:

还有一个没有来自 Mihir 的猴子补丁解决方案的解决方案(根据 AWS SES 文档,http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/SMTP.Connecting.html 是 TLS 包装器解决方案),使用端口 587 和 :enable_starttls_auto 选项(STARTTLS 解决方案)。所以修改后的配置是这样的:

config.action_mailer.default_url_options =  host: “<example.com>” 
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = 
    :address: “email-smtp.us-east-1.amazonaws.com”,
    :port: 587,
    :domain: “<example.com>”,
    :authentication: :login,
    :user_name: “<your aws smtp username>”,
    :password: “<your aws smtp password>”,
    :enable_starttls_auto => true

【讨论】:

根据docs,端口465用于ssmtp(smtp over SSL)。对于带有 STARTTLS 的 SMTP,您需要使用您发现的端口 25 或 587。【参考方案2】:

如果您想使用 SMTP(而不是 AWS-SES gem),这是一个解决方案

http://blog.readypulse.com/2012/01/06/amazon-ses-smtp-emails-using-rails-3-1-in-three-easy-steps/

注意事项

AWS SMTP 仅适用于 TLS AWS SMTP 不支持 STARTTLS ActionMailer 的配置没有简单的 TLS 开关。 后续步骤

在您的 AWS 控制台上启用 SMTP 支持 – 请参阅此处的说明。 在 config/initializers 目录下创建一个初始化程序。我将其命名为 amazon_ses.rb 并将以下代码添加到资金补丁 ActionMailer 的 SMTP 设置中。

module Net
    class SMTP
        def tls?
            true
        end
    end
end

在您的 development.rb 和 production.rb 文件中添加以下代码。修改设置以匹配您的环境。

config.action_mailer.default_url_options =  host: “<example.com>” 
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = 
    address: “email-smtp.us-east-1.amazonaws.com”,
    port: 465,
    domain: “<example.com>”,
    authentication: :login,
    user_name: “<your aws smtp username>”,
    password: “<your aws smtp password>”

【讨论】:

当我将模块更改与邮件设置放在同一个文件中时,我得到了这个工作。 (在 Rails 3.2 上)我必须将 require 'net/smtp' 添加到初始化文件的顶部(module Net 上方)。我认为它正在加载初始化程序,然后稍后加载实际的库,覆盖猴子补丁。 这对我有用,添加了以下 smtp_settings: :openssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :enable_starttls_auto => true 我正在使用 Ruby 1.8.7 和 Rails 2.3.5 在我的测试中(Ruby 1.8.7、Rails 2.3.15),当使用端口 25 和 465 时需要此补丁,但对于 587 则不需要。 不幸的是,对我来说唯一的解决方案就是这个猴子补丁【参考方案3】:

我在开发模式下使用 Rails 2.3 和 Ruby 1.8.7 并使用沙盒 SES 帐户向/从经过验证的发件人发送数据时遇到了同样的问题。

我通过添加unofficial aws-ses gem 解决了这个问题。将其粘贴到您的 Gemfile 中,然后将 smtp 设置替换为以下 5 行:

  # Configure mail sending options: Use AWS-SES for all environments
  config.after_initialize do
    ActionMailer::Base.delivery_method = :amazon_ses
    ActionMailer::Base.custom_amazon_ses_mailer = AWS::SES::Base.new(:secret_access_key => 'asfd/1234', :access_key_id => 'ABCD')
  end

然后发送按预期工作......这告诉我电子邮件本身设置正确。

我进行了很多谷歌搜索,但没有看到任何确认 SES-SMTP 与 Rails 2.3 + Ruby 1.8.7 兼容。除了您和我的经验之外,我也没有发现任何明确否认它的东西。

如果您找到解决方案,请告诉我们!

【讨论】:

【参考方案4】:

在发送 EHLO 命令之前,SES 需要 SSL 会话。

我知道 System.Net.Mail 不适用于 SES,因为 System.Net.Mail 在 SMTP 会话开始后启动 TLS。

【讨论】:

感谢您的建议,但如果我正确阅读 this commit,ActionMailer(Rails 等效于 System.Net.Mail)会在开始会话之前启动 TLS。【参考方案5】:

我在 Rails 3.2.12 上进行了这项工作,将 require 'net/smtp' 添加到初始化程序文件中,模块更改如下:

require 'net/smtp'

  module Net
    class SMTP
      def tls?
        true
      end
    end
 end

【讨论】:

以上是关于EOFError 错误尝试通过带有 Rails 3.1.3 的 SMTP 使用 Amazon SES的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4:EOFError:仅在开发中的任何电子邮件后到达文件结尾

EOFError: 文件末尾到达 Net::HTTP 问题

Rails:创建/更新记录时出现 EOF 错误

添加带有rails迁移错误的整数数组列

带有设计的 Rails 3:没有路线匹配 /d/users/sign_out

创建/更新记录时EOF错误:轨