对于我的部署,我更喜欢在
config/
下的 YML 文件中包含所有 Rails 配置选项。我对action_mailer.smtp_settings
有特别的问题。
我有一个文件,
config/smtp.yml
:
development:
address: localhost
port: 1025
test:
production:
address: smtp.xs4all.nl
port: 465
authentication: plain
user_name: xxxxx
password: xxxxx
tls: true
然后我尝试通过初始化程序包含这些值。
config/initializers/smtp.rb
:
options = YAML.load_file(Rails.root.join('config', 'smtp.yml'))[Rails.env]
options.each do |name, value|
Portfolio::Application.config.action_mailer.smtp_settings[name.to_sym] = value
end unless options.nil?
这会加载
smtp.yml
文件,解析该文件并返回当前环境的哈希值,例如
{"address"=>"smtp.xs4all.nl", "port"=>465, "authentication"=>"plain", "user_name"=>"xxxxx", "password"=>"xxxxx", "tls"=>true}
将键转换为符号并将其添加到 smtp 设置中,例如:
irb(main):002:0> Portfolio::Application.config.action_mailer.smtp_settings
=> {:port=>465, :address=>"smtp.xs4all.nl", :authentication=>"plain", :user_name=>"xxxxx", :password=>"xxxx", :tls=>true}
但是在部署到生产时,这会导致一些冲突,可能是因为某些部分还没有启动。 Capistrano 失败:
* executing "cd -- /var/www/ANT_cms/releases/20131218170336 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile"
servers: ["li153-5.members.linode.com"]
[li153-5.members.linode.com] executing command
** [out :: li153-5.members.linode.com] rake aborted!
** [out :: li153-5.members.linode.com] undefined method `[]=' for nil:NilClass
为什么我的
Portfolio::Application.config.action_mailer.smtp_settings
在这里?我怎样才能确保 actionMailers 配置选项已经加载?
深入挖掘,我发现问题在于
bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile"
只加载一小部分,而不是例如ActionMailer
。
在我的装载机中添加一个提前退出修复了这个
config/initializers/smtp.rb
:
unless Portfolio::Application.config.action_mailer.nil?
options = YAML.load_file(Rails.root.join('config', 'smtp.yml'))[Rails.env]
options.each do |name, value|
Portfolio::Application.config.action_mailer.smtp_settings[name.to_sym] = value
end unless options.nil?
end
然后,下一个问题是生产中的 action_mailer 已设置,但 smtp_settings 不必定义和填充默认值。所以用空散列预填充它可以解决整个问题:
unless Portfolio::Application.config.action_mailer.nil?
Portfolio::Application.config.action_mailer.smtp_settings = {}
options = YAML.load_file(Rails.root.join('config', 'smtp.yml'))[Rails.env]
options.each do |name, value|
Portfolio::Application.config.action_mailer.smtp_settings[name.to_sym] = value
end unless options.nil?
end
仍然,有点丑,但它完成了工作。
Portfolio::Application.config.action_mailer.smtp_settings = config_for(:smtp).symbolize_keys
如果你想把它配置得更像Action Storage, by service,你可以这样做。
config/mailer.yml
sendgrid:
user_name: apikey
password: "<%= ENV.fetch("SENDGRIP_API_KEY") %>"
address: smtp.sendgrid.net
port: 587
authentication: :plain
enable_starttls_auto: true
gmail:
user_name: xxxxx
password: "<%= ENV.fetch("GMAIL_APP_PASSWORD") %>"
address: smtp.gmail.com
port: 587
authentication: :plain
enable_starttls_auto: true
open_timeout: 5
read_timeout: 5
app/lib/mail/gmail_smtp.rb
class GmailSmtp < Mail::SMTP; end
config/initializers/mailer.rb
Rails.application.configure do
config_file = Rails.root.join("config/mailer.yml")
action_mailer_config = ActiveSupport::ConfigurationFile.parse(config_file).deep_symbolize_keys
# Default for all mailers
config.action_mailer.smtp_settings = action_mailer_config[:sendgrid]
config.action_mailer.gmail_smtp_settings = action_mailer_config[:gmail]
end
app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
default delivery_method: :gmail_smtp
def my_notification
end
end