Rails4:自定义模型ActionMailer

Rails 4: customize model ActionMailer

我目前正在关注 Jessica Biggs 的 Creating a Scoped Invitation System for Rails codewall.com 教程。

发送邀请表部分,作者说:

We'll also need a Mailer to send the email. The invitation mailer is very basic, so I'm not going to go into a lot of detail here, but it will send to the :email of the newly created invitation and include an invite URL that we will construct later. The mailer will have 2 methods, one for sending he invitation email to new users and one for sending a notification email to existing users.

由于我对 Rails 总体而言,尤其是 ActionMailer 不是很熟悉,所以我试图从 Rails Guides Action Mailer Basics.

中理解作者的意思

因此,我 运行 rails g mailer InviteMailer 生成了我的邮件程序并添加了以下操作:

class InviteMailer < ApplicationMailer

  def invite_new_user
    @link = new_user_registration_path(:invite_token => @invite.token) 
    mail to: @invite.email, subject: "Calendar Invitation"
  end

  def notify_existing_user
  end

end

现在,我碰壁了,我不知道如何继续前进并实现邮件程序的其余部分。

任何指向我正确方向的提示都将不胜感激。

好的,你已经得到了 Mailer class 和方法。

Mailers are very similar to Rails controllers. They also have methods called actions and use views to structure the content. Where a controller generates content like HTML to send back to the client, a Mailer creates a message to be delivered via email.

现在,您需要定义邮件程序的 notify_existing_user 操作,假设您要向现有用户发送一封电子邮件,内容为 Thanks for signing up! 因此,您必须添加:

class InviteMailer < ApplicationMailer
  default from: 'your_email@example.com'

  def notify_existing_user(user)
    @user = user
    mail(to: @user.email, subject: 'Thanks for signing up!')
  end
end

default Hash - This is a hash of default values for any email you send from this mailer.

因此,您可以将您的电子邮件地址用作发件人电子邮件地址。

现在,您需要创建一个邮件视图:

notify_existing_user.html.erb app/views/invite_mailer/。这将是用于电子邮件的模板,格式为 HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1>Welcome to example.com, <%= @user.name %></h1>
    <p>Thanks for signing up!</p>
  </body>
</html>

您还可以在 app/views/invite_mailer/ 中创建文本视图 notify_existing_user.text.erb:

Welcome to example.com, <%= @user.name %>
===============================================

Thanks for signing up!

Mailers are really just another way to render a view. Instead of rendering a view and sending out the HTTP protocol, they are just sending it out through the email protocols instead. Due to this, it makes sense to just have your controller tell the Mailer to send an email when a user is successfully created.

让我们创建一个简单的用户脚手架:

rails generate scaffold user name email login
rake db:migrate

然后,您可以从 users_controller 中调用 InviteMailer.notify_existing_user 方法,如下所示:

class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        # Tell the InviteMailer to notify the existing user that just been created
        InviteMailer.notify_existing_user(@user).deliver_later

        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
end

就是这样。现在,当您创建用户并保存用户时,将使用您的 InviteMailer.

notify_existing_user 方法向他发送一封电子邮件。

首先,您的邮件程序需要知道应该向哪个用户发送电子邮件。所以我们添加一个用户参数。剩下的很简单:我们只是调用创建邮件对象的邮件,它是隐式返回的。

class InviteMailer < ApplicationMailer
  def invite_new_user(user, invite)
    @user = user
    @invite = invite
    mail(to: user.email, subject: 'Welcome! ...')
  end

  def notify_existing_user(user)
    @user = user
    mail(to: user.email, subject: 'Sorry to nag you ...')
  end  
end

mail 将自动查找以下模板并将它们添加到电子邮件正文中。

<%# app/views/invite_mailer/invite_new_user.html.erb %>
<h1>Your are cordially invited to ...</h1>
Add the invitation link here. The invitation is available as @invite.

<%# app/views/invite_mailer/notify_existing_user.html.erb %>
<h1>Yo dude ...</h1>

请注意,如果您想发送多部分纯文本/html 电子邮件,您还需要创建一个 .text.erb 视图。发送明文版本通常是个好主意。

要调用我们的邮件程序,我们会做类似的事情:

class InvitationsController 

  def new
     @user = User.new
  end

  def create
     @user = User.new(user_params) 
     @invite = Invitation.new
     # @todo generate some kind of invitation token.

     if @invite.save
       InviteMailer.invite_new_user(@user, @invitation).deliver_later
       redirect_to users_path, notice: 'invitation sent'
     else
       render :new
     end
  end

  def user_params
    params.require(:user).permit(:email)
  end
end