5

我正在尝试将 actionmailer 与 sendgrid 一起使用并在 Rails 3.2 上进行设计。我浏览了许多关于 SO 的问题,例如用 sendmail 替换 smtp、创建一个config/email.yml我没有)以及更多想法,但没有任何效果。我肯定错过了什么。

电子邮件似乎没有在开发或生产中发送。(sendgrid 不报告任何已发送的电子邮件,并且我在“手动测试”中检查过我从未收到过电子邮件)。

运行 Heroku 控制台,我刚刚设法获得了以下信息:

NoMethodError: undefined method `email' for nil:NilClass on the notifier.rb file:

:mail( :to => user.email, :subject => "Thanks for signing up" )

完整的跟踪:

irb(main):007:0> Notifier.welcome_email(@user).deliver --trace
NoMethodError: undefined method `email' for nil:NilClass
from /app/app/mailers/notifier.rb:16:in `welcome_email'
from /app/vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.13/lib/abstract_controller/base.rb:167:in `process_action'
from /app/vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.13/lib/abstract_controller/base.rb:121:in `process'
from /app/vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.13/lib/abstract_controller/rendering.rb:45:in `process'
from /app/vendor/bundle/ruby/1.9.1/gems/actionmailer-3.2.13/lib/action_mailer/base.rb:459:in `process'
from /app/vendor/bundle/ruby/1.9.1/gems/actionmailer-3.2.13/lib/action_mailer/base.rb:453:in `initialize'
from /app/vendor/bundle/ruby/1.9.1/gems/actionmailer-3.2.13/lib/action_mailer/base.rb:439:in `new'
from /app/vendor/bundle/ruby/1.9.1/gems/actionmailer-3.2.13/lib/action_mailer/base.rb:439:in `method_missing'
from (irb):7
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands/console.rb:47:in `start'
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands/console.rb:8:in `start'
from /app/vendor/bundle/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

但我不明白为什么它无法识别 user.email。

有人知道我做错了什么吗?

以下是我认为重要的文件:

应用程序/邮件程序/notifier.rb

class Notifier < ActionMailer::Base
  include SendGrid
  sendgrid_category :use_subject_lines
  sendgrid_enable   :ganalytics, :opentrack, :clicktrack
  sendgrid_ganalytics_options :utm_source => "general_notifier", :utm_medium => "email"

default :from => "math@example.com"
# send a signup email to the user, pass in the user object that contains the user's email address
def welcome_email(user)
@user = user
@url  = "http://example.com/login"
mail( :to => user.email, :subject => "Thanks for signing up" )
  end
end

通知程序由 app/controllers/user_controller.rb 调用:

class UsersController < ApplicationController
before_filter :authenticate_user!

# POST /users
# POST /users.json
def create
@user = User.new(params[:user])

respond_to do |format|
    if @user.save
      # Tell the UserMailer to send a welcome Email after save
      Notifier.welcome_email(@user).deliver

      format.html { redirect_to(@user, :notice => 'User was successfully created.') }
      format.json { render :json => @user, :status => :created, :location => @user }
    else
      format.html { render :action => "new" }
      format.json { render :json => @user.errors, :status => :unprocessable_entity }
    end
    end
  end

def index
  authorize! :index, @user, :message => 'Not authorized as an administrator.'
  @users = User.all
end

def show
  @user = User.find(params[:id])
end

def update
  authorize! :update, @user, :message => 'Not authorized as an administrator.'
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user], :as => :superadmin)
    redirect_to users_path, :notice => "User updated."
  else
    redirect_to users_path, :alert => "Unable to update user."
  end
end

def destroy
  authorize! :destroy, @user, :message => 'Not authorized as an administrator.'
  user = User.find(params[:id])
  unless user == current_user
    user.destroy
    redirect_to users_path, :notice => "User deleted."
  else
    redirect_to users_path, :notice => "Can't delete yourself."
  end
end

我的 config/Environement.rb 文件(密码指向 application.yml)

# Load the rails application
require File.expand_path('../application', __FILE__)

