Swoosh

Compose, deliver and test your emails easily in Elixir.

Published on 2020-06-20 00:00:00

Elixirでメーラーとして使えるライブラリです。
アダプタが多数用意 されており、 Getting started に従うだけで使い始めることができます。

使い方

ここではSMTPアダプタを利用した使い方を紹介します。
以下の順に説明しますがアダプタの設定以外はSMTPにかかわらず共通です。
また、説明はPhoenix上での利用例です。
  • App.Mailerを作成する

  • メール作成ロジックの記述

  • 送信ロジックの記述

  • アダプタの設定

MyApp.Mailerを作成する

lib/my_app/mailer.ex として以下を作成します。

defmodule MyApp.Mailer do
  use Swoosh.Mailer, otp_app: :my_app
end

これにより、後述するdeliver関数をこのモジュールに展開します。

メール作成ロジックの記述

コンタクトフォームで入力した内容を元にメールを作成する場合は
lib/my_app/contacts.ex として以下を作成します。

Swoosh.Emailの関数一覧はこちら

defmodule MyApp.Contacts do
  import Swoosh.Email
  alias MyApp.Contacts.Email

  def changeset(%Email{} = email, params \\ %{}) do
    Email.changeset(email, params)
  end

  def create_email(%Email{} = email) do
    new()
    |> to({"MyApp Customer Service", "[email protected]"})
    |> from({"Contact from website", "[email protected]"})
    |> reply_to({email.name, email.email_address})
    |> subject("Contact from website")
    |> text_body(email.content)
  end
end
MyApp.Contacts.Email は用途に合わせて作成します。以下は例です。
defmodule MyApp.Contacts.Email do
  use Ecto.Schema
  import Ecto.Changeset

  embedded_schema do
    field(:name, :string)
    field(:email_address, :string)
    field(:content, :string)
  end

  @email_address_regex ~r/\A[\w+\-.][email protected][a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  def changeset(email, attrs) do
    email
    |> cast(attrs, [:name, :email_address, :content])
    |> validate_required([:name, :email_address, :content])
    |> validate_format(:email_address, @email_address_regex)
  end
end

送信ロジックの記述

LiveComponent上のコンタクトフォームを例とした場合、以下のように記述します。
送信ボタン押下時に送出する"submit"を受けるロジックです。
※LiveViewを使わずにcontrollerでPOSTを受ける場合でもほぼ同じように書きます。
@impl true
def handle_event("submit", %{"contact" => params}, socket) do
  changeset = inputs_changeset(params)

  if changeset.valid? do
    {:ok, _} =
      changeset
      |> Ecto.Changeset.apply_changes()
      |> MyApp.Contacts.create_email()  # メールを作成
      |> MyApp.Mailer.deliver()         # メールを送信 シンプル!

    {
      :noreply,
      socket
      |> clear_flash()
      |> put_flash(:info, "お問い合わせありがとうございます。")
      |> push_redirect(to: Routes.live_path(socket, MyAppWeb.PageLive, page: "contact"))
    }
  else
    {
      :noreply,
      socket
      |> update(:changeset, fn _ -> changeset end)
      |> clear_flash()
      |> put_flash(:error, "入力をご確認ください。")
      |> push_patch(to: Routes.live_path(socket, MyAppWeb.PageLive, page: "contact"))
    }
  end
end

アダプタの設定

最後にプロダクション環境の config/prod.exs と config/prod.secret.exs にSMTPの設定をします。
※開発環境の場合は Mailbox preview in the browser を使うことができます。リンク先を参照ください。

prod.exs

config :my_app, MyApp.Mailer,
  adapter: Swoosh.Adapters.SMTP,
  relay: "契約しているメールサーバーを指定",
  tls: :always,  # メールサーバーに合わせて設定
  auth: :always, # メールサーバーに合わせて設定
  port: 587,     # メールサーバーに合わせて設定
  retries: 2,
  no_mx_lookups: false

prod.secret.exs

mail_server_user =
  System.get_env("MAIL_SERVER_USER") ||
    raise """
    environment variable MAIL_SERVER_USER is missing.
    """

mail_server_pass =
  System.get_env("MAIL_SERVER_PASS") ||
    raise """
    environment variable MAIL_SERVER_PASS is missing.
    """

config :my_apps, MyApp.Mailer,
  username: mail_server_user,
  password: mail_server_pass

以上です。

警告

海外でホストしているサービスから日本国内のメールサーバーを使うような場合、国内のメールサーバーが国外IPアドレスをフィルタしていないか注意してください。さくらインターネットは 国外IPアドレスフィルタ がデフォルトで有効ですので無効化しないとメールを送信することができません。