【Rails7】Windows ActionMailerを使ってGmailからメール送信してみよう【初心者用】

PG工場

RailsでGmailからメール送信してみよう

本記事ではActionMailerを使ってGmailからメール送信する機能の作り方を紹介します。Googleのアプリパスワードの作成方法など初心者でもわかりやすいように丁寧にご説明いたしますので、ぜひ参考にしてみてください。

■Googleアプリパスワードの作成

Gmailからメール送信するためにはGoogleのアプリパスワードが必要です。1から4の手順で作業を進めます。
手順1. Googleアカウントの作成する
手順2. Googleアカウントへログインする
手順3. 2段階認証プロセスを有効にする
手順4. アプリパスワードを作成する

Googleアカウントをまだ持っていない人はGoogleのホームページからアカウントを作成しましょう(ここでの説明は省略します)。Googleアカウントへログインしたら下記URLへアクセスします。
https://myaccount.google.com/

Googleアカウント画面が表示されたら左サイドバーのメニューリストの上から4つ目の「セキュリティ」をクリックします。
セキュリティ画面が表示されたら「Google にログインする方法」のところまで下にスクロールし「2段階認証プロセス」をクリックします。

「2段階認証プロセス」画面が表示されるので2段階認証プロセスが無効になっていたら有効に変更します。

そして、その画面を一番下までスクロールすると「アプリパスワード」の項目がでてくるので「アプリパスワード」をクリックします。
アプリパスワード画面が表示されるので「Appname」の入力欄にアプリの名前などを入力してください(何でもよいです)。

画面右下の「作成」ボタンをクリックします。認証画面が表示されたらGoogleアカウントを作成したときのパスワードを入力し「次へ」をクリックします。

生成されたアプリ パスワードが表示されますので、どこかにメモしておきましょう。このパスワードは1回しか表示されません。もし忘れてしまったら何度でも作成できます。

■RubyOnRailsでアプリケーション作成

【開発環境】
ruby 3.0.2
rails 7.1.2
Windows10

これからRailsでアプリを作成していきます。

それではコマンドプロンプトを開いてアプリを作成するフォルダへ移動します。
下記コマンドを実行します。”>”はコマンド入力可能の文字ですので入力しないでください。

>cd C:\Rails_Apps\Ruby32\

ここのフォルダでrails newコマンドでアプリの作成を始めます。下記コマンドを実行してください。「GmailApp」がアプリ名です。

>rails new GmailApp

【実行結果】

C:\Rails_Apps\Ruby32>rails new GmailApp
      create
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
      create  .gitattributes
      create  Gemfile
         run  git init from "."
Initialized empty Git repository in C:/Rails_Apps/Ruby32/GmailApp/.git/
      create  app
      create  app/assets/config/manifest.js
      create  app/assets/stylesheets/application.css
      create  app/channels/application_cable/channel.rb
      create  app/channels/application_cable/connection.rb
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/jobs/application_job.rb
      create  app/mailers/application_mailer.rb
      create  app/models/application_record.rb
      create  app/views/layouts/application.html.erb
      create  app/views/layouts/mailer.html.erb
      create  app/views/layouts/mailer.text.erb
      create  app/assets/images
      create  app/assets/images/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/rails
      create  bin/rake
      create  bin/setup
      create  Dockerfile
      create  .dockerignore
      create  bin/docker-entrypoint
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/cable.yml
      create  config/puma.rb
      create  config/storage.yml
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/assets.rb
      create  config/initializers/content_security_policy.rb
      create  config/initializers/cors.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/new_framework_defaults_7_1.rb
      create  config/initializers/permissions_policy.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/master.key
      append  .gitignore
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  lib/assets
      create  lib/assets/.keep
      create  log
      create  log/.keep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/apple-touch-icon-precomposed.png
      create  public/apple-touch-icon.png
      create  public/favicon.ico
      create  public/robots.txt
      create  tmp
      create  tmp/.keep
      create  tmp/pids
      create  tmp/pids/.keep
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor
      create  vendor/.keep
      create  test/fixtures/files
      create  test/fixtures/files/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/channels/application_cable/connection_test.rb
      create  test/test_helper.rb
      create  test/system
      create  test/system/.keep
      create  test/application_system_test_case.rb
      create  storage
      create  storage/.keep
      create  tmp/storage
      create  tmp/storage/.keep
      remove  config/initializers/cors.rb
      remove  config/initializers/new_framework_defaults_7_1.rb
         run  bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Using rake 13.1.0
Using base64 0.2.0
Using bigdecimal 3.1.4
Using concurrent-ruby 1.2.2
Using connection_pool 2.4.1
Using ruby2_keywords 0.0.5
Using minitest 5.20.0
Using mutex_m 0.2.0
Using builder 3.2.4
Using erubi 1.12.0
Using mini_portile2 2.8.5
Using racc 1.7.3
Using rack 3.0.8
Using crass 1.0.6
Using websocket-extensions 0.1.5
Fetching nio4r 2.7.0
Using zeitwerk 2.6.12
Using timeout 0.4.1
Using marcel 1.0.2
Using mini_mime 1.1.5
Using date 3.3.4
Using public_suffix 5.0.4
Using bindex 0.8.1
Using msgpack 1.7.2
Using bundler 2.4.13
Using matrix 0.4.2
Fetching regexp_parser 2.8.3
Installing regexp_parser 2.8.3
Installing nio4r 2.7.0 with native extensions
Fetching stringio 3.1.0
Installing stringio 3.1.0 with native extensions
Using io-console 0.6.0
Using webrick 1.8.1
Using thor 1.3.0
Using rexml 3.2.6
Using rubyzip 2.3.2
Using websocket 1.2.10
Using i18n 1.14.1
Using tzinfo 2.0.6
Using drb 2.2.0
Using nokogiri 1.15.5
Using sqlite3 1.6.9
Using rack-session 2.0.0
Using rack-test 2.1.0
Using sprockets 4.2.1
Using websocket-driver 0.7.6
Using net-protocol 0.2.2
Using addressable 2.8.5
Using bootsnap 1.17.0
Using puma 6.4.0
Fetching reline 0.4.1
Installing reline 0.4.1
Using rackup 2.1.0
Fetching selenium-webdriver 4.16.0
Installing selenium-webdriver 4.16.0
Using activesupport 7.1.2
Using loofah 2.22.0
Using xpath 3.2.0
Fetching net-imap 0.4.7
Installing net-imap 0.4.7
Using net-pop 0.1.2
Using net-smtp 0.4.0
Using rails-dom-testing 2.2.0
Using globalid 1.2.1
Using activemodel 7.1.2
Using rails-html-sanitizer 1.6.0
Using capybara 3.39.2
Using mail 2.8.1
Using activejob 7.1.2
Using actionview 7.1.2
Using activerecord 7.1.2
Using actionpack 7.1.2
Using jbuilder 2.11.5
Using actioncable 7.1.2
Using activestorage 7.1.2
Using actionmailer 7.1.2
Using sprockets-rails 3.4.2
Using actionmailbox 7.1.2
Using actiontext 7.1.2
Using psych 5.1.1.1
Fetching rdoc 6.6.1
Installing rdoc 6.6.1
Fetching irb 1.10.1
Installing irb 1.10.1
Using debug 1.8.0
Using railties 7.1.2
Using importmap-rails 1.2.3
Using rails 7.1.2
Using stimulus-rails 1.3.0
Using web-console 4.2.1
Using turbo-rails 1.5.0
Bundle complete! 14 Gemfile dependencies, 83 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
         run  bundle lock --add-platform=x86_64-linux
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Writing lockfile to C:/Rails_Apps/Ruby32/GmailApp/Gemfile.lock
         run  bundle binstubs bundler
       rails  importmap:install
bin/rails aborted!
TZInfo::DataSourceNotFound: tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install
C:/Rails_Apps/Ruby32/GmailApp/config/environment.rb:5:in `
' Caused by: TZInfo::DataSources::ZoneinfoDirectoryNotFound: None of the paths included in TZInfo::DataSources::ZoneinfoDataSource.search_path are valid zoneinfo directories. C:/Rails_Apps/Ruby32/GmailApp/config/environment.rb:5:in `
' Tasks: TOP => app:template => environment (See full trace by running task with --trace) rails turbo:install stimulus:install You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem. You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem. C:\Rails_Apps\Ruby32>

上記のように表示されれば実行が完了です。
作成されたアプリのフォルダへ移動する必要がありますので下記コマンドを実行しフォルダ移動します。

C:\Rails_Apps\Ruby32>cd GmailApp

下記のようにフォルダへ移動され”>”の位置が「GmailApp」の右になりました。

