簡體   English   中英

Rails應用程序不會在JRuby下發送郵件(通過sendmail)

[英]Rails app won't send mail (via sendmail) under JRuby

將我的Rails 2.3應用程序從MRI Ruby 1.8.7切換到JRuby 1.6.5后,該應用程序無法再發送郵件。 我正在使用ActionMailer:

class MessageMailer < ActionMailer::Base
  def message(msg, recipient, reply_to_email=nil)
    template = (msg.message_type.nil?) ? "default" : msg.message_type.name.downcase.gsub(' ', '_')

    recipients recipient
    subject msg.subject
    from (msg.sender.nil? or msg.sender.email.blank?) ? "\"no-reply\" <#{SYSTEM_EMAIL_ADDRESS}>" : msg.sender.email
    content_type "text/html"
    body render_message(template, :message => msg)
    reply_to reply_to_email || ((msg.sender.nil? or msg.sender.email.blank?) ? "\"no-reply\" <#{SYSTEM_EMAIL_ADDRESS}>" : msg.sender.email)
  end

  ...
end

MessageMailer.deliver_message(...)

這可能無關緊要,因為這一切都在MRI Ruby 1.8.7下起作用。

Rails應用程序配置為在config / environments / production.rb中使用sendmail:

config.action_mailer.delivery_method = :sendmail

更有趣的是sendmail日志(/var/log/mail.log):

# Sending mail under MRI Ruby 1.8.7
Jan  5 09:38:49 my sendmail[24755]: q05EcnCr024755: from=edwarda, size=310, class=0, nrcpts=1, msgid=<201201051438.q05EcnCr024755@my.example.org>, relay=edwarda@localhost
Jan  5 09:38:49 my sm-mta[24757]: q05Ecn02024757: from=<edwarda@my.example.org>, size=516, class=0, nrcpts=1, msgid=<201201051438.q05EcnCr024755@my.example.org>, proto=ESMTP, daemon=MTA-v4, relay=localhost [127.0.0.1]
Jan  5 09:38:49 my sendmail[24755]: q05EcnCr024755: to=me@example.com, ctladdr=edwarda (1011/1012), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30310, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (q05Ecn02024757 Message accepted for delivery)
Jan  5 09:38:49 my sm-mta[24759]: STARTTLS=client, relay=aspmx.l.google.com., version=TLSv1/SSLv3, verify=FAIL, cipher=RC4-SHA, bits=128/128
Jan  5 09:38:49 my sm-mta[24759]: q05Ecn02024757: to=<me@example.com>, ctladdr=<edwarda@my.example.org> (1011/1012), delay=00:00:00, xdelay=00:00:00, mailer=esmtp, pri=120516, relay=aspmx.l.google.com. [74.125.45.27], dsn=2.0.0, stat=Sent (OK 1325774329 o43si18661797yhk.140)

# Sending mail under JRuby 1.6.5
Jan  5 11:10:26 my sendmail[7623]: q05GAQkH007623: from=edwarda, size=199, class=0, nrcpts=0, relay=edwarda@localhost

請注意,當我運行JRuby時,nrcpts(收件人數)為0,運行1.8.7時為1。

我正在使用完全相同的代碼和寶石,除了我為JRuby使用這些寶石:

gem 'activerecord-jdbc-adapter', '<= 1.2.0', :require => false
gem 'activerecord-jdbcpostgresql-adapter', '<= 1.2.0', :require => 'jdbc_adapter'
gem 'ffi-ncurses'
gem 'jruby-openssl'
gem 'torquebox', '2.0.0.beta1', :platforms => 'jruby'
gem 'torquebox-rake-support', :platforms => 'jruby'
gem 'torquebox-capistrano-support', '2.0.0.beta1'

如果有用,這是我的Gemfile.lock

我的Rails日志中沒有有趣或異常的輸出; 只有通常的成功消息。

編輯:我不能在我的開發(OSX)機器上重現此問題。

有關為什么收件人可能會迷路或者我可能會對此進行故障排除的任何想法?

這與JRuby錯誤有關: http : //jira.codehaus.org/browse/JRUBY-6162

顯然IO.popen在嘗試執行sendmail命令時過早關閉。 在上游修復之前,這個猴子補丁可以包含在初始化程序中以解決問題:

Rails 2:

module ActionMailer
  class Base
    def perform_delivery_sendmail(mail)
      sendmail_args = sendmail_settings[:arguments]
      sendmail_args += " -f \"#{mail['return-path']}\"" if mail['return-path']

      IO.popen("#{sendmail_settings[:location]} #{sendmail_args}", "r+") do |f| #r+ geht, w+ geht nicht richtig, bzw. nur manchmal
        f.puts mail.encoded.gsub(/\r/, '')
        f.close_write
        sleep 1 # <---- added this line in order to give sendmail some time to process
      end
    end
  end
end

Rails 3:

module Mail
  class Sendmail

    def initialize(values)
      self.settings = { :location       => '/usr/sbin/sendmail',
                        :arguments      => '-i -t' }.merge(values)
    end

    attr_accessor :settings

    def deliver!(mail)
      envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
      return_path = "-f \"#{envelope_from.to_s.shellescape}\"" if envelope_from

      arguments = [settings[:arguments], return_path].compact.join(" ")

      Sendmail.call(settings[:location], arguments, mail.destinations.collect(&:shellescape).join(" "), mail)
    end

    def Sendmail.call(path, arguments, destinations, mail)
      IO.popen("#{path} #{arguments} #{destinations}", "r+") do |io|
        io.puts mail.encoded.to_lf
        io.close_write  # <------ changed this from flush to close_write
        sleep 1 # <-------- added this line
      end
    end
  end
end

最有可能的是較舊的版本向“ sendmail -t”傳遞了一條不包含任何收件人標頭的消息。 -t告訴sendmail使用這些標頭來確定郵件的去向,因此,如果沒有它們,您將在from =行的日志中得到nrcpts = 0,並且消息的to =行也沒有記錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM