forked from shibao/cannery
		
	add emails
This commit is contained in:
		
							
								
								
									
										48
									
								
								lib/lokal/accounts/email.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								lib/lokal/accounts/email.ex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
defmodule Lokal.Email do
 | 
			
		||||
  @moduledoc """
 | 
			
		||||
  Emails that can be sent using Swoosh.
 | 
			
		||||
 | 
			
		||||
  You can find the base email templates at
 | 
			
		||||
  `lib/Lokal_web/templates/layout/email.html.heex` for html emails and
 | 
			
		||||
  `lib/Lokal_web/templates/layout/email.txt.heex` for text emails.
 | 
			
		||||
  """
 | 
			
		||||
 | 
			
		||||
  use Phoenix.Swoosh, view: LokalWeb.EmailView, layout: {LokalWeb.LayoutView, :email}
 | 
			
		||||
  import LokalWeb.Gettext
 | 
			
		||||
  alias Lokal.Accounts.User
 | 
			
		||||
  alias LokalWeb.EmailView
 | 
			
		||||
 | 
			
		||||
  @typedoc """
 | 
			
		||||
  Represents an HTML and text body email that can be sent
 | 
			
		||||
  """
 | 
			
		||||
  @type t() :: Swoosh.Email.t()
 | 
			
		||||
 | 
			
		||||
  @spec base_email(User.t(), String.t()) :: t()
 | 
			
		||||
  defp base_email(%User{email: email}, subject) do
 | 
			
		||||
    from = Application.get_env(:Lokal, Lokal.Mailer)[:email_from] || "noreply@localhost"
 | 
			
		||||
    name = Application.get_env(:Lokal, Lokal.Mailer)[:email_name]
 | 
			
		||||
    new() |> to(email) |> from({name, from}) |> subject(subject)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @spec generate_email(key :: String.t(), User.t(), attrs :: map()) :: t()
 | 
			
		||||
  def generate_email("welcome", user, %{"url" => url}) do
 | 
			
		||||
    user
 | 
			
		||||
    |> base_email(dgettext("emails", "Confirm your %{name} account", name: "Lokal"))
 | 
			
		||||
    |> render_body("confirm_email.html", %{user: user, url: url})
 | 
			
		||||
    |> text_body(EmailView.render("confirm_email.txt", %{user: user, url: url}))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def generate_email("reset_password", user, %{"url" => url}) do
 | 
			
		||||
    user
 | 
			
		||||
    |> base_email(dgettext("emails", "Reset your %{name} password", name: "Lokal"))
 | 
			
		||||
    |> render_body("reset_password.html", %{user: user, url: url})
 | 
			
		||||
    |> text_body(EmailView.render("reset_password.txt", %{user: user, url: url}))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def generate_email("update_email", user, %{"url" => url}) do
 | 
			
		||||
    user
 | 
			
		||||
    |> base_email(dgettext("emails", "Update your %{name} email", name: "Lokal"))
 | 
			
		||||
    |> render_body("update_email.html", %{user: user, url: url})
 | 
			
		||||
    |> text_body(EmailView.render("update_email.txt", %{user: user, url: url}))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										13
									
								
								lib/lokal/accounts/email_worker.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/lokal/accounts/email_worker.ex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
defmodule Lokal.EmailWorker do
 | 
			
		||||
  @moduledoc """
 | 
			
		||||
  Oban worker that dispatches emails
 | 
			
		||||
  """
 | 
			
		||||
 | 
			
		||||
  use Oban.Worker, queue: :mailers, tags: ["email"]
 | 
			
		||||
  alias Lokal.{Accounts, Email, Mailer}
 | 
			
		||||
 | 
			
		||||
  @impl Oban.Worker
 | 
			
		||||
  def perform(%Oban.Job{args: %{"email" => email, "user_id" => user_id, "attrs" => attrs}}) do
 | 
			
		||||
    Email.generate_email(email, user_id |> Accounts.get_user!(), attrs) |> Mailer.deliver()
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -1,7 +1,42 @@
 | 
			
		||||
defmodule Lokal.Mailer do
 | 
			
		||||
  @moduledoc """
 | 
			
		||||
  Mailer, currently uses Swoosh
 | 
			
		||||
  Mailer adapter for emails
 | 
			
		||||
 | 
			
		||||
  Since emails are loaded as Oban jobs, the `:attrs` map must be serializable to
 | 
			
		||||
  json with Jason, which restricts the use of structs.
 | 
			
		||||
  """
 | 
			
		||||
 | 
			
		||||
  use Swoosh.Mailer, otp_app: :lokal
 | 
			
		||||
  alias Lokal.{Accounts.User, EmailWorker}
 | 
			
		||||
  alias Oban.Job
 | 
			
		||||
 | 
			
		||||
  @doc """
 | 
			
		||||
  Deliver instructions to confirm account.
 | 
			
		||||
  """
 | 
			
		||||
  @spec deliver_confirmation_instructions(User.t(), String.t()) :: Job.t()
 | 
			
		||||
  def deliver_confirmation_instructions(%User{id: user_id}, url) do
 | 
			
		||||
    %{email: :welcome, user_id: user_id, attrs: %{url: url}}
 | 
			
		||||
    |> EmailWorker.new()
 | 
			
		||||
    |> Oban.insert!()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @doc """
 | 
			
		||||
  Deliver instructions to reset a user password.
 | 
			
		||||
  """
 | 
			
		||||
  @spec deliver_reset_password_instructions(User.t(), String.t()) :: Job.t()
 | 
			
		||||
  def deliver_reset_password_instructions(%User{id: user_id}, url) do
 | 
			
		||||
    %{email: :reset_password, user_id: user_id, attrs: %{url: url}}
 | 
			
		||||
    |> EmailWorker.new()
 | 
			
		||||
    |> Oban.insert!()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @doc """
 | 
			
		||||
  Deliver instructions to update a user email.
 | 
			
		||||
  """
 | 
			
		||||
  @spec deliver_update_email_instructions(User.t(), String.t()) :: Job.t()
 | 
			
		||||
  def deliver_update_email_instructions(%User{id: user_id}, url) do
 | 
			
		||||
    %{email: :update_email, user_id: user_id, attrs: %{url: url}}
 | 
			
		||||
    |> EmailWorker.new()
 | 
			
		||||
    |> Oban.insert!()
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								lib/lokal_web/templates/email/confirm_email.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/lokal_web/templates/email/confirm_email.html.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center;">
 | 
			
		||||
  <span style="margin-bottom: 0.75em; font-size: 1.5em;">
 | 
			
		||||
    <%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
  </span>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <span style="margin-bottom: 1em; font-size: 1.25em;">
 | 
			
		||||
    <%= dgettext("emails", "Welcome to %{name}!", name: "Lokal") %>
 | 
			
		||||
  </span>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails", "You can confirm your account by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <a style="margin: 1em; color: rgb(31, 31, 31);" href="<%= @url %>"><%= @url %></a>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails",
 | 
			
		||||
    "If you didn't create an account at %{name}, please ignore this.",
 | 
			
		||||
    name: "Lokal") %>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										12
									
								
								lib/lokal_web/templates/email/confirm_email.txt.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lib/lokal_web/templates/email/confirm_email.txt.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "Welcome to %{name}%!", name: "Lokal") %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "You can confirm your account by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
<%= @url %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails",
 | 
			
		||||
  "If you didn't create an account at %{url}, please ignore this.",
 | 
			
		||||
  url: Routes.live_url(Endpoint, PageLive)) %>
 | 
			
		||||
							
								
								
									
										19
									
								
								lib/lokal_web/templates/email/reset_password.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/lokal_web/templates/email/reset_password.html.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center;">
 | 
			
		||||
  <span style="margin-bottom: 0.5em; font-size: 1.5em;">
 | 
			
		||||
    <%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
  </span>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails", "You can reset your password by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <a style="margin: 1em; color: rgb(31, 31, 31);" href="<%= @url %>"><%= @url %></a>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails",
 | 
			
		||||
    "If you didn't request this change from %{name}, please ignore this.",
 | 
			
		||||
    name: "Lokal") %>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/lokal_web/templates/email/reset_password.txt.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/lokal_web/templates/email/reset_password.txt.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "You can reset your password by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
