jamescarr

jamescarr

I just had a heck of a time getting mailgun working this evening, ultimately due to a typo on my mailgun domain in my config details. I thought I would share my journey for those who might run into the same issue.

Since I use direnv, I configured mailgun in config/runtime.exs to work in both dev and production environments:

   config :pento, Pento.Mailer,
     adapter: Swoosh.Adapters.Mailgun,
     api_key: System.get_env("MAILGUN_API_KEY"),
     domain: System.get_env("MAILGUN_DOMAIN"),
     base_url: "https://api.mailgun.net/v3",
     log_level: :debug

I likewise configured the appropriate settings for dev and production:

config :pento, Pento.Mailer, adapter: Swoosh.Adapters.Mailgun
config :swoosh, api_client: Swoosh.ApiClient.Finch, finch_name: Pento.Finch

And also added plug and multipart dependencies to mix.exs. I loaded up my application, reset a password and it reported success, redirecting me to the login screen. But mailgun reported no emails sent! Sadly, I am on a free plan so no logs visible on mailgun’s side. I looked through the console, but it looks like the log_level: :debug setting for the mailer had no effect, there were no logs beyond the ones indicating a success and redirect.

I decided to change up the default UserNotifier boilerplate to log an error and sure enough, I got an error log for {405, ""}.

    case Mailer.deliver(email) do
      {:ok, response} ->
        Logger.info("Email sent successfully: #{inspect(response)}")
        {:ok, email}
      {:error, reason} ->
        Logger.error("Failed to send email: #{inspect(reason)}")
        {:error, email}
    end

This was a start, but still missing a lot of detail. I went looking around to see if there was some way to log the lower level finch requests and after some reading came up with the following (not sure if this is correct):

defmodule Pento.Logger do
  require Logger

  def attach do
    :telemetry.attach(
      "finch-request-logger",
      [:finch, :request, :stop],
      &__MODULE__.handle_event/4,
      nil
    )
  end

  def handle_event(_event_name, measurements, metadata, _config) do
    {_, response} = metadata.result
    details = %{
      response_status: response.status,
      request_host: metadata.request.host,
      request_method: metadata.request.method,
      request_path: metadata.request.path,
      duration: measurements.duration
    }
    if response.status > 400 do
      Logger.error("#{inspect(details)}")
    else
      Logger.info("#{inspect(details)}")
    end

  end
end

Finally, I modified the generated PentoWeb.Telemetry module to attach the logger.

  @impl true
  def init(_arg) do
    children = [
      # Telemetry poller will execute the given period measurements
      # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
      {:telemetry_poller, measurements: periodic_measurements(), period: 10_000},
      {Finch, name: Pento.Logger}
    ]
    Pento.Logger.attach()

Thankfully, this logged out the details that showed me where I had gone wrong, can you spot it?

[error] %{request_host: "api.mailgun.net", request_path: "/v3/https://sandbox6b3be3f286c2409ab2d71b6fb9b1d52c.mailgun.org//messages", response_status: 405, request_method: "POST", duration: 340163917}

My question for you all going forward, is this the “right way” to log http requests from a third party? If I wanted to log all external requests made by finch in the future, it seems like this is the right approach?

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews