Repository: swoosh/swoosh
Pull request #783 (2023-06-27 02:36:12)

SendInBlue -> Brevo
@garlandcrow


Patch:
diff --git a/README.md b/README.md
index 4608cac..6c39141 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ configuration options.
   See `Swoosh.ApiClient.Finch` for details.
 
   If you need to integrate with another HTTP client, it's easy to define a new
-  API client.  Follow the `Swoosh.ApiClient` behaviour and configure Swoosh to
+  API client. Follow the `Swoosh.ApiClient` behaviour and configure Swoosh to
   use it:
 
   ```elixir
@@ -127,25 +127,25 @@ Swoosh supports the most popular transactional email providers out of the box
 and also has an SMTP adapter. Below is the list of the adapters currently
 included:
 
-| Provider     | Swoosh adapter                                                                                      |
-|--------------|-----------------------------------------------------------------------------------------------------|
-| SMTP         | [Swoosh.Adapters.SMTP](https://hexdocs.pm/swoosh/Swoosh.Adapters.SMTP.html#content)                 |
-| SendGrid     | [Swoosh.Adapters.Sendgrid](https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendgrid.html#content)         |
-| Sendinblue   | [Swoosh.Adapters.Sendinblue](https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendinblue.html#content)     |
-| Sendmail     | [Swoosh.Adapters.Sendmail](https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendmail.html#content)         |
-| Mandrill     | [Swoosh.Adapters.Mandrill](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mandrill.html#content)         |
-| Mailgun      | [Swoosh.Adapters.Mailgun](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mailgun.html#content)           |
-| Mailjet      | [Swoosh.Adapters.Mailjet](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mailjet.html#content)           |
-| Postmark     | [Swoosh.Adapters.Postmark](https://hexdocs.pm/swoosh/Swoosh.Adapters.Postmark.html#content)         |
-| SparkPost    | [Swoosh.Adapters.SparkPost](https://hexdocs.pm/swoosh/Swoosh.Adapters.SparkPost.html#content)       |
-| Amazon SES   | [Swoosh.Adapters.AmazonSES](https://hexdocs.pm/swoosh/Swoosh.Adapters.AmazonSES.html#content)       |
-| Amazon SES   | [Swoosh.Adapters.ExAwsAmazonSES](https://hexdocs.pm/swoosh/Swoosh.Adapters.ExAwsAmazonSES.html)     |
-| Dyn          | [Swoosh.Adapters.Dyn](https://hexdocs.pm/swoosh/Swoosh.Adapters.Dyn.html#content)                   |
-| SocketLabs   | [Swoosh.Adapters.SocketLabs](https://hexdocs.pm/swoosh/Swoosh.Adapters.SocketLabs.html#content)     |
-| Gmail        | [Swoosh.Adapters.Gmail](https://hexdocs.pm/swoosh/Swoosh.Adapters.Gmail.html#content)               |
-| MailPace     | [Swoosh.Adapters.MailPace](https://hexdocs.pm/swoosh/Swoosh.Adapters.MailPace.html#content)         |
-| SMTP2GO      | [Swoosh.Adapters.SMTP2GO](https://hexdocs.pm/swoosh/Swoosh.Adapters.SMTP2GO.html#content)           |
-| ProtonBridge | [Swoosh.Adapters.ProtonBridge](https://hexdocs.pm/swoosh/Swoosh.Adapters.ProtonBridge.html#content) |
+|   Provider   |                                            Swoosh adapter                                           |  Remarks   |
+|--------------|-----------------------------------------------------------------------------------------------------|------------|
+| SMTP         | [Swoosh.Adapters.SMTP](https://hexdocs.pm/swoosh/Swoosh.Adapters.SMTP.html#content)                 |            |
+| SendGrid     | [Swoosh.Adapters.Sendgrid](https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendgrid.html#content)         |            |
+| Brevo        | [Swoosh.Adapters.Brevo](https://hexdocs.pm/swoosh/Swoosh.Adapters.Brevo.html#content)               | Sendinblue |
+| Sendmail     | [Swoosh.Adapters.Sendmail](https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendmail.html#content)         |            |
+| Mandrill     | [Swoosh.Adapters.Mandrill](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mandrill.html#content)         |            |
+| Mailgun      | [Swoosh.Adapters.Mailgun](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mailgun.html#content)           |            |
+| Mailjet      | [Swoosh.Adapters.Mailjet](https://hexdocs.pm/swoosh/Swoosh.Adapters.Mailjet.html#content)           |            |
+| Postmark     | [Swoosh.Adapters.Postmark](https://hexdocs.pm/swoosh/Swoosh.Adapters.Postmark.html#content)         |            |
+| SparkPost    | [Swoosh.Adapters.SparkPost](https://hexdocs.pm/swoosh/Swoosh.Adapters.SparkPost.html#content)       |            |
+| Amazon SES   | [Swoosh.Adapters.AmazonSES](https://hexdocs.pm/swoosh/Swoosh.Adapters.AmazonSES.html#content)       |            |
+| Amazon SES   | [Swoosh.Adapters.ExAwsAmazonSES](https://hexdocs.pm/swoosh/Swoosh.Adapters.ExAwsAmazonSES.html)     |            |
+| Dyn          | [Swoosh.Adapters.Dyn](https://hexdocs.pm/swoosh/Swoosh.Adapters.Dyn.html#content)                   |            |
+| SocketLabs   | [Swoosh.Adapters.SocketLabs](https://hexdocs.pm/swoosh/Swoosh.Adapters.SocketLabs.html#content)     |            |
+| Gmail        | [Swoosh.Adapters.Gmail](https://hexdocs.pm/swoosh/Swoosh.Adapters.Gmail.html#content)               |            |
+| MailPace     | [Swoosh.Adapters.MailPace](https://hexdocs.pm/swoosh/Swoosh.Adapters.MailPace.html#content)         | OhMySMTP   |
+| SMTP2GO      | [Swoosh.Adapters.SMTP2GO](https://hexdocs.pm/swoosh/Swoosh.Adapters.SMTP2GO.html#content)           |            |
+| ProtonBridge | [Swoosh.Adapters.ProtonBridge](https://hexdocs.pm/swoosh/Swoosh.Adapters.ProtonBridge.html#content) |            |
 
 Configure which adapter you want to use by updating your `config/config.exs`
 file:
diff --git a/lib/swoosh/adapters/brevo.ex b/lib/swoosh/adapters/brevo.ex
new file mode 100644
index 0000000..87ebb00
--- /dev/null
+++ b/lib/swoosh/adapters/brevo.ex
@@ -0,0 +1,216 @@
+defmodule Swoosh.Adapters.Brevo do
+  @moduledoc ~S"""
+  An adapter that sends email using the Brevo API (Transactional emails only).
+
+  For reference: [Brevo API docs](https://developers.brevo.com/reference/sendtransacemail)
+
+  **This adapter requires an API Client.** Swoosh comes with Hackney and Finch out of the box.
+  See the [installation section](https://hexdocs.pm/swoosh/Swoosh.html#module-installation)
+  for details.
+
+  ## Example
+
+      # config/config.exs
+      config :sample, Sample.Mailer,
+        adapter: Swoosh.Adapters.Brevo,
+        api_key: "my-api-key"
+
+      # lib/sample/mailer.ex
+      defmodule Sample.Mailer do
+        use Swoosh.Mailer, otp_app: :sample
+      end
+
+  ## Using with provider options
+
+      import Swoosh.Email
+
+      new()
+      |> from("nora@example.com")
+      |> to("shushu@example.com")
+      |> subject("Hello, Wally!")
+      |> text_body("Hello")
+      |> put_provider_option(:id, 42)
+      |> put_provider_option(:template_id, 42)
+      |> put_provider_option(:params, %{param1: "a", param2: 123})
+      |> put_provider_option(:tags, ["tag_1", "tag_2"])
+      |> put_provider_option(:schedule_at, ~U[2022-11-15 11:00:00Z])
+
+  ## Provider Options
+
+    * `sender_id` (integer) - `sender`, the sender `id` where this library will
+      add email obtained from the `from/1`
+
+    * `template_id` (integer) - `templateId`, the Id of the `active`
+      transactional email template
+
+    * `params` (map) - `params`, a map of key/value attributes to customize the
+      template
+
+    * `tags` (list[string]) - `tags`, a list of tags for each email for easy
+      filtering
+
+    * `schedule_at` (UTC DateTime) - `schedule_at`, a UTC date-time on which the email has to schedule
+
+  """
+
+  use Swoosh.Adapter, required_config: [:api_key]
+
+  alias Swoosh.Email
+
+  @base_url "https://api.brevo.com/v3"
+  @api_endpoint "/smtp/email"
+
+  defp base_url(config), do: config[:base_url] || @base_url
+
+  @impl true
+  def deliver(%Email{} = email, config \\ []) do
+    headers = [
+      {"Accept", "application/json"},
+      {"Content-Type", "application/json"},
+      {"User-Agent", "swoosh/#{Swoosh.version()}"},
+      {"Api-Key", config[:api_key]}
+    ]
+
+    body = email |> prepare_payload() |> Swoosh.json_library().encode!
+    url = [base_url(config), @api_endpoint]
+
+    case Swoosh.ApiClient.post(url, headers, body, email) do
+      {:ok, code, _headers, body} when code >= 200 and code <= 399 ->
+        {:ok, %{id: extract_message_id(body)}}
+
+      {:ok, code, _headers, body} when code >= 400 ->
+        case Swoosh.json_library().decode(body) do
+          {:ok, error} -> {:error, {code, error}}
+          {:error, _} -> {:error, {code, body}}
+        end
+
+      {:error, reason} ->
+        {:error, reason}
+    end
+  end
+
+  defp extract_message_id(body) do
+    body
+    |> Swoosh.json_library().decode!()
+    |> Map.get("messageId")
+  end
+
+  defp prepare_payload(email) do
+    %{}
+    |> prepare_from(email)
+    |> prepare_reply_to(email)
+    |> prepare_to(email)
+    |> prepare_cc(email)
+    |> prepare_bcc(email)
+    |> prepare_subject(email)
+    |> prepare_text_content(email)
+    |> prepare_html_content(email)
+    |> prepare_template_id(email)
+    |> prepare_headers(email)
+    |> prepare_params(email)
+    |> prepare_tags(email)
+    |> prepare_attachments(email)
+    |> prepare_schedule_at(email)
+  end
+
+  defp prepare_from(payload, %{from: {_name, email}, provider_options: %{sender_id: sender_id}}),
+    do: Map.put(payload, "sender", %{id: sender_id, email: email})
+
+  defp prepare_from(payload, %{from: {_, "TEMPLATE"}}), do: payload
+
+  defp prepare_from(payload, %{from: from}),
+    do: Map.put(payload, "sender", prepare_recipient(from))
+
+  defp prepare_reply_to(payload, %{reply_to: nil}),
+    do: payload
+
+  defp prepare_reply_to(payload, %{reply_to: reply_to}),
+    do: Map.put(payload, "replyTo", prepare_recipient(reply_to))
+
+  defp prepare_to(payload, %{to: to}) do
+    Map.put(payload, "to", Enum.map(to, &prepare_recipient/1))
+  end
+
+  defp prepare_cc(payload, %{cc: []}), do: payload
+
+  defp prepare_cc(payload, %{cc: cc}) do
+    Map.put(payload, "cc", Enum.map(cc, &prepare_recipient/1))
+  end
+
+  defp prepare_bcc(payload, %{bcc: []}), do: payload
+
+  defp prepare_bcc(payload, %{bcc: bcc}) do
+    Map.put(payload, "bcc", Enum.map(bcc, &prepare_recipient/1))
+  end
+
+  defp prepare_subject(payload, %{subject: ""}), do: payload
+
+  defp prepare_subject(payload, %{subject: subject}),
+    do: Map.put(payload, "subject", subject)
+
+  defp prepare_subject(payload, _), do: payload
+
+  defp prepare_text_content(payload, %{text_body: nil}), do: payload
+
+  defp prepare_text_content(payload, %{text_body: text_content}) do
+    Map.put(payload, "textContent", text_content)
+  end
+
+  defp prepare_html_content(payload, %{html_body: nil}), do: payload
+
+  defp prepare_html_content(payload, %{html_body: html_content}) do
+    Map.put(payload, "htmlContent", html_content)
+  end
+
+  defp prepare_template_id(payload, %{provider_options: %{template_id: template_id}}) do
+    Map.put(payload, "templateId", template_id)
+  end
+
+  defp prepare_template_id(payload, _), do: payload
+
+  defp prepare_headers(payload, %{headers: map}) when map_size(map) == 0, do: payload
+
+  defp prepare_headers(payload, %{headers: headers}) do
+    Map.put(payload, "headers", headers)
+  end
+
+  defp prepare_params(payload, %{provider_options: %{params: params}}) when is_map(params) do
+    Map.put(payload, "params", params)
+  end
+
+  defp prepare_params(payload, _), do: payload
+
+  defp prepare_tags(payload, %{provider_options: %{tags: tags}}) when is_list(tags) do
+    Map.put(payload, "tags", tags)
+  end
+
+  defp prepare_tags(payload, _), do: payload
+
+  defp prepare_attachments(payload, %{attachments: []}), do: payload
+
+  defp prepare_attachments(payload, %{attachments: attachments}) do
+    Map.put(
+      payload,
+      "attachment",
+      Enum.map(
+        attachments,
+        &%{
+          name: &1.filename,
+          content: Swoosh.Attachment.get_content(&1, :base64)
+        }
+      )
+    )
+  end
+
+  defp prepare_schedule_at(payload, %{provider_options: %{schedule_at: schedule_at}}) do
+    Map.put(payload, "scheduledAt", schedule_at)
+  end
+
+  defp prepare_schedule_at(payload, _), do: payload
+
+  defp prepare_recipient({name, email}) when name in [nil, ""],
+    do: %{email: email}
+
+  defp prepare_recipient({name, email}),
+    do: %{name: name, email: email}
+end
diff --git a/lib/swoosh/adapters/mail_pace.ex b/lib/swoosh/adapters/mail_pace.ex
index 5e030da..19a79fb 100644
--- a/lib/swoosh/adapters/mail_pace.ex
+++ b/lib/swoosh/adapters/mail_pace.ex
@@ -28,6 +28,7 @@ defmodule Swoosh.Adapters.MailPace do
   import Swoosh.Email.Render
 
   @endpoint "https://app.mailpace.com/api/v1/send"
+  @server_token_key "MailPace-Server-Token"
 
   @impl true
   def deliver(%Email{} = email, config \\ []) do
@@ -52,7 +53,7 @@ defmodule Swoosh.Adapters.MailPace do
   defp prepare_headers(config) do
     [
       {"User-Agent", "swoosh/#{Swoosh.version()}"},
-      {"MailPace-Server-Token", config[:api_key]},
+      {server_token_key(config), config[:api_key]},
       {"Content-Type", "application/json"},
       {"Accept", "application/json"}
     ]
@@ -117,4 +118,6 @@ defmodule Swoosh.Adapters.MailPace do
   end
 
   defp endpoint(config), do: config[:endpoint] || @endpoint
+
+  defp server_token_key(config), do: config[:server_token_key] || @server_token_key
 end
diff --git a/lib/swoosh/adapters/oh_my_smtp.ex b/lib/swoosh/adapters/oh_my_smtp.ex
index 1ad4cac..11effb7 100644
--- a/lib/swoosh/adapters/oh_my_smtp.ex
+++ b/lib/swoosh/adapters/oh_my_smtp.ex
@@ -1,7 +1,7 @@
 defmodule Swoosh.Adapters.OhMySmtp do
   @moduledoc ~S"""
 
-  **deprecated**
+  **Deprecated - use MailPace now**
 
   > Moving from OhMySMTP to MailPace
   > https://docs.mailpace.com/guide/moving_from_ohmysmtp
@@ -30,97 +30,23 @@ defmodule Swoosh.Adapters.OhMySmtp do
   use Swoosh.Adapter, required_config: [:api_key]
 
   alias Swoosh.Email
-  import Swoosh.Email.Render
 
   @endpoint "https://app.ohmysmtp.com/api/v1/send"
 
+  defp endpoint(config), do: config[:endpoint] || @endpoint
+
   @impl true
-  @deprecated "Use Swoosh.Adapter.MailPlace.deliver/2 instead"
+  @deprecated "use Swoosh.Adapter.MailPace.deliver/2 instead"
   def deliver(%Email{} = email, config \\ []) do
-    headers = prepare_headers(config)
-    params = email |> prepare_body() |> Swoosh.json_library().encode!
-
-    case Swoosh.ApiClient.post(endpoint(config), headers, params, email) do
-      {:ok, 200, _headers, body} ->
-        {:ok, Swoosh.json_library().decode!(body)}
-
-      {:ok, code, _headers, body} when code > 399 ->
-        case Swoosh.json_library().decode(body) do
-          {:ok, error} -> {:error, {code, error}}
-          {:error, _} -> {:error, {code, body}}
-        end
-
-      {:error, reason} ->
-        {:error, reason}
-    end
-  end
-
-  defp prepare_headers(config) do
-    [
-      {"User-Agent", "swoosh/#{Swoosh.version()}"},
-      {"OhMySMTP-Server-Token", config[:api_key]},
-      {"Content-Type", "application/json"},
-      {"Accept", "application/json"}
-    ]
+    Swoosh.Adapters.MailPace.deliver(
+      email,
+      Keyword.merge(
+        [
+          endpoint: endpoint(config),
+          server_token_key: "OhMySMTP-Server-Token"
+        ],
+        config
+      )
+    )
   end
-
-  defp prepare_body(email) do
-    %{}
-    |> prepare_from(email)
-    |> prepare_to(email)
-    |> prepare_subject(email)
-    |> prepare_html(email)
-    |> prepare_text(email)
-    |> prepare_cc(email)
-    |> prepare_bcc(email)
-    |> prepare_reply_to(email)
-    |> prepare_attachments(email)
-  end
-
-  defp prepare_from(body, %{from: from}), do: Map.put(body, "from", render_recipient(from))
-
-  defp prepare_to(body, %{to: to}), do: Map.put(body, "to", render_recipient(to))
-
-  defp prepare_cc(body, %{cc: []}), do: body
-  defp prepare_cc(body, %{cc: cc}), do: Map.put(body, "cc", render_recipient(cc))
-
-  defp prepare_bcc(body, %{bcc: []}), do: body
-  defp prepare_bcc(body, %{bcc: bcc}), do: Map.put(body, "bcc", render_recipient(bcc))
-
-  defp prepare_reply_to(body, %{reply_to: nil}), do: body
-
-  defp prepare_reply_to(body, %{reply_to: reply_to_recipient}),
-    do: Map.put(body, "replyto", render_recipient(reply_to_recipient))
-
-  defp prepare_subject(body, %{subject: ""}), do: body
-  defp prepare_subject(body, %{subject: subject}), do: Map.put(body, "subject", subject)
-
-  defp prepare_text(body, %{text_body: nil}), do: body
-  defp prepare_text(body, %{text_body: text_body}), do: Map.put(body, "textbody", text_body)
-
-  defp prepare_html(body, %{html_body: nil}), do: body
-  defp prepare_html(body, %{html_body: html_body}), do: Map.put(body, "htmlbody", html_body)
-
-  defp prepare_attachments(body, %{attachments: []}), do: body
-
-  defp prepare_attachments(body, %{attachments: attachments}) do
-    attachments =
-      Enum.map(attachments, fn %{content_type: content_type, filename: name} = attachment ->
-        attachment_object = %{
-          name: name,
-          content: Swoosh.Attachment.get_content(attachment, :base64),
-          content_type: content_type
-        }
-
-        if attachment.type == :inline do
-          Map.put(attachment_object, :cid, attachment.cid)
-        else
-          attachment_object
-        end
-      end)
-
-    Map.put(body, "attachments", attachments)
-  end
-
-  defp endpoint(config), do: config[:endpoint] || @endpoint
 end
diff --git a/lib/swoosh/adapters/sendinblue.ex b/lib/swoosh/adapters/sendinblue.ex
index 27fe320..3dc1205 100644
--- a/lib/swoosh/adapters/sendinblue.ex
+++ b/lib/swoosh/adapters/sendinblue.ex
@@ -1,9 +1,12 @@
 defmodule Swoosh.Adapters.Sendinblue do
   @moduledoc ~S"""
-  An adapter that sends email using the Sendinblue API (Transactional emails only).
+  **Deprecated - use Brevo now**
 
-  For reference: [Sendinblue API docs](https://developers.sendinblue.com/reference/sendtransacemail)
+  > Moving from Sendinblue to Brevo
+  > https://www.brevo.com/blog/becoming-brevo/
 
+  An adapter that sends email using the Sendinblue API (Transactional emails only).
+  For reference: [Sendinblue API docs](https://developers.sendinblue.com/reference/sendtransacemail)
   **This adapter requires an API Client.** Swoosh comes with Hackney and Finch out of the box.
   See the [installation section](https://hexdocs.pm/swoosh/Swoosh.html#module-installation)
   for details.
@@ -14,7 +17,6 @@ defmodule Swoosh.Adapters.Sendinblue do
       config :sample, Sample.Mailer,
         adapter: Swoosh.Adapters.Sendinblue,
         api_key: "my-api-key"
-
       # lib/sample/mailer.ex
       defmodule Sample.Mailer do
         use Swoosh.Mailer, otp_app: :sample
@@ -23,7 +25,6 @@ defmodule Swoosh.Adapters.Sendinblue do
   ## Using with provider options
 
       import Swoosh.Email
-
       new()
       |> from("nora@example.com")
       |> to("shushu@example.com")
@@ -39,18 +40,13 @@ defmodule Swoosh.Adapters.Sendinblue do
 
     * `sender_id` (integer) - `sender`, the sender `id` where this library will
       add email obtained from the `from/1`
-
     * `template_id` (integer) - `templateId`, the Id of the `active`
       transactional email template
-
     * `params` (map) - `params`, a map of key/value attributes to customize the
       template
-
     * `tags` (list[string]) - `tags`, a list of tags for each email for easy
       filtering
-
     * `schedule_at` (UTC DateTime) - `schedule_at`, a UTC date-time on which the email has to schedule
-
   """
 
   use Swoosh.Adapter, required_config: [:api_key]
@@ -58,159 +54,12 @@ defmodule Swoosh.Adapters.Sendinblue do
   alias Swoosh.Email
 
   @base_url "https://api.sendinblue.com/v3"
-  @api_endpoint "/smtp/email"
 
   defp base_url(config), do: config[:base_url] || @base_url
 
   @impl true
+  @deprecated "use Swoosh.Adapters.Brevo.deliver/2 instead"
   def deliver(%Email{} = email, config \\ []) do
-    headers = [
-      {"Accept", "application/json"},
-      {"Content-Type", "application/json"},
-      {"User-Agent", "swoosh/#{Swoosh.version()}"},
-      {"Api-Key", config[:api_key]}
-    ]
-
-    body = email |> prepare_payload() |> Swoosh.json_library().encode!
-    url = [base_url(config), @api_endpoint]
-
-    case Swoosh.ApiClient.post(url, headers, body, email) do
-      {:ok, code, _headers, body} when code >= 200 and code <= 399 ->
-        {:ok, %{id: extract_message_id(body)}}
-
-      {:ok, code, _headers, body} when code >= 400 ->
-        case Swoosh.json_library().decode(body) do
-          {:ok, error} -> {:error, {code, error}}
-          {:error, _} -> {:error, {code, body}}
-        end
-
-      {:error, reason} ->
-        {:error, reason}
-    end
+    Swoosh.Adapters.Brevo.deliver(email, Keyword.merge([base_url: base_url(config)], config))
   end
-
-  defp extract_message_id(body) do
-    body
-    |> Swoosh.json_library().decode!()
-    |> Map.get("messageId")
-  end
-
-  defp prepare_payload(email) do
-    %{}
-    |> prepare_from(email)
-    |> prepare_reply_to(email)
-    |> prepare_to(email)
-    |> prepare_cc(email)
-    |> prepare_bcc(email)
-    |> prepare_subject(email)
-    |> prepare_text_content(email)
-    |> prepare_html_content(email)
-    |> prepare_template_id(email)
-    |> prepare_headers(email)
-    |> prepare_params(email)
-    |> prepare_tags(email)
-    |> prepare_attachments(email)
-    |> prepare_schedule_at(email)
-  end
-
-  defp prepare_from(payload, %{from: {_name, email}, provider_options: %{sender_id: sender_id}}),
-    do: Map.put(payload, "sender", %{id: sender_id, email: email})
-
-  defp prepare_from(payload, %{from: {_, "TEMPLATE"}}), do: payload
-
-  defp prepare_from(payload, %{from: from}),
-    do: Map.put(payload, "sender", prepare_recipient(from))
-
-  defp prepare_reply_to(payload, %{reply_to: nil}),
-    do: payload
-
-  defp prepare_reply_to(payload, %{reply_to: reply_to}),
-    do: Map.put(payload, "replyTo", prepare_recipient(reply_to))
-
-  defp prepare_to(payload, %{to: to}) do
-    Map.put(payload, "to", Enum.map(to, &prepare_recipient/1))
-  end
-
-  defp prepare_cc(payload, %{cc: []}), do: payload
-
-  defp prepare_cc(payload, %{cc: cc}) do
-    Map.put(payload, "cc", Enum.map(cc, &prepare_recipient/1))
-  end
-
-  defp prepare_bcc(payload, %{bcc: []}), do: payload
-
-  defp prepare_bcc(payload, %{bcc: bcc}) do
-    Map.put(payload, "bcc", Enum.map(bcc, &prepare_recipient/1))
-  end
-
-  defp prepare_subject(payload, %{subject: ""}), do: payload
-
-  defp prepare_subject(payload, %{subject: subject}),
-    do: Map.put(payload, "subject", subject)
-
-  defp prepare_subject(payload, _), do: payload
-
-  defp prepare_text_content(payload, %{text_body: nil}), do: payload
-
-  defp prepare_text_content(payload, %{text_body: text_content}) do
-    Map.put(payload, "textContent", text_content)
-  end
-
-  defp prepare_html_content(payload, %{html_body: nil}), do: payload
-
-  defp prepare_html_content(payload, %{html_body: html_content}) do
-    Map.put(payload, "htmlContent", html_content)
-  end
-
-  defp prepare_template_id(payload, %{provider_options: %{template_id: template_id}}) do
-    Map.put(payload, "templateId", template_id)
-  end
-
-  defp prepare_template_id(payload, _), do: payload
-
-  defp prepare_headers(payload, %{headers: map}) when map_size(map) == 0, do: payload
-
-  defp prepare_headers(payload, %{headers: headers}) do
-    Map.put(payload, "headers", headers)
-  end
-
-  defp prepare_params(payload, %{provider_options: %{params: params}}) when is_map(params) do
-    Map.put(payload, "params", params)
-  end
-
-  defp prepare_params(payload, _), do: payload
-
-  defp prepare_tags(payload, %{provider_options: %{tags: tags}}) when is_list(tags) do
-    Map.put(payload, "tags", tags)
-  end
-
-  defp prepare_tags(payload, _), do: payload
-
-  defp prepare_attachments(payload, %{attachments: []}), do: payload
-
-  defp prepare_attachments(payload, %{attachments: attachments}) do
-    Map.put(
-      payload,
-      "attachment",
-      Enum.map(
-        attachments,
-        &%{
-          name: &1.filename,
-          content: Swoosh.Attachment.get_content(&1, :base64)
-        }
-      )
-    )
-  end
-
-  defp prepare_schedule_at(payload, %{provider_options: %{schedule_at: schedule_at}}) do
-    Map.put(payload, "scheduledAt", schedule_at)
-  end
-
-  defp prepare_schedule_at(payload, _), do: payload
-
-  defp prepare_recipient({name, email}) when name in [nil, ""],
-    do: %{email: email}
-
-  defp prepare_recipient({name, email}),
-    do: %{name: name, email: email}
 end
diff --git a/mix.exs b/mix.exs
index 404eb5b..d69f4e3 100644
--- a/mix.exs
+++ b/mix.exs
@@ -78,6 +78,11 @@ defmodule Swoosh.Mixfile do
     ]
   end
 
+  @deprecated_adapters [
+    Swoosh.Adapters.OhMySmtp,
+    Swoosh.Adapters.Sendinblue
+  ]
+
   defp docs do
     [
       source_ref: "v#{@version}",
@@ -105,7 +110,7 @@ defmodule Swoosh.Mixfile do
           Swoosh.TestAssertions,
           Swoosh.X.TestAssertions
         ],
-        Deprecated: Swoosh.Adapters.OhMySmtp
+        Deprecated: @deprecated_adapters
       ]
     ]
   end
@@ -117,7 +122,7 @@ defmodule Swoosh.Mixfile do
       [_, module] = Regex.run(~r/\Adefmodule (.+) do/, content)
       module |> String.split(".") |> Module.concat()
     end)
-    |> Kernel.--([Swoosh.Adapters.OhMySmtp])
+    |> Kernel.--(@deprecated_adapters)
   end
 
   defp aliases do


Test patch:
diff --git a/test/integration/adapters/sendinblue_test.exs b/test/integration/adapters/brevo_test.exs
similarity index 59%
rename from test/integration/adapters/sendinblue_test.exs
rename to test/integration/adapters/brevo_test.exs
index 7e383da..5831eed 100644
--- a/test/integration/adapters/sendinblue_test.exs
+++ b/test/integration/adapters/brevo_test.exs
@@ -1,4 +1,4 @@
-defmodule Swoosh.Integration.Adapters.SendinblueTest do
+defmodule Swoosh.Integration.Adapters.BrevoTest do
   use ExUnit.Case, async: true
 
   import Swoosh.Email
@@ -7,8 +7,8 @@ defmodule Swoosh.Integration.Adapters.SendinblueTest do
 
   setup_all do
     config = [
-      api_key: System.get_env("SENDINBLUE_API_KEY"),
-      domain: System.get_env("SENDINBLUE_DOMAIN")
+      api_key: System.get_env("BREVO_API_KEY") || System.get_env("SENDINBLUE_API_KEY"),
+      domain: System.get_env("BREVO_DOMAIN") || System.get_env("SENDINBLUE_DOMAIN")
     ]
 
     {:ok, config: config}
@@ -17,15 +17,15 @@ defmodule Swoosh.Integration.Adapters.SendinblueTest do
   test "simple deliver", %{config: config} do
     email =
       new()
-      |> from({"Swoosh Sendinblue", "swoosh+sendinblue@#{config[:domain]}"})
+      |> from({"Swoosh Brevo", "swoosh+brevo@#{config[:domain]}"})
       |> reply_to("swoosh+replyto@#{config[:domain]}")
       |> to("swoosh+to@#{config[:domain]}")
       |> cc("swoosh+cc@#{config[:domain]}")
       |> bcc("swoosh+bcc@#{config[:domain]}")
-      |> subject("Swoosh - Sendinblue integration test")
+      |> subject("Swoosh - Brevo integration test")
       |> text_body("This email was sent by the Swoosh library automation testing")
       |> html_body("<p>This email was sent by the Swoosh library automation testing</p>")
 
-    assert {:ok, %{id: _}} = Swoosh.Adapters.Sendinblue.deliver(email, config)
+    assert {:ok, %{id: _}} = Swoosh.Adapters.Brevo.deliver(email, config)
   end
 end
diff --git a/test/swoosh/adapters/sendinblue_test.exs b/test/swoosh/adapters/brevo_test.exs
similarity index 89%
rename from test/swoosh/adapters/sendinblue_test.exs
rename to test/swoosh/adapters/brevo_test.exs
index e05cb68..bd004fb 100644
--- a/test/swoosh/adapters/sendinblue_test.exs
+++ b/test/swoosh/adapters/brevo_test.exs
@@ -1,8 +1,8 @@
-defmodule Swoosh.Adapters.SendinblueTest do
+defmodule Swoosh.Adapters.BrevoTest do
   use Swoosh.AdapterCase, async: true
 
   import Swoosh.Email
-  alias Swoosh.Adapters.Sendinblue
+  alias Swoosh.Adapters.Brevo
 
   @example_message_id "<42.11@relay.example.com>"
 
@@ -45,7 +45,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "text-only delivery returns :ok", %{bypass: bypass, config: config} do
@@ -69,7 +69,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "html-only delivery returns :ok", %{bypass: bypass, config: config} do
@@ -93,7 +93,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with all fields returns :ok", %{bypass: bypass, config: config} do
@@ -133,7 +133,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with template_id returns :ok", %{bypass: bypass, config: config} do
@@ -157,7 +157,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with template_id and params returns :ok", %{bypass: bypass, config: config} do
@@ -191,7 +191,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with template_id using template's sender returns :ok", %{
@@ -221,7 +221,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with template_id using template's subject returns :ok", %{
@@ -250,7 +250,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with scheduled_at returns :ok", %{bypass: bypass, config: config} do
@@ -280,7 +280,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       make_response(conn)
     end)
 
-    assert Sendinblue.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
+    assert Brevo.deliver(email, config) == {:ok, %{id: "#{@example_message_id}"}}
   end
 
   test "deliver/1 with 429 response", %{bypass: bypass, config: config, valid_email: email} do
@@ -296,7 +296,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
           "message" => "The expected rate limit is exceeded."
         }}}
 
-    assert Sendinblue.deliver(email, config) == response
+    assert Brevo.deliver(email, config) == response
   end
 
   test "deliver/1 with 4xx response", %{bypass: bypass, config: config, valid_email: email} do
@@ -312,7 +312,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
           "message" => "error message explained."
         }}}
 
-    assert Sendinblue.deliver(email, config) == response
+    assert Brevo.deliver(email, config) == response
   end
 
   test "deliver/1 with 5xx response", %{bypass: bypass, config: config, valid_email: email} do
@@ -322,11 +322,11 @@ defmodule Swoosh.Adapters.SendinblueTest do
       Plug.Conn.resp(conn, 500, "")
     end)
 
-    assert Sendinblue.deliver(email, config) == {:error, {500, ""}}
+    assert Brevo.deliver(email, config) == {:error, {500, ""}}
   end
 
   test "validate_config/1 with valid config", %{config: config} do
-    assert Sendinblue.validate_config(config) == :ok
+    assert Brevo.validate_config(config) == :ok
   end
 
   test "validate_config/1 with invalid config" do
@@ -336,7 +336,7 @@ defmodule Swoosh.Adapters.SendinblueTest do
       expected [:api_key] to be set, got: []
       """,
       fn ->
-        Sendinblue.validate_config([])
+        Brevo.validate_config([])
       end
     )
   end