👗

Rails グループメンバーへメール送信

2023/05/05に公開

この続きです🏋🏻

https://zenn.dev/goldsaya/articles/f32a3b3186084f

https://zenn.dev/goldsaya/articles/00e083c805b1b1

グループのオーナーから、グループメンバーにメールを送信できるようにします!

要件

  • グループオーナーのみグループ詳細ページに「Notice an Event」リンクを表示させる
  • 「Notice an Event」をクリックすると、メール作成画面に移動
  • タイトル・本文を入力できるフォームの作成
  • タイトル・本文を入力後、送信ボタンをクリックすると、グループメンバーにメールが送信される
  • その後、「送信が完了しました」と表示しその下に内容を記述

完成

groups/show.html.erb

new_mail.html.erb

send_mail.html.erb

Action Mailer

Ruby on Railsには標準でAction Mailerというメールの送信機能が組み込まれている!

例えば、

メールフォームの入力内容を業務担当者に自動送信
メールマガジンを一括メール送信
システム障害を検知してシステム担当者メール通知

など、色々な場面で活用することができる!

🌱わかりやすい記事 https://www.sejuku.net/blog/48739

メイラーを作成

rails g mailer ContactMailer

bin/rails generate mailer 任意のメイラー名 でOK!

こんな感じでMailerが作成される!

ターミナル結果

作成されたファイルのうち、「app/mailers/contact_mailer.rb」が、メール送信機能を実装するための空のクラスとなる。

サーバーを設定

(Gmailで送信するための設定)

メールサーバの設定をするには「config/environments/環境毎に設定.rb」に追記します。

config/environments/development.rb
Rails.application.configure do
 # ----- 中略 -----  #
config.action_mailer.raise_delivery_errors = true
 # ----- 中略 -----  #

 #  以下を末尾に追記   #
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
 address:              'smtp.gmail.com',
 port:                  587,
 domain:               'gmail.com',
 user_name:            '送信元となるGmailアドレスを記入',
 password:             'アプリパスワードを記入',
 authentication:       'login',
 enable_starttls_auto:  true
}
end

すでに記述のあるconfig.action_mailer.raise_delivery_errorsがfalseになっていれば、trueに変更する!

port:は上記の数のままで問題ございません!

上から、config.action_mailerというパラメーターに色んなオプションを指定しています。

1行目delivery_methodメールの送信方法を設定するためのメソッド
デフォルトで :smtpになっているらしい

ちなみにSMTPとは

メールを相手のメールサーバーまで届ける仕組みが「SMTP」だ。
「SMTP」とは「Simple Mail Transfer Protocol(シンプル・メール・トランスファー・プロトコル)」の略で、あえて訳せば「簡単なメールの送信の手順」というところだろうか。お約束ごとと考えてもいい。
「メールを送るよ〜」「ええで!」「宛先は〇●だよ」「りょ」「本文はかくかくしかじかだよ」「受け取ったで!」――とまぁそんな具合。
参照:https://time-space.kddi.com/ict-keywords/kaisetsu/20170824/2081

2行目 smtp_settingsSMTP サーバーを使用してメールを送信する場合に設定するための Action Mailer のオプションの一つ

  • address: SMTP サーバーのアドレス。
  • port: SMTP サーバーのポート番号。
  • domain: アプリケーションのドメイン名。
  • user_name: SMTPサーバーに接続するためのユーザー名。
  • password: SMTPサーバーに接続するためのパスワード。
  • authentication: 認証方式。通常、:login または :plain を使用。
  • enable_starttls_auto: STARTTLS に対応している場合に、セキュアな接続を確立するために必要なオプション。

Gmailの設定を変更

Net::SMTPAuthenticationErrorにならないために、、
GmailのGoogleアカウントページから、アプリパスワードを取得!

Googleアカウント→セキュリティのGoogleでのログインで2段階プロセスをON、
その後、アプリパスワードというものを設定できるようになるので、そこでアプリパスワードを設定。

🌱こちらの記事のSTEP2アプリパスワードの取得部分がとてもわかりやすいです!
https://qiita.com/mi-1109/items/974c03776eba61146aa4

