config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail, enabled: false
+config :swoosh,
+ api_client: Swoosh.ApiClient.Finch,
+ finch_name: MyFinch
+
config :pleroma, Pleroma.Emails.UserEmail,
logo: nil,
styling: %{
* `user_agent`: what user agent should we use? (default: `:default`), must be string or `:default`
* `adapter`: array of adapter options
-### :hackney_pools
-
-Advanced. Tweaks Hackney (http client) connections pools.
-
-There's three pools used:
-
-* `:federation` for the federation jobs.
- You may want this pool max_connections to be at least equal to the number of federator jobs + retry queue jobs.
-* `:media` for rich media, media proxy
-* `:upload` for uploaded media (if using a remote uploader and `proxy_remote: true`)
-
-For each pool, the options are:
-
-* `max_connections` - how much connections a pool can hold
-* `timeout` - retention duration for connections
-
-
-### :connections_pool
-
-*For `gun` adapter*
-
-Settings for HTTP connection pool.
-
-* `:connection_acquisition_wait` - Timeout to acquire a connection from pool.The total max time is this value multiplied by the number of retries.
-* `connection_acquisition_retries` - Number of attempts to acquire the connection from the pool if it is overloaded. Each attempt is timed `:connection_acquisition_wait` apart.
-* `:max_connections` - Maximum number of connections in the pool.
-* `:connect_timeout` - Timeout to connect to the host.
-* `:reclaim_multiplier` - Multiplied by `:max_connections` this will be the maximum number of idle connections that will be reclaimed in case the pool is overloaded.
-
-### :pools
-
-*For `gun` adapter*
-
-Settings for request pools. These pools are limited on top of `:connections_pool`.
-
-There are four pools used:
-
-* `:federation` for the federation jobs. You may want this pool's max_connections to be at least equal to the number of federator jobs + retry queue jobs.
-* `:media` - for rich media, media proxy.
-* `:upload` - for proxying media when a remote uploader is used and `proxy_remote: true`.
-* `:default` - for other requests.
-
-For each pool, the options are:
-
-* `:size` - limit to how much requests can be concurrently executed.
-* `:recv_timeout` - timeout while `gun` will wait for response
-* `:max_waiting` - limit to how much requests can be waiting for others to finish, after this is reached, subsequent requests will be dropped.
-
## Captcha
### Pleroma.Captcha
def deliver(email, config \\ [])
def deliver(email, config) do
- # temporary hackney fix until hackney max_connections bug is fixed
- # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
- email =
- Swoosh.Email.put_private(email, :hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
-
case enabled?() do
true -> Swoosh.Mailer.deliver(email, parse_config(config))
false -> {:error, :deliveries_disabled}
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.API do
- @behaviour Pleroma.Gun
-
- alias Pleroma.Gun
-
- @gun_keys [
- :connect_timeout,
- :http_opts,
- :http2_opts,
- :protocols,
- :retry,
- :retry_timeout,
- :trace,
- :transport,
- :tls_opts,
- :tcp_opts,
- :socks_opts,
- :ws_opts,
- :supervise
- ]
-
- @impl Gun
- def open(host, port, opts \\ %{}), do: :gun.open(host, port, Map.take(opts, @gun_keys))
-
- @impl Gun
- defdelegate info(pid), to: :gun
-
- @impl Gun
- defdelegate close(pid), to: :gun
-
- @impl Gun
- defdelegate await_up(pid, timeout \\ 5_000), to: :gun
-
- @impl Gun
- defdelegate connect(pid, opts), to: :gun
-
- @impl Gun
- defdelegate await(pid, ref), to: :gun
-
- @impl Gun
- defdelegate set_owner(pid, owner), to: :gun
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.Conn do
- alias Pleroma.Gun
-
- require Logger
-
- def open(%URI{} = uri, opts) do
- pool_opts = Pleroma.Config.get([:connections_pool], [])
-
- opts =
- opts
- |> Enum.into(%{})
- |> Map.put_new(:connect_timeout, pool_opts[:connect_timeout] || 5_000)
- |> Map.put_new(:supervise, false)
- |> maybe_add_tls_opts(uri)
-
- do_open(uri, opts)
- end
-
- defp maybe_add_tls_opts(opts, %URI{scheme: "http"}), do: opts
-
- defp maybe_add_tls_opts(opts, %URI{scheme: "https"}) do
- tls_opts = [
- verify: :verify_peer,
- cacertfile: CAStore.file_path(),
- depth: 20,
- reuse_sessions: false,
- log_level: :warning,
- customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)]
- ]
-
- tls_opts =
- if Keyword.keyword?(opts[:tls_opts]) do
- Keyword.merge(tls_opts, opts[:tls_opts])
- else
- tls_opts
- end
-
- Map.put(opts, :tls_opts, tls_opts)
- end
-
- defp do_open(uri, %{proxy: {proxy_host, proxy_port}} = opts) do
- connect_opts =
- uri
- |> destination_opts()
- |> add_http2_opts(uri.scheme, Map.get(opts, :tls_opts, []))
-
- with open_opts <- Map.delete(opts, :tls_opts),
- {:ok, conn} <- Gun.open(proxy_host, proxy_port, open_opts),
- {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]),
- stream <- Gun.connect(conn, connect_opts),
- {:response, :fin, 200, _} <- Gun.await(conn, stream) do
- {:ok, conn, protocol}
- else
- error ->
- Logger.warn(
- "Opening proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
- )
-
- error
- end
- end
-
- defp do_open(uri, %{proxy: {proxy_type, proxy_host, proxy_port}} = opts) do
- version =
- proxy_type
- |> to_string()
- |> String.last()
- |> case do
- "4" -> 4
- _ -> 5
- end
-
- socks_opts =
- uri
- |> destination_opts()
- |> add_http2_opts(uri.scheme, Map.get(opts, :tls_opts, []))
- |> Map.put(:version, version)
-
- opts =
- opts
- |> Map.put(:protocols, [:socks])
- |> Map.put(:socks_opts, socks_opts)
-
- with {:ok, conn} <- Gun.open(proxy_host, proxy_port, opts),
- {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]) do
- {:ok, conn, protocol}
- else
- error ->
- Logger.warn(
- "Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
- )
-
- error
- end
- end
-
- defp do_open(%URI{host: host, port: port} = uri, opts) do
- host = Pleroma.HTTP.AdapterHelper.parse_host(host)
-
- with {:ok, conn} <- Gun.open(host, port, opts),
- {:ok, protocol} <- Gun.await_up(conn, opts[:connect_timeout]) do
- {:ok, conn, protocol}
- else
- error ->
- Logger.warn(
- "Opening connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
- )
-
- error
- end
- end
-
- defp destination_opts(%URI{host: host, port: port}) do
- host = Pleroma.HTTP.AdapterHelper.parse_host(host)
- %{host: host, port: port}
- end
-
- defp add_http2_opts(opts, "https", tls_opts) do
- Map.merge(opts, %{protocols: [:http2], transport: :tls, tls_opts: tls_opts})
- end
-
- defp add_http2_opts(opts, _, _), do: opts
-
- def compose_uri_log(%URI{scheme: scheme, host: host, path: path}) do
- "#{scheme}://#{host}#{path}"
- end
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.ConnectionPool do
- @registry __MODULE__
-
- alias Pleroma.Gun.ConnectionPool.WorkerSupervisor
-
- def children do
- [
- {Registry, keys: :unique, name: @registry},
- Pleroma.Gun.ConnectionPool.WorkerSupervisor
- ]
- end
-
- @spec get_conn(URI.t(), keyword()) :: {:ok, pid()} | {:error, term()}
- def get_conn(uri, opts) do
- key = "#{uri.scheme}:#{uri.host}:#{uri.port}"
-
- case Registry.lookup(@registry, key) do
- # The key has already been registered, but connection is not up yet
- [{worker_pid, nil}] ->
- get_gun_pid_from_worker(worker_pid, true)
-
- [{worker_pid, {gun_pid, _used_by, _crf, _last_reference}}] ->
- GenServer.call(worker_pid, :add_client)
- {:ok, gun_pid}
-
- [] ->
- # :gun.set_owner fails in :connected state for whatevever reason,
- # so we open the connection in the process directly and send it's pid back
- # We trust gun to handle timeouts by itself
- case WorkerSupervisor.start_worker([key, uri, opts, self()]) do
- {:ok, worker_pid} ->
- get_gun_pid_from_worker(worker_pid, false)
-
- {:error, {:already_started, worker_pid}} ->
- get_gun_pid_from_worker(worker_pid, true)
-
- err ->
- err
- end
- end
- end
-
- defp get_gun_pid_from_worker(worker_pid, register) do
- # GenServer.call will block the process for timeout length if
- # the server crashes on startup (which will happen if gun fails to connect)
- # so instead we use cast + monitor
-
- ref = Process.monitor(worker_pid)
- if register, do: GenServer.cast(worker_pid, {:add_client, self()})
-
- receive do
- {:conn_pid, pid} ->
- Process.demonitor(ref)
- {:ok, pid}
-
- {:DOWN, ^ref, :process, ^worker_pid, reason} ->
- case reason do
- {:shutdown, {:error, _} = error} -> error
- {:shutdown, error} -> {:error, error}
- _ -> {:error, reason}
- end
- end
- end
-
- @spec release_conn(pid()) :: :ok
- def release_conn(conn_pid) do
- # :ets.fun2ms(fn {_, {worker_pid, {gun_pid, _, _, _}}} when gun_pid == conn_pid ->
- # worker_pid end)
- query_result =
- Registry.select(@registry, [
- {{:_, :"$1", {:"$2", :_, :_, :_}}, [{:==, :"$2", conn_pid}], [:"$1"]}
- ])
-
- case query_result do
- [worker_pid] ->
- GenServer.call(worker_pid, :remove_client)
-
- [] ->
- :ok
- end
- end
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
- use GenServer, restart: :temporary
-
- defp registry, do: Pleroma.Gun.ConnectionPool
-
- def start_monitor do
- pid =
- case :gen_server.start(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do
- {:ok, pid} ->
- pid
-
- {:error, {:already_registered, pid}} ->
- pid
- end
-
- {pid, Process.monitor(pid)}
- end
-
- @impl true
- def init(_) do
- {:ok, nil, {:continue, :reclaim}}
- end
-
- @impl true
- def handle_continue(:reclaim, _) do
- max_connections = Pleroma.Config.get([:connections_pool, :max_connections])
-
- reclaim_max =
- [:connections_pool, :reclaim_multiplier]
- |> Pleroma.Config.get()
- |> Kernel.*(max_connections)
- |> round
- |> max(1)
-
- :telemetry.execute([:pleroma, :connection_pool, :reclaim, :start], %{}, %{
- max_connections: max_connections,
- reclaim_max: reclaim_max
- })
-
- # :ets.fun2ms(
- # fn {_, {worker_pid, {_, used_by, crf, last_reference}}} when used_by == [] ->
- # {worker_pid, crf, last_reference} end)
- unused_conns =
- Registry.select(
- registry(),
- [
- {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]}
- ]
- )
-
- case unused_conns do
- [] ->
- :telemetry.execute(
- [:pleroma, :connection_pool, :reclaim, :stop],
- %{reclaimed_count: 0},
- %{
- max_connections: max_connections
- }
- )
-
- {:stop, :no_unused_conns, nil}
-
- unused_conns ->
- reclaimed =
- unused_conns
- |> Enum.sort(fn {_pid1, crf1, last_reference1}, {_pid2, crf2, last_reference2} ->
- crf1 <= crf2 and last_reference1 <= last_reference2
- end)
- |> Enum.take(reclaim_max)
-
- reclaimed
- |> Enum.each(fn {pid, _, _} ->
- DynamicSupervisor.terminate_child(Pleroma.Gun.ConnectionPool.WorkerSupervisor, pid)
- end)
-
- :telemetry.execute(
- [:pleroma, :connection_pool, :reclaim, :stop],
- %{reclaimed_count: Enum.count(reclaimed)},
- %{max_connections: max_connections}
- )
-
- {:stop, :normal, nil}
- end
- end
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.ConnectionPool.Worker do
- alias Pleroma.Gun
- use GenServer, restart: :temporary
-
- defp registry, do: Pleroma.Gun.ConnectionPool
-
- def start_link([key | _] = opts) do
- GenServer.start_link(__MODULE__, opts, name: {:via, Registry, {registry(), key}})
- end
-
- @impl true
- def init([_key, _uri, _opts, _client_pid] = opts) do
- {:ok, nil, {:continue, {:connect, opts}}}
- end
-
- @impl true
- def handle_continue({:connect, [key, uri, opts, client_pid]}, _) do
- with {:ok, conn_pid, protocol} <- Gun.Conn.open(uri, opts),
- Process.link(conn_pid) do
- time = :erlang.monotonic_time(:millisecond)
-
- {_, _} =
- Registry.update_value(registry(), key, fn _ ->
- {conn_pid, [client_pid], 1, time}
- end)
-
- send(client_pid, {:conn_pid, conn_pid})
-
- {:noreply,
- %{
- key: key,
- timer: nil,
- client_monitors: %{client_pid => Process.monitor(client_pid)},
- protocol: protocol
- }, :hibernate}
- else
- err ->
- {:stop, {:shutdown, err}, nil}
- end
- end
-
- @impl true
- def handle_cast({:add_client, client_pid}, state) do
- case handle_call(:add_client, {client_pid, nil}, state) do
- {:reply, conn_pid, state, :hibernate} ->
- send(client_pid, {:conn_pid, conn_pid})
- {:noreply, state, :hibernate}
- end
- end
-
- @impl true
- def handle_cast({:remove_client, client_pid}, state) do
- case handle_call(:remove_client, {client_pid, nil}, state) do
- {:reply, _, state, :hibernate} ->
- {:noreply, state, :hibernate}
- end
- end
-
- @impl true
- def handle_call(:add_client, {client_pid, _}, %{key: key, protocol: protocol} = state) do
- time = :erlang.monotonic_time(:millisecond)
-
- {{conn_pid, used_by, _, _}, _} =
- Registry.update_value(registry(), key, fn {conn_pid, used_by, crf, last_reference} ->
- {conn_pid, [client_pid | used_by], crf(time - last_reference, crf), time}
- end)
-
- :telemetry.execute(
- [:pleroma, :connection_pool, :client, :add],
- %{client_pid: client_pid, clients: used_by},
- %{key: state.key, protocol: protocol}
- )
-
- state =
- if state.timer != nil do
- Process.cancel_timer(state[:timer])
- %{state | timer: nil}
- else
- state
- end
-
- ref = Process.monitor(client_pid)
-
- state = put_in(state.client_monitors[client_pid], ref)
- {:reply, conn_pid, state, :hibernate}
- end
-
- @impl true
- def handle_call(:remove_client, {client_pid, _}, %{key: key} = state) do
- {{_conn_pid, used_by, _crf, _last_reference}, _} =
- Registry.update_value(registry(), key, fn {conn_pid, used_by, crf, last_reference} ->
- {conn_pid, List.delete(used_by, client_pid), crf, last_reference}
- end)
-
- {ref, state} = pop_in(state.client_monitors[client_pid])
-
- Process.demonitor(ref, [:flush])
-
- timer =
- if used_by == [] do
- max_idle = Pleroma.Config.get([:connections_pool, :max_idle_time], 30_000)
- Process.send_after(self(), :idle_close, max_idle)
- else
- nil
- end
-
- {:reply, :ok, %{state | timer: timer}, :hibernate}
- end
-
- @impl true
- def handle_info(:idle_close, state) do
- # Gun monitors the owner process, and will close the connection automatically
- # when it's terminated
- {:stop, :normal, state}
- end
-
- @impl true
- def handle_info({:gun_up, _pid, _protocol}, state) do
- {:noreply, state, :hibernate}
- end
-
- # Gracefully shutdown if the connection got closed without any streams left
- @impl true
- def handle_info({:gun_down, _pid, _protocol, _reason, []}, state) do
- {:stop, :normal, state}
- end
-
- # Otherwise, wait for retry
- @impl true
- def handle_info({:gun_down, _pid, _protocol, _reason, _killed_streams}, state) do
- {:noreply, state, :hibernate}
- end
-
- @impl true
- def handle_info({:DOWN, _ref, :process, pid, reason}, state) do
- :telemetry.execute(
- [:pleroma, :connection_pool, :client, :dead],
- %{client_pid: pid, reason: reason},
- %{key: state.key}
- )
-
- handle_cast({:remove_client, pid}, state)
- end
-
- # LRFU policy: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.55.1478
- defp crf(time_delta, prev_crf) do
- 1 + :math.pow(0.5, 0.0001 * time_delta) * prev_crf
- end
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Gun.ConnectionPool.WorkerSupervisor do
- @moduledoc "Supervisor for pool workers. Does not do anything except enforce max connection limit"
-
- use DynamicSupervisor
-
- def start_link(opts) do
- DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)
- end
-
- def init(_opts) do
- DynamicSupervisor.init(
- strategy: :one_for_one,
- max_children: Pleroma.Config.get([:connections_pool, :max_connections])
- )
- end
-
- def start_worker(opts, retry \\ false) do
- case DynamicSupervisor.start_child(__MODULE__, {Pleroma.Gun.ConnectionPool.Worker, opts}) do
- {:error, :max_children} ->
- if retry or free_pool() == :error do
- :telemetry.execute([:pleroma, :connection_pool, :provision_failure], %{opts: opts})
- {:error, :pool_full}
- else
- start_worker(opts, true)
- end
-
- res ->
- res
- end
- end
-
- defp free_pool do
- wait_for_reclaimer_finish(Pleroma.Gun.ConnectionPool.Reclaimer.start_monitor())
- end
-
- defp wait_for_reclaimer_finish({pid, mon}) do
- receive do
- {:DOWN, ^mon, :process, ^pid, :no_unused_conns} ->
- :error
-
- {:DOWN, ^mon, :process, ^pid, :normal} ->
- :ok
- end
- end
-end
+++ /dev/null
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.ReverseProxy.Client.Hackney do
- @behaviour Pleroma.ReverseProxy.Client
-
- @impl true
- def request(method, url, headers, body, opts \\ []) do
- opts = Keyword.put(opts, :ssl_options, versions: [:"tlsv1.2", :"tlsv1.1", :tlsv1])
- :hackney.request(method, url, headers, body, opts)
- end
-
- @impl true
- def stream_body(ref) do
- case :hackney.stream_body(ref) do
- :done -> :done
- {:ok, data} -> {:ok, data, ref}
- {:error, error} -> {:error, error}
- end
- end
-
- @impl true
- def close(ref), do: :hackney.close(ref)
-end
{:tesla, "~> 1.4.4", override: true},
{:castore, "~> 0.1"},
{:cowlib, "~> 2.9", override: true},
- {:gun, "~> 2.0.0-rc.1", override: true},
- {:finch, "~> 0.13.0"},
+ {:finch, "~> 0.14.0"},
{:jason, "~> 1.2"},
{:mogrify, "~> 0.9.1"},
{:ex_aws, "~> 2.1.6"},
"cachex": {:hex, :cachex, "3.4.0", "868b2959ea4aeb328c6b60ff66c8d5123c083466ad3c33d3d8b5f142e13101fb", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "370123b1ab4fba4d2965fb18f87fd758325709787c8c5fce35b3fe80645ccbe5"},
"calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.1.201603 or ~> 0.5.20 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"},
"captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e0f16822d578866e186a0974d65ad58cddc1e2ab", [ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"]},
- "castore": {:hex, :castore, "0.1.19", "a2c3e46d62b7f3aa2e6f88541c21d7400381e53704394462b9fd4f06f6d42bb6", [:mix], [], "hexpm", "e96e0161a5dc82ef441da24d5fa74aefc40d920f3a6645d15e1f9f3e66bb2109"},
+ "castore": {:hex, :castore, "0.1.20", "62a0126cbb7cb3e259257827b9190f88316eb7aa3fdac01fd6f2dfd64e7f46e9", [:mix], [], "hexpm", "a020b7650529c986c454a4035b6b13a328e288466986307bea3aadb4c95ac98a"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
"fast_html": {:hex, :fast_html, "2.0.5", "c61760340606c1077ff1f196f17834056cb1dd3d5cb92a9f2cabf28bc6221c3c", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "605f4f4829443c14127694ebabb681778712ceecb4470ec32aa31012330e6506"},
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
- "finch": {:hex, :finch, "0.13.0", "c881e5460ec563bf02d4f4584079e62201db676ed4c0ef3e59189331c4eddf7b", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "49957dcde10dcdc042a123a507a9c5ec5a803f53646d451db2f7dea696fba6cc"},
+ "finch": {:hex, :finch, "0.14.0", "619bfdee18fc135190bf590356c4bf5d5f71f916adb12aec94caa3fa9267a4bc", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5459acaf18c4fdb47a8c22fb3baff5d8173106217c8e56c5ba0b93e66501a8dd"},
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
"floki": {:hex, :floki, "0.34.0", "002d0cc194b48794d74711731db004fafeb328fe676976f160685262d43706a8", [:mix], [], "hexpm", "9c3a9f43f40dde00332a589bd9d389b90c1f518aef500364d00636acc5ebc99c"},
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
"gettext": {:git, "https://github.com/tusooa/gettext.git", "72fb2496b6c5280ed911bdc3756890e7f38a4808", [ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808"]},
- "gun": {:hex, :gun, "2.0.0-rc.2", "7c489a32dedccb77b6e82d1f3c5a7dadfbfa004ec14e322cdb5e579c438632d2", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "6b9d1eae146410d727140dbf8b404b9631302ecc2066d1d12f22097ad7d254fc"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~> 2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"mock": {:hex, :mock, "0.3.7", "75b3bbf1466d7e486ea2052a73c6e062c6256fb429d6797999ab02fa32f29e03", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "4da49a4609e41fd99b7836945c26f373623ea968cfb6282742bcb94440cf7e5c"},
"mogrify": {:hex, :mogrify, "0.9.2", "b360984adea7dd6a55f18028e6327973c58de7f548fdb86c9859848aa904d5b0", [:mix], [], "hexpm", "c18d10fd70ca20e2585301616c89f6e4f7159d92efc9cc8ee579e00c886f699d"},
"mox": {:hex, :mox, "1.0.2", "dc2057289ac478b35760ba74165b4b3f402f68803dd5aecd3bfd19c183815d64", [:mix], [], "hexpm", "f9864921b3aaf763c8741b5b8e6f908f44566f1e427b2630e89e9a73b981fef2"},
- "nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"},
+ "nimble_options": {:hex, :nimble_options, "0.5.1", "5c166f7669e40333191bea38e3bd3811cc13f459f1e4be49e89128a21b5d8c4d", [:mix], [], "hexpm", "d176cf7baa4fef0ceb301ca3eb8b55bd7de3e45f489c4f8b4f2849f1f114ef3e"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"},
"oban": {:hex, :oban, "2.12.1", "f604d7e6a8be9fda4a9b0f6cebbd633deba569f85dbff70c4d25d99a6f023177", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b1844c2b74e0d788b73e5144b0c9d5674cb775eae29d88a36f3c3b48d42d058"},
ObanHelpers.perform_all()
Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
- # temporary hackney fix until hackney max_connections bug is fixed
- # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
- |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
|> assert_email_sent()
end
ObanHelpers.perform_all()
Pleroma.Emails.UserEmail.account_confirmation_email(first_user)
- # temporary hackney fix until hackney max_connections bug is fixed
- # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
- |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
|> assert_email_sent()
end
end