C:\Rails_Apps\Ruby32\GmailApp>

■VisualStudioCodeを開く

実際のプログラムコードの記述は「VisualStudioCode」を使用します。「VisualStudioCode」を開いたらメニューの「ファイル」→「フォルダを開く」からアプリのフォルダを開きます。

■Gemfileの”tzinfo-data”の修正

TZInfoとはRubyからタイムゾーン情報を参照し、その情報にもとづいた時間を変換するためのライブラリです。Windowsにはzoneinfoファイルが含まれていないためgemfileの39行目あたりの下記コードを修正します。やることは簡単です。gem “tzinfo-data”以下の文字を削除するか下記のように”#”を入力しコメントアウトし(#から右の文字は無効)gemfileを保存します。

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data"# ←"#"を追記, platforms: %i[ windows jruby ]

gemfileを編集したので「bundle indtall」コマンドを実行すると「gemfile.lock」ファイルが自動で書き換わります。

>bundle install

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Using rake 13.1.0
Using base64 0.2.0
Using bigdecimal 3.1.4
Using concurrent-ruby 1.2.2
Using connection_pool 2.4.1
Using ruby2_keywords 0.0.5
Using drb 2.2.0
Using i18n 1.14.1
Using minitest 5.20.0
Using mutex_m 0.2.0
Using tzinfo 2.0.6
Using activesupport 7.1.2
Using builder 3.2.4
Using erubi 1.12.0
Using mini_portile2 2.8.5
Using racc 1.7.3
Using nokogiri 1.15.5
Using rails-dom-testing 2.2.0
Using crass 1.0.6
Using loofah 2.22.0
Using rails-html-sanitizer 1.6.0
Using actionview 7.1.2
Using rack 3.0.8
Using rack-session 2.0.0
Using rack-test 2.1.0
Using actionpack 7.1.2
Using nio4r 2.7.0
Using websocket-extensions 0.1.5
Using websocket-driver 0.7.6
Using zeitwerk 2.6.12
Using actioncable 7.1.2
Using globalid 1.2.1
Using activejob 7.1.2
Using activemodel 7.1.2
Using timeout 0.4.1
Using activerecord 7.1.2
Using marcel 1.0.2
Using activestorage 7.1.2
Using mini_mime 1.1.5
Using date 3.3.4
Using net-protocol 0.2.2
Using net-imap 0.4.7
Using net-pop 0.1.2
Using net-smtp 0.4.0
Using mail 2.8.1
Using actionmailbox 7.1.2
Using actionmailer 7.1.2
Using actiontext 7.1.2
Using public_suffix 5.0.4
Using addressable 2.8.5
Using bindex 0.8.1
Using msgpack 1.7.2
Using bootsnap 1.17.0
Using bundler 2.4.13
Using matrix 0.4.2
Using regexp_parser 2.8.3
Using xpath 3.2.0
Using capybara 3.39.2
Using stringio 3.1.0
Using psych 5.1.1.1
Using rdoc 6.6.1
Using io-console 0.6.0
Using reline 0.4.1
Using irb 1.10.1
Using debug 1.8.0
Using webrick 1.8.1
Using rackup 2.1.0
Using thor 1.3.0
Using railties 7.1.2
Using importmap-rails 1.2.3
Using jbuilder 2.11.5
Using puma 6.4.0
Using rails 7.1.2
Using rexml 3.2.6
Using rubyzip 2.3.2
Using websocket 1.2.10
Using selenium-webdriver 4.16.0
Using sprockets 4.2.1
Using sprockets-rails 3.4.2
Using sqlite3 1.6.9
Using stimulus-rails 1.3.0
Using turbo-rails 1.5.0
Using tzinfo-data 1.2023.3
Using web-console 4.2.1
Bundle complete! 14 Gemfile dependencies, 84 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

C:\Rails_Apps\Ruby32\GmailApp>

■Railsサーバーを立ち上げる

サーバーが立ち上がるかどうか確認します。「rails s」コマンドを実行すると下記のようにプロンプトが出力されるとサーバーが立ち上がります。

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>rails s
=> Booting Puma
=> Rails 7.1.2 application starting in development
=> Run `bin/rails server --help` for more startup options
*** SIGUSR2 not implemented, signal based restart unavailable!
*** SIGUSR1 not implemented, signal based restart unavailable!
*** SIGHUP not implemented, signal based logs reopening unavailable!
Puma starting in single mode...
* Puma version: 6.4.0 (ruby 3.0.2-p107) ("The Eagle of Durango")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 17960
* Listening on http://[::1]:3000
* Listening on http://127.0.0.1:3000
Use Ctrl-C to stop

