Rails Mailer 在部署到生产环境时不工作
Rails Mailer does not work when deploying to production
遵循 Michael Hartl 的帐户激活教程(第 11 章),在部署到 Heroku 并创建新用户时,我收到 "We're sorry, but something went wrong." 消息。用户已在数据库中创建,但电子邮件未发送,因此无法激活帐户。
我不知道为什么,但是当收到 "We're sorry..." 错误时,浏览器会向我显示“herokuapp.com/users”地址,当控制器说重定向到 root。
这里是用户控制器:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.where(activated: true).paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
redirect_to root_url and return unless @user.activated?
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
@user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "Profile updated!"
redirect_to @user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted!"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in"
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
和型号:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
# Validates presence and lenght for the user name
validates :name, presence: true,
length: { maximum: 50 }
# Validates presence, length, format and uniqueness for user email
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
# User has a secure password (password_digest), length and presence
has_secure_password
validates :password, presence: true,
length: { minimum: 6 },
allow_nil: true
# VALID_PASSWORD_REGEX = "((?=.*\d)(?=.*[a-z]).{6,20})"
# validates :password, format: { with: VALID_PASSWORD_REGEX }
# Returns the hash digest of the given string. (only for tests)
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
# FOR REMEMBER ME
# Returns a random token for safe "remember me".
def User.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# Returns true if the given token matches the digest.
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
# Forgets a user.
def forget
update_attribute(:remember_digest, nil)
end
# Activates an account.
def activate
update_columns(activated: true, activated_at: Time.zone.now)
end
# Sends activation email.
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
应用程序和用户邮件程序:
class ApplicationMailer < ActionMailer::Base
default from: "noreply@example.com"
layout 'mailer'
end
-
class UserMailer < ApplicationMailer
def account_activation(user)
@user = user
mail to: @user.email, subject: "Account activation"
end
end
Production.rb
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.public_file_server.enabled = true
config.assets.js_compressor = :uglifier
config.assets.compile = false
config.assets.digest = true
config.force_ssl = true
config.log_level = :debug
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = 'whispering-spire-86793.herokuapp.com'
config.action_mailer.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.log_formatter = ::Logger::Formatter.new
config.active_record.dump_schema_after_migration = false
end
和 heroku 日志
2016-07-14T12:22:19.113508+00:00 app[web.1]: [3] Puma starting in cluster mode...
2016-07-14T12:22:19.113539+00:00 app[web.1]: [3] * Version 3.4.0 (ruby 2.2.4-p230), codename: Owl Bowl Brawl
2016-07-14T12:22:20.539342+00:00 app[web.1]: [3] * Listening on tcp://0.0.0.0:9375
2016-07-14T12:22:21.039497+00:00 heroku[web.1]: State changed from starting to up
2016-07-14T12:22:22.459846+00:00 heroku[router]: at=info method=POST path="/users" host=whispering-spire-86793.herokuapp.com request_id=7bff9a3c- 3151-48a4-87bc-ba207b1fa10e fwd="88.12.236.151" dyno=web.1 connect=0ms service=390ms status=500 bytes=1714
2016-07-14T12:22:22.684571+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=whispering-spire-86793.herokuapp.com request_id=afd1130c-9864-4650-a5c7-fccd8446039b fwd="88.12.236.151" dyno=web.1 connect=2ms service=2ms status=200 bytes=188
2016-07-14T12:22:23.912741+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=whispering-spire-86793.herokuapp.com request_id=62a47e7f-33c3-42b6-b700-2219cfa8ada1 fwd="88.12.236.151" dyno=web.1 connect=0ms service=3ms status=200 bytes=188
我遇到了同样的问题。由于开发中一切正常,我想一定是开发环境的问题。
所以我从 Hartl 的教程中复制并粘贴了文件 config/environments/production.rb 第 11 章中的清单 11.41。我一定是在第一次尝试时在该文件中输入了错误,因为我的实时应用程序现在正在运行。
此外,请注意行
config.action_mailer.raise_delivery_errors = false
默认情况下已包含在文件中。但是 Hartl 的代码包括
config.action_mailer.raise_delivery_errors = true
因此您需要删除 "false" 行。
为方便起见,完整代码为:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = '<your heroku app>.herokuapp.com'
config.action_mailer.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
祝你好运!
遵循 Michael Hartl 的帐户激活教程(第 11 章),在部署到 Heroku 并创建新用户时,我收到 "We're sorry, but something went wrong." 消息。用户已在数据库中创建,但电子邮件未发送,因此无法激活帐户。
我不知道为什么,但是当收到 "We're sorry..." 错误时,浏览器会向我显示“herokuapp.com/users”地址,当控制器说重定向到 root。
这里是用户控制器:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.where(activated: true).paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
redirect_to root_url and return unless @user.activated?
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
@user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "Profile updated!"
redirect_to @user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted!"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in"
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
和型号:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
# Validates presence and lenght for the user name
validates :name, presence: true,
length: { maximum: 50 }
# Validates presence, length, format and uniqueness for user email
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,
length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
# User has a secure password (password_digest), length and presence
has_secure_password
validates :password, presence: true,
length: { minimum: 6 },
allow_nil: true
# VALID_PASSWORD_REGEX = "((?=.*\d)(?=.*[a-z]).{6,20})"
# validates :password, format: { with: VALID_PASSWORD_REGEX }
# Returns the hash digest of the given string. (only for tests)
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
# FOR REMEMBER ME
# Returns a random token for safe "remember me".
def User.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# Returns true if the given token matches the digest.
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
# Forgets a user.
def forget
update_attribute(:remember_digest, nil)
end
# Activates an account.
def activate
update_columns(activated: true, activated_at: Time.zone.now)
end
# Sends activation email.
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
应用程序和用户邮件程序:
class ApplicationMailer < ActionMailer::Base
default from: "noreply@example.com"
layout 'mailer'
end
-
class UserMailer < ApplicationMailer
def account_activation(user)
@user = user
mail to: @user.email, subject: "Account activation"
end
end
Production.rb
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.public_file_server.enabled = true
config.assets.js_compressor = :uglifier
config.assets.compile = false
config.assets.digest = true
config.force_ssl = true
config.log_level = :debug
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = 'whispering-spire-86793.herokuapp.com'
config.action_mailer.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.log_formatter = ::Logger::Formatter.new
config.active_record.dump_schema_after_migration = false
end
和 heroku 日志
2016-07-14T12:22:19.113508+00:00 app[web.1]: [3] Puma starting in cluster mode...
2016-07-14T12:22:19.113539+00:00 app[web.1]: [3] * Version 3.4.0 (ruby 2.2.4-p230), codename: Owl Bowl Brawl
2016-07-14T12:22:20.539342+00:00 app[web.1]: [3] * Listening on tcp://0.0.0.0:9375
2016-07-14T12:22:21.039497+00:00 heroku[web.1]: State changed from starting to up
2016-07-14T12:22:22.459846+00:00 heroku[router]: at=info method=POST path="/users" host=whispering-spire-86793.herokuapp.com request_id=7bff9a3c- 3151-48a4-87bc-ba207b1fa10e fwd="88.12.236.151" dyno=web.1 connect=0ms service=390ms status=500 bytes=1714
2016-07-14T12:22:22.684571+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=whispering-spire-86793.herokuapp.com request_id=afd1130c-9864-4650-a5c7-fccd8446039b fwd="88.12.236.151" dyno=web.1 connect=2ms service=2ms status=200 bytes=188
2016-07-14T12:22:23.912741+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=whispering-spire-86793.herokuapp.com request_id=62a47e7f-33c3-42b6-b700-2219cfa8ada1 fwd="88.12.236.151" dyno=web.1 connect=0ms service=3ms status=200 bytes=188
我遇到了同样的问题。由于开发中一切正常,我想一定是开发环境的问题。
所以我从 Hartl 的教程中复制并粘贴了文件 config/environments/production.rb 第 11 章中的清单 11.41。我一定是在第一次尝试时在该文件中输入了错误,因为我的实时应用程序现在正在运行。
此外,请注意行
config.action_mailer.raise_delivery_errors = false
默认情况下已包含在文件中。但是 Hartl 的代码包括
config.action_mailer.raise_delivery_errors = true
因此您需要删除 "false" 行。
为方便起见,完整代码为:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
host = '<your heroku app>.herokuapp.com'
config.action_mailer.default_url_options = { host: host }
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => ENV['SENDGRID_USERNAME'],
:password => ENV['SENDGRID_PASSWORD'],
:domain => 'heroku.com',
:enable_starttls_auto => true
}
祝你好运!