Setting up Swoosh mailer in production

I have an app called Ciao. Swoosh came out of the box in development and I’ve configured it for production based on the documentation but anytime I try to use the mailer I get this error:

04:08:02.967 [warning] Failed to lookup telemetry handlers. Ensure the telemetry application has been started.
** (KeyError) key :adapter not found in: [otp_app: :ciao]
    (elixir 1.13.1) lib/keyword.ex:559: Keyword.fetch!/2
    lib/swoosh/mailer.ex:192: Swoosh.Mailer.deliver/2
    lib/ciao/mailer.ex:2: anonymous fn/2 in Ciao.Mailer.instrument/3
    /app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    lib/ciao/accounts/user_notifier.ex:15: Ciao.Accounts.UserNotifier.deliver/3

My setup config.exs:

config :ciao, Ciao.Mailer,
  adapter: Swoosh.Adapters.Sendgrid,
  api_key: System.get_env("SENDGRID_KEY")

Then in mailer.ex:

  use Swoosh.Mailer, otp_app: :ciao

I’ve tried these configs locally and I was able to connect to Sendgrid but not once I deploy to Fly.

Check if maybe the runtime.exs is somehow overriding the settings from config.exs?

That would be the best place to put the config so you don’t have to recompile the app to change the api_key, for instance.

1 Like

It was originally configured in runtime.exs however after I first got the above error I moved it to config.exs based on the docs.

I just tested it out again and it is the same error whether the config is in runtime.exs or config.exs.

That’s very strange. My guess about the config files was because it worked in dev and not prod so maybe the config was being clobbered in runtime.exs or prod.exs

What do you get when logging in to the remote iex session in prod and running Application.get_env(:ciao, Ciao.Mailer)?

TBH I’m not sure how to do that in Fly :man_facepalming:. Whenever I’m on the remote session Application.get_env/2 always returns nil. But it’s not just this config, I have an S3 bucket that is working fine and when I try get_env/2 for that config I get nil. I’d love to figure that out because being able to get my application configs from the remote session would be super helpful.

Curioser and curioser. All I can say is I just tried remoting into one of my self-hosted prod servers and can get_env fine. Sorry for not being able to help.

Well thanks for the responses. I’m glad that get_env is working for you, (I presume on Fly?), so I know it SHOULD be giving me a response. I’ll check into it and see if there is some Fly config I have messed up.

Unfortunately not on fly, I self-host my own Ubuntu server.

@travisf, what does the following give you?

Application.get_all_env(:ciao)

If the result is [], I’d look at your mix.exs file and check the values returned from the project function, as that might not be setup as you expect.

2 Likes

Hmm I’ve never dug into this much, this is my project function:

     [ 
      app: :ciao,
      version: "0.1.0",
      elixir: "~> 1.12",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [] ++ Mix.compilers(),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()
      ]

Am I missing something there?

That seems ok.

How are you establishing a remote session on fly? Is it like this?

flyctl ssh console # optionally with: -a my-app-name
app/bin/ciao remote 
1 Like

Seems to work fine for me on fly. Must be a config issue somewhere between :ciao, Ciao, etc.

iex(someapp@fdaa:0:7...)1> Application.get_env(:someapp, Accounts.Mailer)
[
  adapter: Swoosh.Adapters.AmazonSES,
 ...
]

1 Like

Ah! That solved my problem not seeing any .env configs. I was accessing it with fly ssh console -s -C "/app/bin/ciao remote" rather than just fly ssh console then remoting in.

Now I can see the Swoosh configs, Application.get_all_env(:ciao)

  {Ciao.Mailer,
   [
     adapter: Swoosh.Adapters.Sendgrid,
     api_key: "SECRET_SENDGRID_KEY_REDACTED"
   ]},

After that the problem became much more manageable (having access to Application .env is so helpful). The next issue I had was the api client, I thought with SendGrid I could set the :api_client to false, but apparently you need one.

config :swoosh, :api_client, Swoosh.ApiClient.Hackney

Did the tick! Thanks for all the help everyone!

3 Likes