メールアドレスとパスワードをgithubにプッシュしないように気をつけること!

メーラーを編集

生成直後は、以下のような application_mailer.rb と

app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: 'from@example.com'
  layout 'mailer'
end

空のメーラー

app/mailer/contact_mailer.rb
class ContactMailer < ApplicationMailer
end

が作られている。

application_mailerには全メーラー共通の設定を、
sample_mailerにはメーラー個別の設定を記述する!!

application_mailerはそのままでOK、
contact_mailer.rbを編集

app/mailers/contact_mailer.rb
class ContactMailer < ApplicationMailer

def send_mail(mail_title,mail_content,group_users) #メソッドに対して引数を設定
  @mail_title = mail_title
  @mail_content = mail_content
  mail bcc: group_users.pluck(:email), subject: mail_title
  end
end

このsend_mailメソッドは、引数で渡されたタイトル、内容、グループメンバーのEmailアドレスを使って、グループメンバー全員にメールを送信するメソッド。
mailメソッドを使用して、BCCフィールドをグループメンバーのメールアドレスの配列で指定し、タイトルを設定している。

ちなみに、BCCは「Blind Carbon Copy」の略で、メールの本文の受信者に対して、他に誰がBCCに入っているかを見えないようにするためのフィールドです。

コントローラー記述

Group詳細ページのmailボタン

メール作成画面

メール送信完了画面
の流れです🌱

groups_controller.rb
#該当部分のみ

def new_mail
  @group = Group.find(params[:group_id])
end

def send_mail
  @group = Group.find(params[:group_id])
  group_users = @group.users
  @mail_title = params[:mail_title]
  @mail_content = params[:mail_content]
  ContactMailer.send_mail(@mail_title, @mail_content,group_users).deliver
end

〜解説〜
def send_mailでは、グループのメンバー全員にメールを送信するためのアクション
で、'viwes/groups/new_mail.html`のform_withで入力された値を受け取っている。

@group変数には、グループをidで検索して代入し、
group_users変数には、グループに所属する全ユーザーが代入されている。
@mail_titleと@mail_contentには、それぞれ送信するメールのタイトルと内容が代入され、
最後に、ContactMailer.send_mailメソッドを呼び出して、メールを送信します。

send_mailメソッドは、mailers/contact_mailer.rbファイルに記述されていて、deliverメソッドは、メール送信を実行します。

Viewページ

groups/new_mail.html.erb
<div class='container'>
  <div class='row'>
    <div class="col-sm-12 col-md-8 col-lg-5 px-5 px-sm-0 mx-auto">
    <h2>Event Mail</h2>
    <%= form_with url: group_send_mail_path(@group),method: :get, local: true do |f| %>
    <div class="form-group">
        <%= f.label :title %>
        <%= f.text_field :mail_title,class:'form-control'%>
        </div>
    <div class="form-group">
        <%=f.label:content %>
        <%= f.text_area :mail_content,class:'form-control' %>
    </div>
    <div>
    <%= f.submit'送信', class: "btn btn-sm btn-success" %>
    </div>
    <% end %>
    </div>
  </div>
</div>

groups/send_mail.html.erb
<div class="container d-flex flex-column align-items-center text-left">
  <div>
    <h3 class="mb-3">送信が完了しました</h3>
    <p class="mb-1">内容は以下の通りです。</p>
    <div>
      [タイトル]<p class="font-weight-bold"> <%= @mail_title %></p>
    </div>
    <div>
      [本文]<p class="font-weight-bold"> <%= safe_join(@mail_content.split("\n"),tag(:br)) %></p>
    </div>
  </div>
</div>

safe_joinとは
渡された複数の文字列を連結し、エスケープ処理を施した上で一つの文字列に変換するRailsのヘルパーメソッド。

エスケープ処理とは
HTMLやJavaScriptなどのテキストベースのファイルで特別な意味を持つ文字(例:<、>、&)をそのまま表示したり実行したりすると、意図しない結果を生む可能性があるため、その文字を無効化するための処理。