EdgeやCromeなどのWebブラウザを開いてアドレスバーに「localhost:3000」を入力します。下記WEB画面が表示されればrailsサーバーが立ち上がったことが確認できます。

■Action Mailerで「Infomail」モデルをつくる

ユーザーがシステムの管理者に問い合わせメールを送信するプログラムを作っていきます。まず、問い合わせの内容を保存するModelから作成します。下記コマンドを実行し名前とメッセージの2つのカラムを文字列型で指定し、Infomailモデルを作成します。

>rails g model Infomail name:string 

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>rails g model Infomail name:string message:string
      invoke  active_record
      create    db/migrate/20231209112728_create_infomails.rb
      create    app/models/infomail.rb
      invoke    test_unit
      create      test/models/infomail_test.rb
      create      test/fixtures/infomails.yml

上記の内容が表示されモデルが作成されました。この時点ではまだデータベースが作成されていませんので下記コマンドでテーブルを作成します。

>rails db:migrate

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>rails db:migrate
== 20231209112728 CreateInfomails: migrating ==================================
-- create_table(:infomails)
   -> 0.0073s
== 20231209112728 CreateInfomails: migrated (0.0089s) =========================

上記の様に表示されたらデーブル作成成功です。

■Action Mailerをつくる

メール送信する機能のAction Mailerはgenerateコマンドから作成できます。下記コマンドを実行してください。

>rails g mailer Infomail

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>rails g mailer Infomail
      create  app/mailers/infomail_mailer.rb
      invoke  erb
      create    app/views/infomail_mailer
      invoke  test_unit
      create    test/mailers/infomail_mailer_test.rb
      create    test/mailers/previews/infomail_mailer_preview.rb

■メールの宛先、件名を設定する

これから実際にコードを記述していきます。先ほどのコマンドを実行するとapp\mailers\infomail_mailer.rb ファイルが作成されます。そのファイルを開くと下記のようにApplicationMailerクラスを継承したInfomailMailerクラスが作成されます。(中身は空です)

class InfomailMailer < ApplicationMailer
end

InfomailMailerクラスにメールを送信するInfo_mailメソッドを下記のように記述します。

class InfomailMailer < ApplicationMailer
  def send_mail(infomail)
    @infomail = infomail
    mail(
      from: 'infouser@example.com',
      to:   'admin@example.com',
      subject: 'お問い合わせ通知'
    )
  end
end

mailメソッドのオプションは下記の通りです。このようにオプションを利用すると通常のメール送信と同様のことができます。

オプション説明補足
from送信元メールアドレス
subjectメールの件名
toメールの送信先アドレス複数の宛先には”,”(カンマ)区切りまたは配列を指定
ccカーボンコピーのメールアドレス複数の宛先には”,”(カンマ)区切りまたは配列を指定
bccブラインドカーボンコピーのメールアドレス複数の宛先には”,”(カンマ)区切りまたは配列を指定

■メールの本文を作成する

send_mail.text.erbを下記のフォルダ内に新規で作成します。

app\views\infomail_mailer\send_mail.text.erb

<%= @infomail.name %> 様 から問い合わせがありました。
・お問い合わせ内容
<%= @infomail.message %>

■プレビューでメール内容を確認する

実際にメールを送信せずにメールの内容を確認することができます。Action Mailerはgenerateコマンドですでに作成れている下記ファイルを開きます。

test\mailers\previews\infomail_mailer_preview.rb

ActionMailer::Previewクラスを継承したInfomailMailerPreviewクラスにコードを記述していきます。

# Preview all emails at http://localhost:3000/rails/mailers/infomail_mailer
class InfomailMailerPreview < ActionMailer::Preview
  def infomail
    infomail = Infomail.new(name: "mario", message: "問合せメッセージ")
    InfomailMailer.send_mail(infomail)
  end
end

rails sコマンドでサーバーを立ち上げ、下記URLへアクセスします。

http://localhost:3000/rails/mailers/infomail_mailer

上記の画面が表示されますので「infomail」リンクをクリックするとメールプレビューが表示されます。

■Gmailで送信するための設定

