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
  }

祝你好运!