[#1062] added option to disable send email
authorMaksim <parallel588@gmail.com>
Wed, 10 Jul 2019 05:34:21 +0000 (05:34 +0000)
committerkaniini <nenolod@gmail.com>
Wed, 10 Jul 2019 05:34:21 +0000 (05:34 +0000)
CHANGELOG.md
config/config.exs
config/test.exs
docs/config.md
lib/pleroma/emails/mailer.ex
mix.exs
mix.lock
test/emails/admin_email_test.exs [new file with mode: 0644]
test/emails/mailer_test.exs [new file with mode: 0644]
test/emails/user_email_test.exs [new file with mode: 0644]

index 227f721e31f6d956294f77689ac11c47d4ae5a6a..763cd8d9273132adc576498d0ad8a549d39c01fe 100644 (file)
@@ -14,6 +14,7 @@ Configuration: `federation_incoming_replies_max_depth` option
 - Admin API: Return avatar and display name when querying users
 - Admin API: Allow querying user by ID
 - Added synchronization of following/followers counters for external users
+- Configuration: `enabled` option for `Pleroma.Emails.Mailer`, defaulting to `false`.
 
 ### Fixed
 - Not being able to pin unlisted posts
index 09681f122ddbe8f8759cd005b7d09b1d3bb7f069..0d34191022f729b159b901de219e883b10aa1f3e 100644 (file)
@@ -501,7 +501,7 @@ config :ueberauth,
 
 config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
 
-config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail
+config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail, enabled: false
 
 config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
 
index 63443dde0115a1127df6133a645b329a01810be4..19d7cca5f220df34f8642cb30fe026b347d76c6f 100644 (file)
@@ -23,7 +23,7 @@ config :pleroma, Pleroma.Upload, filters: [], link_name: false
 
 config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
 
-config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test
+config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test, enabled: true
 
 config :pleroma, :instance,
   email: "admin@example.com",
index 931155fe9153978c4f9d99da9f54b2acce6ed5c3..01730ec168b54a4a200b859ec4612b72ff74601c 100644 (file)
@@ -41,6 +41,7 @@ This filter replaces the filename (not the path) of an upload. For complete obfu
 ## Pleroma.Emails.Mailer
 * `adapter`: one of the mail adapters listed in [Swoosh readme](https://github.com/swoosh/swoosh#adapters), or `Swoosh.Adapters.Local` for in-memory mailbox.
 * `api_key` / `password` and / or other adapter-specific settings, per the above documentation.
+* `enabled`: Allows enable/disable send  emails. Default: `false`.
 
 An example for Sendgrid adapter:
 
index 53f5a661c441eca67ec63c1feed66edf9a4c062e..2e4657b7c33b4a1ce9762f5a0e6facc80dfe9e53 100644 (file)
@@ -3,11 +3,58 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Emails.Mailer do
-  use Swoosh.Mailer, otp_app: :pleroma
+  @moduledoc """
+  Defines the Pleroma mailer.
 
+  The module contains functions to delivery email using Swoosh.Mailer.
+  """
+
+  alias Swoosh.DeliveryError
+
+  @otp_app :pleroma
+  @mailer_config [otp: :pleroma]
+
+  @spec enabled?() :: boolean()
+  def enabled?, do: Pleroma.Config.get([__MODULE__, :enabled])
+
+  @doc "add email to queue"
   def deliver_async(email, config \\ []) do
     PleromaJobQueue.enqueue(:mailer, __MODULE__, [:deliver_async, email, config])
   end
 
+  @doc "callback to perform send email from queue"
   def perform(:deliver_async, email, config), do: deliver(email, config)
+
+  @spec deliver(Swoosh.Email.t(), Keyword.t()) :: {:ok, term} | {:error, term}
+  def deliver(email, config \\ [])
+
+  def deliver(email, config) do
+    case enabled?() do
+      true -> Swoosh.Mailer.deliver(email, parse_config(config))
+      false -> {:error, :deliveries_disabled}
+    end
+  end
+
+  @spec deliver!(Swoosh.Email.t(), Keyword.t()) :: term | no_return
+  def deliver!(email, config \\ [])
+
+  def deliver!(email, config) do
+    case deliver(email, config) do
+      {:ok, result} -> result
+      {:error, reason} -> raise DeliveryError, reason: reason
+    end
+  end
+
+  @on_load :validate_dependency
+
+  @doc false
+  def validate_dependency do
+    parse_config([])
+    |> Keyword.get(:adapter)
+    |> Swoosh.Mailer.validate_dependency()
+  end
+
+  defp parse_config(config) do
+    Swoosh.Mailer.parse_config(@otp_app, __MODULE__, @mailer_config, config)
+  end
 end
diff --git a/mix.exs b/mix.exs
index 8f64562ef947700b1d2407efc5845aa10dd458c7..f96789d215870752c286ffa2aaa2d03669bf12c9 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -125,7 +125,7 @@ defmodule Pleroma.Mixfile do
       {:cors_plug, "~> 1.5"},
       {:ex_doc, "~> 0.20.2", only: :dev, runtime: false},
       {:web_push_encryption, "~> 0.2.1"},
-      {:swoosh, "~> 0.20"},
+      {:swoosh, "~> 0.23.2"},
       {:gen_smtp, "~> 0.13"},
       {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
       {:floki, "~> 0.20.0"},
index bd6ab910088812f3387ef1b38ef6723e3e89fa5c..2594ee632ad5855a52453e4cdef916f2623fa6cb 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -17,7 +17,7 @@
   "credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
   "crypt": {:git, "https://github.com/msantos/crypt", "1f2b58927ab57e72910191a7ebaeff984382a1d3", [ref: "1f2b58927ab57e72910191a7ebaeff984382a1d3"]},
   "db_connection": {:hex, :db_connection, "2.0.6", "bde2f85d047969c5b5800cb8f4b3ed6316c8cb11487afedac4aa5f93fd39abfa", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
-  "decimal": {:hex, :decimal, "1.7.0", "30d6b52c88541f9a66637359ddf85016df9eb266170d53105f02e4a67e00c5aa", [:mix], [], "hexpm"},
+  "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
   "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"},
   "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"},
   "ecto": {:hex, :ecto, "3.1.4", "69d852da7a9f04ede725855a35ede48d158ca11a404fe94f8b2fb3b2162cd3c9", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
@@ -33,7 +33,7 @@
   "ex_syslogger": {:git, "https://github.com/slashmili/ex_syslogger.git", "f3963399047af17e038897c69e20d552e6899e1d", [tag: "1.4.0"]},
   "excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
   "floki": {:hex, :floki, "0.20.4", "be42ac911fece24b4c72f3b5846774b6e61b83fe685c2fc9d62093277fb3bc86", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}, {:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
-  "gen_smtp": {:hex, :gen_smtp, "0.13.0", "11f08504c4bdd831dc520b8f84a1dce5ce624474a797394e7aafd3c29f5dcd25", [:rebar3], [], "hexpm"},
+  "gen_smtp": {:hex, :gen_smtp, "0.14.0", "39846a03522456077c6429b4badfd1d55e5e7d0fdfb65e935b7c5e38549d9202", [:rebar3], [], "hexpm"},
   "gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
   "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
   "html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"},
   "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
   "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
   "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
+  "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
   "postgrex": {:hex, :postgrex, "0.14.3", "5754dee2fdf6e9e508cbf49ab138df964278700b764177e8f3871e658b345a1e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
   "prometheus": {:hex, :prometheus, "4.2.2", "a830e77b79dc6d28183f4db050a7cac926a6c58f1872f9ef94a35cd989aceef8", [:mix, :rebar3], [], "hexpm"},
   "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.1", "6c768ea9654de871e5b32fab2eac348467b3021604ebebbcbd8bcbe806a65ed5", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
   "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
   "prometheus_phoenix": {:hex, :prometheus_phoenix, "1.2.1", "964a74dfbc055f781d3a75631e06ce3816a2913976d1df7830283aa3118a797a", [:mix], [{:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
   "prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
+  "prometheus_process_collector": {:hex, :prometheus_process_collector, "1.4.0", "6dbd39e3165b9ef1c94a7a820e9ffe08479f949dcdd431ed4aaea7b250eebfde", [:rebar3], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
   "quack": {:hex, :quack, "0.1.1", "cca7b4da1a233757fdb44b3334fce80c94785b3ad5a602053b7a002b5a8967bf", [:mix], [{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm"},
   "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
   "recon": {:git, "https://github.com/ferd/recon.git", "75d70c7c08926d2f24f1ee6de14ee50fe8a52763", [tag: "2.4.0"]},
   "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
-  "stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"},
-  "swoosh": {:hex, :swoosh, "0.20.0", "9a6c13822c9815993c03b6f8fccc370fcffb3c158d9754f67b1fdee6b3a5d928", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.12", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
+  "swoosh": {:hex, :swoosh, "0.23.2", "7dda95ff0bf54a2298328d6899c74dae1223777b43563ccebebb4b5d2b61df38", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
   "syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
   "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
   "tesla": {:hex, :tesla, "1.2.1", "864783cc27f71dd8c8969163704752476cec0f3a51eb3b06393b3971dc9733ff", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
diff --git a/test/emails/admin_email_test.exs b/test/emails/admin_email_test.exs
new file mode 100644 (file)
index 0000000..4bf54b0
--- /dev/null
@@ -0,0 +1,37 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Emails.AdminEmailTest do
+  use Pleroma.DataCase
+  import Pleroma.Factory
+
+  alias Pleroma.Emails.AdminEmail
+  alias Pleroma.Web.Router.Helpers
+
+  test "build report email" do
+    config = Pleroma.Config.get(:instance)
+    to_user = insert(:user)
+    reporter = insert(:user)
+    account = insert(:user)
+
+    res =
+      AdminEmail.report(to_user, reporter, account, [%{name: "Test", id: "12"}], "Test comment")
+
+    status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, "12")
+    reporter_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, reporter.nickname)
+    account_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, account.nickname)
+
+    assert res.to == [{to_user.name, to_user.email}]
+    assert res.from == {config[:name], config[:notify_email]}
+    assert res.reply_to == {reporter.name, reporter.email}
+    assert res.subject == "#{config[:name]} Report"
+
+    assert res.html_body ==
+             "<p>Reported by: <a href=\"#{reporter_url}\">#{reporter.nickname}</a></p>\n<p>Reported Account: <a href=\"#{
+               account_url
+             }\">#{account.nickname}</a></p>\n<p>Comment: Test comment\n<p> Statuses:\n  <ul>\n    <li><a href=\"#{
+               status_url
+             }\">#{status_url}</li>\n  </ul>\n</p>\n\n"
+  end
+end
diff --git a/test/emails/mailer_test.exs b/test/emails/mailer_test.exs
new file mode 100644 (file)
index 0000000..450bb09
--- /dev/null
@@ -0,0 +1,57 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Emails.MailerTest do
+  use Pleroma.DataCase
+  alias Pleroma.Emails.Mailer
+
+  import Swoosh.TestAssertions
+
+  @email %Swoosh.Email{
+    from: {"Pleroma", "noreply@example.com"},
+    html_body: "Test email",
+    subject: "Pleroma test email",
+    to: [{"Test User", "user1@example.com"}]
+  }
+
+  setup do
+    value = Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled])
+    on_exit(fn -> Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], value) end)
+    :ok
+  end
+
+  test "not send email when mailer is disabled" do
+    Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], false)
+    Mailer.deliver(@email)
+
+    refute_email_sent(
+      from: {"Pleroma", "noreply@example.com"},
+      to: [{"Test User", "user1@example.com"}],
+      html_body: "Test email",
+      subject: "Pleroma test email"
+    )
+  end
+
+  test "send email" do
+    Mailer.deliver(@email)
+
+    assert_email_sent(
+      from: {"Pleroma", "noreply@example.com"},
+      to: [{"Test User", "user1@example.com"}],
+      html_body: "Test email",
+      subject: "Pleroma test email"
+    )
+  end
+
+  test "perform" do
+    Mailer.perform(:deliver_async, @email, [])
+
+    assert_email_sent(
+      from: {"Pleroma", "noreply@example.com"},
+      to: [{"Test User", "user1@example.com"}],
+      html_body: "Test email",
+      subject: "Pleroma test email"
+    )
+  end
+end
diff --git a/test/emails/user_email_test.exs b/test/emails/user_email_test.exs
new file mode 100644 (file)
index 0000000..7d8df6a
--- /dev/null
@@ -0,0 +1,48 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Emails.UserEmailTest do
+  use Pleroma.DataCase
+
+  alias Pleroma.Emails.UserEmail
+  alias Pleroma.Web.Endpoint
+  alias Pleroma.Web.Router
+
+  import Pleroma.Factory
+
+  test "build password reset email" do
+    config = Pleroma.Config.get(:instance)
+    user = insert(:user)
+    email = UserEmail.password_reset_email(user, "test_token")
+    assert email.from == {config[:name], config[:notify_email]}
+    assert email.to == [{user.name, user.email}]
+    assert email.subject == "Password reset"
+    assert email.html_body =~ Router.Helpers.reset_password_url(Endpoint, :reset, "test_token")
+  end
+
+  test "build user invitation email" do
+    config = Pleroma.Config.get(:instance)
+    user = insert(:user)
+    token = %Pleroma.UserInviteToken{token: "test-token"}
+    email = UserEmail.user_invitation_email(user, token, "test@test.com", "Jonh")
+    assert email.from == {config[:name], config[:notify_email]}
+    assert email.subject == "Invitation to Pleroma"
+    assert email.to == [{"Jonh", "test@test.com"}]
+
+    assert email.html_body =~
+             Router.Helpers.redirect_url(Endpoint, :registration_page, token.token)
+  end
+
+  test "build account confirmation email" do
+    config = Pleroma.Config.get(:instance)
+    user = insert(:user, info: %Pleroma.User.Info{confirmation_token: "conf-token"})
+    email = UserEmail.account_confirmation_email(user)
+    assert email.from == {config[:name], config[:notify_email]}
+    assert email.to == [{user.name, user.email}]
+    assert email.subject == "#{config[:name]} account confirmation"
+
+    assert email.html_body =~
+             Router.Helpers.confirm_email_url(Endpoint, :confirm_email, user.id, "conf-token")
+  end
+end