# Initialize the rails application
ExampleApp::Application.initialize!

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:user_name            => 'SENDGRID_USERNAME',
:password             => 'SENDGRID_PASSWORD',
:domain               => 'SENDGRID_DOMAIN',
:address              => 'smtp.sendgrid.net',
:port                 => 587,
:authentication       => :plain,
:enable_starttls_auto => true
}

也在 config/environments/development.rb

  # ActionMailer Config
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }
  config.action_mailer.delivery_method = :smtp
  # change to true to allow email to be sent during development
  config.action_mailer.perform_deliveries = true
  config.action_mailer.raise_delivery_errors = true #useful to have to debug
  config.action_mailer.default :charset => "utf-8"

  config.action_mailer.smtp_settings = {
    :user_name            => 'SENDGRID_USERNAME',
    :password             => 'SENDGRID_PASSWORD',
    :domain               => 'SENDGRID_DOMAIN',
    :address              => 'smtp.sendgrid.net',
    :port                 => 587,
    :authentication       => :plain,
    :enable_starttls_auto => true
  }

如果它可能有帮助,我的 app/models/user.rb 设计:

class User < ActiveRecord::Base
rolify

# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :superadmin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body

validates_presence_of   :name
validates_uniqueness_of :name, :email, :case_sensitive => false

#Add a filter calling assign_role method before user is created
before_create :assign_role

def assign_role
  #assign a default role if no role is assigned
  self.add_role :user if self.roles.first.nil?
end
end

当我单击注册时的完整本地跟踪应该向用户发送电子邮件:

