📚

[Rails]イベント通知機能①(Action Mailer)

に公開

Action Mailer

Action Mailerは、Railsに標準で組み込まれてるメール送信機能。
システム障害・メールマガジン機能などで使える一括送信ができる。

使用方法

メーラーを作成する

bin/rails generate mailer メーラー名

今回は bin/rails generate mailer event で作成。

Winodwsだと、上記コマンドではbin/railsが開いてしまい、ファイルが作成されなかったので下記コマンドのようにruby経由で明示的に実行しました。

ruby bin/rails generate mailer event

下記で作成も可能。

rails g mailer EventMailer

app/mailers/event_mailer.rb が作成される。

class EventMailer < ApplicationMailer
end

app/mailers/application_mailer.rbは、すべてのメール送信クラス(Mailer)の親クラス。
下記がデフォルトで設定されているので、こちらの修正は不要。

class ApplicationMailer < ActionMailer::Base
  default from: 'no-reply@example.com'
  layout 'mailer'
end

app/mailers/event_mailer.rb

event_mailer.rb の修正
ここで「通知メールの内容」や「送り方」を定義する。

app/mailers/event_mailer.rb

class EventMailer < ApplicationMailer
    # (1)
  def send_notification(member, event)
    @group = event[:group]
    @title = event[:title]
    @body = event[:body]
    
    @mail = EventMailer.new()
    mail(
      from: ENV['MAIL_ADDRESS'],
      to:   member.email,
      subject: "#{@group.name} の新しいイベント通知"
    )
  end

    # (2)
  def self.send_notifications_to_group(event)
    group = event[:group]
    group.users.each do |member|
      EventMailer.send_notification(member, event).deliver_now
    end
  end
end

(1)に関して

def send_notification(member, event)
    @group = event[:group]
    @title = event[:title]
    @body = event[:body]
    
    @mail = EventMailer.new()
    mail(
      from: ENV['MAIL_ADDRESS'],
      to:   member.email,
      subject: "#{@group.name} の新しいイベント通知"
    )
end

通知用のインスタンスメソッド

def send_notification(member, event)

⇒ ユーザー(member)1人と、イベント情報(event)を受け取って、その人に1通メールを送るための関数。送るメールを定義している。

メールの本文で使う変数をセット

  @group = event[:group]
  @title = event[:title]
  @body = event[:body]

@group, @title, @body は、ビュー(send_notification.html.erb など)で使われる変数。
イベントハッシュから必要な情報を取り出して代入している。

@mail = EventMailer.new()

新しいイベントを作成して、@mailに代入。

メールの設定

  mail(
    from: ENV['MAIL_ADDRESS'],
    to:   member.email,
    subject: "#{@group.name} の新しいイベント通知"
  )
  • mail(...) は、メールの送信先・件名・差出人を設定する。
  • from: は差出人のアドレスで.env に設定された環境変数を使用する。
  • 件名は、"#{@group.name} の新しいイベント通知"にして、グループ名が入るようにして何のメールかわかりやすくしました。
  • メール本文のはapp/views/event_mailer/send_notification.html.erb で定義する。

(2)に関して

  def self.send_notifications_to_group(event)
    group = event[:group]
    group.users.each do |member|
      EventMailer.send_notification(member, event).deliver_now
    end
  end

グループ全体に通知するクラスメソッド。
グループ全体に一斉送信する関数。

def self.send_notifications_to_group(event)

グループのメンバーにメールを送る

  group = event[:group]
  group.users.each do |member|
    EventMailer.send_notification(member, event).deliver_now
  end

(1)のsend_notification(member, event)が出てきた!

  • group.users.each:グループに属する全ユーザーに対して1人ずつ処理。
  • EventMailer.send_notification(...):EventMailerクラスを使用して、送るユーザーごとにそれぞれのメールを生成。
  • .deliver_now:即時送信(非同期じゃなくその場で送る)

コントローラ

event_notices_controller.rb

  • 投稿機能などと同じように、new・createアクションを作成。
  • メールを作成した後、送った後はどこにリダイレクトするかを設定。
class Public::EventNoticesController < ApplicationController
  def new
    @group = Group.find(params[:group_id])
  end

  def create
    @group = Group.find(params[:group_id])
    @title = params[:title]
    @date = params[:date]
    @body = params[:body] 
    
    event = { 
      :group => @group, 
      :title => @title, 
      :date => @date, 
      :body => @body
    }
    
    EventMailer.send_notifications_to_group(event)
    render :sent
  end

  def sent
    redirect_to group_path(params[:group_id])
  end
end

ビューファイル

app/views/event_mailer/send_notification.html.erb

実際に送るメールの本文を設定する。

=========================================
<%= @group.name %>からの新しいイベントです。
===========================================

イベント名:
<%= @title %>

開催日時:
<%= @date %>

イベント内容:
<%= @body %>

app/views/public/event_notices/new.html.erb

入力フォームの作成。

<div class="main-title">
  <h4><i class="fa-solid fa-envelope"></i>メール送信画面</h4>
</div>

<div class="detail-results">
  <div class="detail-card">
    <div class="detail-row">
      <p>イベント告知など、メンバーに送信したいメールを入力してください。</p>
      <%= form_with url: group_event_notices_path(@group), method: :post, local:true do |f| %>
        <div class="form-field">
          <b><i class="fa-solid fa-champagne-glasses"></i> イベント名</b>
          <%= f.text_field :title, class: 'form-input' %>
        </div>
        <div class="form-field">
          <b><i class="fa-solid fa-calendar-days"></i> 開催日時</b>
          <%= f.text_field :date, class: 'form-input' %>
        </div>
        <div class="form-field">
          <b><i class="fa-solid fa-question"></i> イベント内容</b>
          <%= f.text_area :body, class: 'form-input' %>
        </div>
        <div class="form-field d-flex justify-content-end">
          <%= button_tag(type: 'submit', class: 'submit-btn') do %>
            <i class="fa-solid fa-paper-plane"></i>
          <% end %>
        </div>
      <% end %>
    </div>
  </div>
</div>

app/views/public/event_notices/sent.html.erb

送信後、リダイレクト先、送信結果画面。

<div class="main-title">
  <h4><i class="fa-solid fa-envelope"></i>送信結果画面</h4>
</div>
<div class="detail-results">
  <div class="detail-card">
    <div class="detail-row">
      <h4>送信が完了しました。</h4>
      <p>内容は以下の通りです。</p>
      <hr>
      <b><i class="fa-solid fa-champagne-glasses"></i> イベント名</b>
      <p><%= @title %></p>
      <b><i class="fa-solid fa-calendar-days"></i> 開催日時</b>
      <p><%= @date %></p>
      <b><i class="fa-solid fa-question"></i> イベント内容</b>
      <p><%= @body %></p>
    </div>
  </div>
</div>

gmailに届かない問題が発生しているが、本日はここまで。

明日まとめたいこと

  • gmailでは届かない問題解決方法
  • .envとは
  • SMTPとは

参考文献

https://railsguides.jp/action_mailer_basics.html
https://www.sejuku.net/blog/48739
https://qiita.com/sazumy/items/e0e9f1aaeed47c616c6b
https://zenn.dev/goldsaya/articles/0e4187f0cbf326

Discussion