それでは実際にメールを送信するための設定をしていきます。開発環境での設定をしますので下記ファイルを開いてください。

config\environments\development.rb

:smtpの配信メソッドの詳細設定を行います。ファイルを開いたら一番下に下記のコードを追記します。

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
   address:              'smtp.gmail.com',
   port:                  587,
   domain:               'gmail.com',
   user_name:            'xxxxx@gmail.com',
   password:             'bgyz hjum wylm kahp',
   authentication:       'plain',
   enable_starttls_auto:  true
  }

address:とport:とdomain:は固定値です。user_name:にgmailのメールアドレスを、password:に、本記事「1.Googleアプリパスワードの説明」で取得したアプリパスワードを入力します。(16桁の番号です)

gmailを使用する場合の項目説明一覧です。

項目入力値説明
address:'smtp.gmail.com',固定値。リモートメールサーバーを利用可能にします
port:587,固定値。メールサーバーのポート番号です
domain:'gmail.com',固定値。ドメインを指定
user_name:'xxxxx@gmail.com',gmailのメールアドレス
password:'gmail.com',Googleのアプリパスワード(16桁番号)
authentication:'plain',メールサーバーで認証が必要な場合はここで認証の種類を指定。('plain'の場合パスワードを平文で送信)
enable_starttls_auto:trueSMTPサーバーでSTARTTLSが有効かどうかを検出して有効にします。(デフォルトはtrue)

■メール送信してみよう

これでメール送信するための設定が完了しましたので実際にメールを送信してみます。コマンドプロンプトのRailsコンソールからdeliver_nowメソッドを実行します。メール送信の実行タイミングはRailsのコントローラーなどから実行できますが、まずははRailsコンソールから実行します。

app\mailers\infomail_mailer.rbファイルのsend_mailメソッドに記述済みの送信元、送信先、件名で送付されますので入力に間違いがないか確認してから実行しましょう。

【再掲載】

class InfomailMailer < ApplicationMailer
  def send_mail(infomail)
    @infomail = infomail
    mail(
      from: 'infouser@example.com',
      to:   'admin@example.com',
      subject: 'お問い合わせ通知'
    )
  end
end

それではコンソールに下記コマンドを実行しRailsコンソールに切り替えます。

>rails c

【実行結果】

C:\Rails_Apps\Ruby32\GmailApp>rails c
Loading development environment (Rails 7.1.2)
irb(main):001>

Railsコンソールに切り替わりましたので下記コマンドを実行します。

irb(main):001:0> infomail = Infomail.new(name: "mario", message: "テスト_問い合わせ")
irb(main):002:0> InfomailMailer.send_mail(infomail).deliver_now

【実行結果】

irb(main):001> infomail = Infomail.new(name: "mario", message: "テスト_問い合わせ")
=>
# InfomailMailer.send_mail(infomail).deliver_now
  Rendering layout layouts/mailer.text.erb
  Rendering infomail_mailer/send_mail.text.erb within layouts/mailer
  Rendered infomail_mailer/send_mail.text.erb within layouts/mailer (Duration: 3.2ms | Allocations: 251)
  Rendered layout layouts/mailer.text.erb (Duration: 15.7ms | Allocations: 495)
InfomailMailer#send_mail: processed outbound mail in 631.5ms
Delivered mail 657527c279e93_43cc8050043@LAPTOP.mail (16301.0ms)
Date: Sun, 10 Dec 2023 11:26:10 +0900
From: infouser@example.com
To: admin@example.com
Message-ID: <657521c879e93_43cc8050043@LAPTOP.mail>
Subject: =?UTF-8?Q?=E3=81=8A=E5=95=8F=E3=81=84=E5=00=88=E3=82=8F=E3=81=9B=E9=80=9A=E7=9F=A5?=
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: base64

bWFyaW8g5qeYIOOBi+OCieWVj+OBhOWQiOOCj+OBm+OBjOOBguOCiuOBvuOB
l+OBn+OAgg0K44O744GK5ZWP44GE5ZCI88KP44Gb5YaF5a65DQrjg4bjgrnj
g4hf5ZWP44GE5ZCI44KP44GbDQo=

=> #, , , >, , , , >
irb(main):003>

上記の様に表示されたらメール送信が完了です。実際にメールが届いているか確認してみましょう。なお、上記の実行結果のメールアドレスは架空のアドレスに修正しています。

コメント