58 lines
2 KiB
Elixir
58 lines
2 KiB
Elixir
defmodule Mv.Smtp.ConfigBuilder do
|
|
@moduledoc """
|
|
Builds Swoosh/gen_smtp SMTP adapter options from connection parameters.
|
|
|
|
Single source of truth for TLS/sockopts logic (port 587 vs 465):
|
|
- Port 587 (STARTTLS): `gen_tcp` is used first; `sockopts` must NOT contain `:verify`.
|
|
- Port 465 (implicit SSL): initial connection is `ssl:connect`; `sockopts` must contain `:verify`.
|
|
|
|
Used by `config/runtime.exs` (boot-time ENV) and `Mv.Mailer.smtp_config/0` (Settings-only).
|
|
"""
|
|
|
|
@doc """
|
|
Builds the keyword list of Swoosh SMTP adapter options.
|
|
|
|
Options (keyword list):
|
|
- `:host` (required) — relay hostname
|
|
- `:port` (required) — port number (e.g. 587 or 465)
|
|
- `:ssl_mode` (required) — `"tls"` or `"ssl"`
|
|
- `:verify_mode` (required) — `:verify_peer` or `:verify_none`
|
|
- `:username` (optional)
|
|
- `:password` (optional)
|
|
|
|
Nil values are stripped from the result.
|
|
"""
|
|
@spec build_opts(keyword()) :: keyword()
|
|
def build_opts(opts) do
|
|
host = Keyword.fetch!(opts, :host)
|
|
port = Keyword.fetch!(opts, :port)
|
|
username = Keyword.get(opts, :username)
|
|
password = Keyword.get(opts, :password)
|
|
ssl_mode = Keyword.fetch!(opts, :ssl_mode)
|
|
verify_mode = Keyword.fetch!(opts, :verify_mode)
|
|
|
|
base_opts = [
|
|
adapter: Swoosh.Adapters.SMTP,
|
|
relay: host,
|
|
port: port,
|
|
username: username,
|
|
password: password,
|
|
ssl: ssl_mode == "ssl",
|
|
tls: if(ssl_mode == "tls", do: :always, else: :never),
|
|
auth: :always,
|
|
# tls_options: used for STARTTLS (587). For 465, gen_smtp uses sockopts for initial ssl:connect.
|
|
tls_options: [verify: verify_mode]
|
|
]
|
|
|
|
# Port 465: initial connection is ssl:connect; pass verify in sockopts.
|
|
# Port 587: initial connection is gen_tcp; sockopts must NOT contain verify (gen_tcp rejects it).
|
|
opts =
|
|
if ssl_mode == "ssl" do
|
|
Keyword.put(base_opts, :sockopts, verify: verify_mode)
|
|
else
|
|
base_opts
|
|
end
|
|
|
|
Enum.reject(opts, fn {_k, v} -> is_nil(v) end)
|
|
end
|
|
end
|