defmodule Bamboo.FallbackAdapter do @moduledoc """ This adapter allows you to compose multiple adapters to increase the guarantee of delivering. It applies adapters one by one and fails only when all adapters fail. Config example: config :myapp, MyApp.Mailer, adapter: Bamboo.FallbackAdapter, fallback_options: [ {Bamboo.SendGridAdapter, api_key: "SENDGRID_API_KEY"}, {Bamboo.MailgunAdapter, api_key: "MAILGUN_API_KEY", domain: "MAILGUN_DOMAIN"} ] """ @behaviour Bamboo.Adapter def handle_config(config) do config |> Map.update!(:fallback_options, fn adapter_configs -> adapter_configs |> Enum.map(fn {adapter, config} -> { adapter, config |> Enum.into(%{}) |> adapter.handle_config() } end) end) end def deliver(email, %{fallback_options: adapter_configs}) do adapter_configs |> Enum.reduce_while([], fn {adapter, config}, errors -> try do {:halt, adapter.deliver(email, config)} rescue e in Bamboo.ApiError -> {:cont, [e | errors]} end end) |> case do %Bamboo.Email{} = email -> email errors -> Bamboo.ApiError.raise_api_error(""" None of given providers sent an email #{errors |> Enum.map(& &1.message) |> Enum.join("\n\n")} """) end end def supports_attachments?, do: true end