safe join無しの記述だと、コンテント内で入れていた改行がなくなってしまったりするらしい。

groups/show.html.erb
<%= link_to 'Notice an Event',group_new_mail_path(@group), class: "btn btn-sm btn-info" %>

ルーティングの記述

routes.rb
#該当部分のみ
resources :groups, only:  [:new, :index, :show, :create, :edit, :update] do
    resource :group_users, only: [:create, :destroy]
    get "new/mail" => "groups#new_mail"
    get "send/mail" => "groups#send_mail"
  end

メールのview記述

views/contact_mailer/send_mail.text.erb
=========================================
New event from <%= @group.name %>!!
=========================================

Title: 
<%= @mail_title %>

Details:
<%= @mail_content %>

確認

この流れで問題なく送信できているような気になっていましたが、
肝心のメールが自分宛に届かず。。

なぜか調べたところ

devise.rbのconfig.mailer_senderに、
送信元となるGmailアドレス(development.rbのuserに記述したのと同じアドレス)を記入
しなければならないそう!

config/initializers/devise.rb
config.mailer_sender = '送信元となるGmailアドレスを記入'

🌱こちらの記事がとてもわかりやすかったです!!
https://qiita.com/mi-1109/items/974c03776eba61146aa4

また、development.rbに載っているメールアドレスと、アプリパスワードをgithubにそのままプッシュしないように注意です!

🌱参考にさせていただいた記事
https://qiita.com/ki_87/items/67f8965e8de17e95ac1c


上記とは違う書き方のメモ

メーラーの編集

mailers/event_mailer.rb
class EventMailer < ApplicationMailer
  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: 'New Event Notice!!'
    )
  end
  
  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

サーバーを設定

config/enviroments/development.rb
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:              'smtp.gmail.com',
    port:                  587,
    domain:               'gmail.com',
    user_name:            ENV['MAIL_ADDRESS'],
    password:             ENV['MAIL_PASSWORD'],
    authentication:       'plain',
    enable_starttls_auto:  true
  }

ルーティング

routes.rb
resources :groups, only: [:new, :index, :show, :create, :edit, :update] do
    resource :group_users, only: [:create, :destroy]
    resources :event_notices, only: [:new, :create]
    get "event_notices" => "event_notices#sent"
  end

コントローラー

controllers/event_notices_controller.rb
class EventNoticesController < ApplicationController
  
  def new
    @group = Group.find(params[:group_id])
  end
  
  def create
    @group = Group.find(params[:group_id])
    @title = params[:title]
    @body = params[:body] 
    
    event = { 
      :group => @group, 
      :title => @title, 
      :body => @body 
    }
    
    EventMailer.send_notifications_to_group(event)
    render :sent
  end
  
  def sent
    redirect_to group_path(params[:group_id])
  end
end

ビュー

views/event_notices/new.html.erb
<div class="container">
  <div class="row justify-content-center">
    <div class="col-6">
      <h1>Event Mail</h1>
      
      <%= form_with url: group_event_notices_path(@group), method: :post, local:true do |f| %>
        <div class="form-group">
          <%= f.label :title %>
          <%= f.text_field :title, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :body %>
          <%= f.text_area :body, class: 'form-control' %>
        </div>
        <div class="form-group d-flex justify-content-end">
          <%= f.submit "Send", class: 'btn btn-success' %>
        </div>
      <% end %>
    </div>
  </div>
</div>
views/event_notices/sent.html.erb
<div class="container">
  <div class="row justify-content-center">
    <div class="col-6">
      <h1>送信が完了しました</h1>
      <p>内容は以下の通りです。</p>
      
      <h2>[タイトル]</h2>
      <p><%= @title %></p>
      
      <h2>[本文]</h2>
      <p><%= @body %></p>
  </div>
</div>
views/event_mailer/send_notification.text.erb
=========================================
New event from <%= @group.name %>!!
===========================================

Title: 
<%= @title %>

Details:
<%= @body %>

こんな書き方もある💡

Discussion