<%= @url %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails",
 | 
			
		||||
  "If you didn't request this change from %{url}, please ignore this.",
 | 
			
		||||
  url: Routes.live_url(Endpoint, PageLive)) %>
 | 
			
		||||
							
								
								
									
										19
									
								
								lib/lokal_web/templates/email/update_email.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/lokal_web/templates/email/update_email.html.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center;">
 | 
			
		||||
  <span style="margin-bottom: 0.5em; font-size: 1.5em;">
 | 
			
		||||
    <%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
  </span>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails", "You can change your email by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <a style="margin: 1em; color: rgb(31, 31, 31);" href="<%= @url %>"><%= @url %></a>
 | 
			
		||||
 | 
			
		||||
  <br/>
 | 
			
		||||
 | 
			
		||||
  <%= dgettext("emails",
 | 
			
		||||
    "If you didn't request this change from %{name}, please ignore this.",
 | 
			
		||||
    name: "Lokal") %>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/lokal_web/templates/email/update_email.txt.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/lokal_web/templates/email/update_email.txt.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "Hi %{email},", email: @user.email) %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails", "You can change your email by visiting the URL below:") %>
 | 
			
		||||
 | 
			
		||||
<%= @url %>
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails",
 | 
			
		||||
  "If you didn't request this change from %{url}, please ignore this.",
 | 
			
		||||
  url: Routes.live_url(Endpoint, PageLive)) %>
 | 
			
		||||
							
								
								
									
										24
									
								
								lib/lokal_web/templates/layout/email.html.heex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/lokal_web/templates/layout/email.html.heex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <title>
 | 
			
		||||
      <%= @email.subject %>
 | 
			
		||||
    </title>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body
 | 
			
		||||
    style="padding: 2em; color: rgb(31, 31, 31); background-color: rgb(220, 220, 228); font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; text-align: center;"
 | 
			
		||||
  >
 | 
			
		||||
    <%= @inner_content %>
 | 
			
		||||
 | 
			
		||||
    <hr
 | 
			
		||||
      style="margin: 2em auto; border-width: 1px; border-color: rgb(212, 212, 216); width: 100%; max-width: 42rem;"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <a style="color: rgb(31, 31, 31);" href={Routes.live_url(Endpoint, PageLive)}>
 | 
			
		||||
      <%= dgettext(
 | 
			
		||||
        "emails",
 | 
			
		||||
        "This email was sent from %{name}, the self-hosted firearm tracker website.",
 | 
			
		||||
        name: "Lokal"
 | 
			
		||||
      ) %>
 | 
			
		||||
    </a>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										12
									
								
								lib/lokal_web/templates/layout/email.txt.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lib/lokal_web/templates/layout/email.txt.eex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<%= @email.subject %>
 | 
			
		||||
 | 
			
		||||
====================
 | 
			
		||||
 | 
			
		||||
<%= @inner_content %>
 | 
			
		||||
 | 
			
		||||
=====================
 | 
			
		||||
 | 
			
		||||
<%= dgettext("emails",
 | 
			
		||||
  "This email was sent from %{name} at %{url}, the self-hosted firearm tracker website.",
 | 
			
		||||
  name: "Lokal",
 | 
			
		||||
  url: Routes.live_url(Endpoint, PageLive)) %>
 | 
			
		||||
							
								
								
									
										1
									
								
								lib/lokal_web/templates/layout/empty.html.heex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								lib/lokal_web/templates/layout/empty.html.heex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<%= @inner_content %>
 | 
			
		||||
							
								
								
									
										8
									
								
								lib/lokal_web/views/email_view.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								lib/lokal_web/views/email_view.ex
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
defmodule LokalWeb.EmailView do
 | 
			
		||||
  @moduledoc """
 | 
			
		||||
  A view for email-related helper functions
 | 
			
		||||
  """
 | 
			
		||||
  alias LokalWeb.{Endpoint, PageLive}
 | 
			
		||||
 | 
			
		||||
  use LokalWeb, :view
 | 
			
		||||
end
 | 
			
		||||
		Reference in New Issue
	
	Block a user