+++ date = "2018-08-24" tags = ["mail","phx"] title = "phxでmail notifyを実装した" slug = "phx" +++ ## 導入 今度は、少し機能多めのchatでもと思ってherokuにたててみました。login機能が付きます。 iconの取得はmailから`gravatar.com`を使ってるんじゃないですかね(知りませんが)。コード読めという話ですね。 さて、ではrepoのcloneからいきましょー。今回もexample chatみたいな感じのやつです。 ```sh $ git clone https://github.com/tony612/exchat $ cd !$:t $ cat ./elixir_buildpack.config erlang_version=20.1 elixir_version=1.6.0 always_rebuild=true config_vars_to_export=(DATABASE_URL JWT_SECRET) $ cat ./Procfile web: MIX_ENV=prod POOL_SIZE=2 mix ecto.migrate && mix phoenix.server # npm i # frontendは、react ,redux, jwt(login), bootstrapみたいな感じ。 $ heroku buildpacks:add --index 2 https://github.com/gjaldon/heroku-buildpack-phoenix-static.git -a $APP_NAME ``` `heroku config:set`には、`DATABASE_URL`, `JWT_SECRET`, `SECRET_KEY_BASE`を入れてください。というか、`DATABASE_URL`, `PORT`はpostgresを入れれば勝手に作成されると思う。JWTとKEYは、`$ mix phx.gen.sercet`になります。 ## notifyの実装 通知の手段は色々あるんですけど、mailが簡単そうなので、まずは簡単そうなものから。 > mix.exs ```erlang applications: [:bamboo] defp deps do [{:phoenix, "~> 1.3.3"}, {:bamboo, "~> 1.0.0"}, {:bamboo_smtp, "~> 1.5.0"} ] ``` > config/prod.ex ```erlang config :exchat, Exchat.Mailer, adapter: Bamboo.SMTPAdapter, server: "smtp.gmail.com", port: 587, username: System.get_env("GMAIL"), password: System.get_env("GMAIL_APP_PASS"), tls: :if_available, # can be `:always` or `:never` ssl: false, # can be `true` retries: 1 ``` これに関しては、`mailgun`とかを使うのが通常なんだけど、demoなのでgmailで。 > lib/mailer.ex ```erlang defmodule Exchat.Mailer do use Bamboo.Mailer, otp_app: :exchat end ``` > lib/mail.ex ```erlang defmodule Exchat.Email do use Bamboo.Phoenix, view: Exchat.EmailView def hello_email(email) do new_email |> to(email) |> from("support@xxx.herokuapp.com") |> subject("login") |> text_body(".") end end ``` userがloginしたらmailを送信するようにする。これによって、管理者は送信メールが出るので、それを通知すればいいかな。 > web/controllers/api_auth.ex ```erlang def login_by_email_pass(conn, email, pass, opts) do repo = Keyword.fetch!(opts, :repo) user = repo.get_by(User, email: email) cond do user && checkpw(pass, user.password_hash) -> Exchat.Email.hello_email(user.email) |> Exchat.Mailer.deliver_now {:ok, login(conn, user)} user -> {:error, :unauthorized, conn} true -> dummy_checkpw() {:error, :not_found, conn} end end ``` 実際、loginしてみてmailをcheckしてみる。確認できたなら、コードを変更。 DMやmessageが来た時も通知したければこんな感じでやってくとよさそう。 というかメールの通知は色々とつらい。普通はやらないと思うので、[ravenx](https://github.com/acutario/ravenx)/slackとか使うのがいいんでしょうか。 ## mailgun 一応、mailgunの書き方も掲載しておきます。 `mailgun`: 使用する上での注意点としては、freeの場合は、sandboxでしかapi/v3からmailの送信はできません。しかも、認証済みのmail addressにしか送れず、よって、`lib/mail.ex`を書き換えて、to:verify-email, from:sandbox.domain, text_body:emailというようにしなければなりません。つまり、login userに送信(通知)するのではなく誰かがloginした時に管理者に通知する役割しか担えませんので注意です。freeでない場合はapiから普通に送れますので大丈夫ですが。 ```erlang # In config/config.exs, or config.prod.exs, etc. config :my_app, MyApp.Mailer, adapter: Bamboo.MailgunAdapter, api_key: "my_api_key", domain: "your.domain" ``` mailgun(MailgunAdapter)を使う場合の`new_email`の値はこちらを参考に。 ```sh $ curl -s --user 'api:YOUR_API_KEY' \ https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages \ -F from='Excited User ' \ -F to=YOU@YOUR_DOMAIN_NAME \ -F to=bar@example.com \ -F subject='Hello' \ -F text='Testing some Mailgun awesomeness!' ```