在 Heroku 上使用 Postmark API 的 Rails 电子邮件——由对等方重置连接

Posted

技术标签:

【中文标题】在 Heroku 上使用 Postmark API 的 Rails 电子邮件——由对等方重置连接【英文标题】:Rails email using Postmark API on Heroku -- connection reset by peer 【发布时间】:2015-04-23 12:29:28 【问题描述】:

我今天有多处瘀伤,试图同时学习两件事...... Postmark 和 Rails HTTP 请求的 API。

目标:使用 Heroku 的 Postmark 插件发送生产电子邮件。

我正在尝试结合这篇关于 HTTP 请求的文章... http://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html ...使用此 API 参考邮戳... http://developer.postmarkapp.com/developer-send-api.html

不幸的是,来自 Postmark 的示例是在 curl 中完成的,我没有成功地将它们转换为 HTTP 请求。我怀疑问题集中在标题上——除了正文之外的传输部分。

下面代码中的救援子句捕获了错误“对等方重置连接”。在这一点上,我不知道我是否接近提供邮戳身份验证的标头的正确格式。

我有正确的服务器令牌(在配置条目中)并且发件人电子邮件已获得所需的邮戳签名。

   def send_production_email(email_address, subject, email_body)

      # Use API to interact with Heroku add-on Postmark
      # http://developer.postmarkapp.com/developer-send-api.html

      uri = URI('https://api.postmarkapp.com/email')

      # Form the request
      req = Net::HTTP::Post.new(uri)

      # Set request headers -- SUSPECT THIS IS WRONG
      req['Accept'] = 'application/json'
      req['Content-Type'] = 'application/json'
      req['X-Postmark-Server-Token'] = Rails.application.config.postmark_token

      rbody =
          'From' => 'Support <michael@mydomain.com>',
          'To' => email_address,
          'Subject' => subject,
          'HtmlBody' => wrap_html(email_body),
          'TextBody' => email_body
      .to_json

      req.body = rbody

      # Send the request, waiting for the response

      begin
         response = Net::HTTP.new(uri.host, uri.port).start |http| http.request(req) 
      rescue Exception => e
         logthis("http request error: #e.message")
         return
      end

      # ...parsing section omitted since I do not get that far...

   end

第二次尝试以这种方式格式化,但导致相同的对等重置错误:

      rbody =
          'From' => 'Support <michael@disambiguator.com>', # TODO: replace email when domain is live
          'To' => email_address,
          'Subject' => subject,
          'HtmlBody' => wrap_html(email_body),
          'TextBody' => email_body
      .to_json

      uri = URI('https://api.postmarkapp.com/email')

      http = Net::HTTP.new(uri.host, uri.port)
      # http.use_ssl = true

      request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'X-Postmark-Server-Token' => Rails.application.config.postmark_token)
      request.body = rbody

      # Send the request, waiting for the response

      begin
         response = http.request(request)
      rescue Exception => e
         logthis("http request error: #e.message")
         return
      end

感谢您的指导!

【问题讨论】:

【参考方案1】:

我是 Wildbit 的员工,也是 official Postmark Ruby gem 的维护者。

“对等方重置连接”错误是由于您尝试将未加密的 HTTP 请求发送到期望通过 HTTPS 进行安全通信的端点。所以,如果你改变这一行:

Net::HTTP.new(uri.host, uri.port).start |http| http.request(req) 

到:

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
response = http.start  |http| http.request(req) 

那么您应该能够收到来自 API 的响应。我看到你在第二个例子中有这一行,但它被注释了。由于您将其作为练习进行,我想补充一点,当使用 net/http 时,您通常不必使用像 Net::HTTP::Post 这样的底层类。使用 Net::HTTP 类的实例提供的更高级别的 API 通常更简单。下面是一个示例,说明如何使用它来简化您的方法:

def send_production_email(email_address, subject, email_body)
  uri = URI('https://api.postmarkapp.com/email')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  headers = 'Accept' => 'application/json',
             'Content-Type' => 'application/json',
             'X-Postmark-Server-Token' => Rails.application.config.postmark_token
  payload = 'From' => 'tema@wildbit.com',
             'To' => email_address,
             'Subject' => subject,
             'HtmlBody' => email_body,
             'TextBody' => email_body

  http.post(uri.request_uri, payload.to_json, headers)
rescue => e
  puts "http request error: #e.message"
end

如果您对net/http 在官方 Postmark Ruby gem 中的使用方式感兴趣,请查看HttpClient class’ source。

【讨论】:

谢谢你,@temochka。我非常喜欢让事情变得更简单!在第二个更简单的示例中,您将如何提取所需的响应以便检查错误代码? 我也很感谢您引用了邮戳宝石。我改用它,让生活变得更简单。它在 Heroku 上效果很好! @temochka @vbsql7 不客气!回答你的问题,当请求成功时,我只返回一个解析的 JSON 文档作为 Ruby 哈希。否则,抛出一个将 Net::HTTP::Response 对象作为构造函数参数的专用异常子类听起来是个不错的选择。

以上是关于在 Heroku 上使用 Postmark API 的 Rails 电子邮件——由对等方重置连接的主要内容,如果未能解决你的问题,请参考以下文章

图片未显示在 Gmail 中 - 使用 django python-postmark

如何在 node.js 上使用邮戳电子邮件?

在 Heroku 上使用 React、Axios 访问内部 API

在 Heroku 上部署 Django API + React 应用程序

在 Heroku 上使用 Rails API 部署 Create-React-App

在 Heroku 上部署 React 应用和 API 的最佳实践