Started GET "/" for 127.0.0.1 at 2013-05-12 11:18:32 +0200
User Load (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 22 LIMIT 1
Processing by StaticPagesController#home as HTML
User Load (0.6ms)  SELECT "users".* FROM "users" 
Rendered static_pages/home.html.erb within layouts/application (2.0ms)
Rendered layouts/_viewports.html.erb (0.0ms)
(0.7ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" =  "users_roles"."role_id" WHERE "users_roles"."user_id" = 22 AND (((roles.name = 'superadmin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))
Rendered layouts/_navigation.html.erb (3.3ms)
Rendered layouts/_header.html.erb (4.0ms)
Rendered layouts/_messages.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.5ms)
Completed 200 OK in 129ms (Views: 126.1ms | ActiveRecord: 1.3ms)
[2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set    content-length of the response or set Response#chunked = true
[2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set  content-length of the response or set Response#chunked = true
[2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
 [2013-05-12 11:18:32] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
 [2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
[2013-05-12 11:18:33] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

以及我的 log/development.log 的日志

Started GET "/users/sign_up" for 127.0.0.1 at 2013-05-12 11:18:17 +0200
Processing by Devise::RegistrationsController#new as HTML
Rendered devise/shared/_links.erb (0.5ms)
Rendered devise/registrations/new.html.erb within layouts/application (12.6ms)
Rendered layouts/_viewports.html.erb (0.1ms)
Rendered layouts/_navigation.html.erb (1.4ms)
Rendered layouts/_header.html.erb (3.3ms)
Rendered layouts/_messages.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.5ms)
Completed 200 OK in 153ms (Views: 151.2ms | ActiveRecord: 0.0ms)


Started POST "/users" for 127.0.0.1 at 2013-05-12 11:18:32 +0200
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓",     
"authenticity_token"=>"xlNUA6fffffYzkFn5bMR18zSiNg=", "user"=>  
{"name"=>"Macro", "email"=>"mathieu.proffit75@gmail.com", "password"=>"[FILTERED]", 
"password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
[1m[36m (0.5ms)[0m  [1mBEGIN[0m
[1m[35mUser Exists (0.6ms)[0m  SELECT 1 AS one FROM "users" WHERE "users"."email" =  
'mathieu.proffit75@gmail.com' LIMIT 1
[1m[36mUser Exists (0.6ms)[0m  [1mSELECT 1 AS one FROM "users" WHERE 
LOWER("users"."name") = LOWER('Macro') LIMIT 1[0m
[1m[35mUser Exists (0.4ms)[0m  SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") 
= LOWER('mathieu.proffit75@gmail.com') LIMIT 1
[1m[36mRole Load (0.7ms)[0m  [1mSELECT "roles".* FROM "roles" WHERE "roles"."name" = 
'user' AND "roles"."resource_type" IS NULL AND "roles"."resource_id" IS NULL LIMIT 1[0m
[1m[35mRole Load (0.5ms)[0m  SELECT "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT 
1 [["id", 6]]
[1m[36mSQL (0.7ms)[0m  [1mINSERT INTO "users" ("created_at", "current_sign_in_at",  
"current_sign_in_ip", "email", "encrypted_password", "last_sign_in_at",    
"last_sign_in_ip", "name", "remember_created_at", "reset_password_sent_at",  
"reset_password_token", "sign_in_count", "updated_at") VALUES ($1, $2, $3, $4, $5, $6,  
$7, $8, $9, $10, $11, $12, $13) RETURNING "id"[0m  [["created_at", Sun, 12 May 2013 
09:18:32 UTC +00:00], ["current_sign_in_at", nil], ["current_sign_in_ip", nil], 
["email", "mathieu.proffit75@gmail.com"], ["encrypted_password", 
"$2a$10$WaMqXevJ/zAQeTyJfffffffffffffBtqsCV97G"], ["last_sign_in_at", 
nil], ["last_sign_in_ip", nil], ["name", "Macro"], ["remember_created_at", nil], 
["reset_password_sent_at", nil], ["reset_password_token", nil], ["sign_in_count", 0], 
["updated_at", Sun, 12 May 2013 09:18:32 UTC +00:00]]
[1m[35m (0.3ms)[0m  INSERT INTO "users_roles" ("user_id", "role_id") VALUES (22, 6)
[1m[36m (9.4ms)[0m  [1mCOMMIT[0m
[1m[35m (0.3ms)[0m  BEGIN
[1m[36m (0.7ms)[0m  [1mUPDATE "users" SET "last_sign_in_at" = '2013-05-12 
09:18:32.706773', "current_sign_in_at" = '2013-05-12 09:18:32.706773', "last_sign_in_ip" 
= '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = 
'2013-05-12 09:18:32.707691' WHERE "users"."id" = 22[0m
[1m[35m (8.3ms)[0m  COMMIT
Redirected to http://localhost:3000
Completed 302 Found in 125ms (ActiveRecord: 0.0ms)


Started GET "/" for 127.0.0.1 at 2013-05-12 11:18:32 +0200
[1m[36mUser Load (0.9ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."id" = 22    
LIMIT 1[0m

 Processing by StaticPagesController#home as HTML
 [1m[35mUser Load (0.6ms)[0m  SELECT "users".* FROM "users" 
 Rendered static_pages/home.html.erb within layouts/application (2.0ms)
  Rendered layouts/_viewports.html.erb (0.0ms)
 [1m[36m (0.7ms)[0m  [1mSELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON 
 "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = 22 AND 
 (((roles.name = 'superadmin') AND (roles.resource_type IS NULL) AND (roles.resource_id  
 IS NULL)))[0m
 Rendered layouts/_navigation.html.erb (3.3ms)
 Rendered layouts/_header.html.erb (4.0ms)
 Rendered layouts/_messages.html.erb (0.1ms)
 Rendered layouts/_footer.html.erb (0.5ms)
 Completed 200 OK in 129ms (Views: 126.1ms | ActiveRecord: 1.3ms)
4

1 回答 1

5

这有点误导,虽然对我来说有点鲁莽;错误从来不是来自调用email对象nil(如标题所述),我应该注意到您正在使用 Devise,因此所有请求都由其处理RegistrationsController。也就是说,请更改标题,忽略或删除users_controller;它不是处理注册请求的人。

然后将以下行添加到您的User模型中:

after_create { Notifier.welcome_email(self).deliver }

应该这样做,因为 SendGrid 配置正确:)。

于 2013-05-12T09:49:43.753 回答