Adding the action name in deliver.action_mailer event

Hi there,

Is there a reason why deliver.action_mailer event (here) does not contain the action name?

If I want to create a log where I save the mailer action and the mail recipients, I need to do it across two separate events, calling multiple time the database.

ActiveSupport::Notifications.subscribe(/action_mailer/) do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)

  case event.name.split('.').first
  when 'process'
    # create the log with action name contained in `event.payload[:action]` and `event.transaction_id`
  when 'deliver'
    # find the log with `event.transaction_id` and assign `event.payload[:to]`
  end
end

It seems to me that this would not be a big change in the payload creation method in the mailer, but I may be missing something.

Some folks hacked a workaround by using the after_action of mailers to add attributes on the message object and use it later in an observer. This seems like a lot of custom code to have instrumentation that actionmailer already provides.
Also, the approved answer there uses after_action to directly create the log, but after_action is called before the mail is actually sent, so a log can be created even if a mail is never sent.

In short: no solutions that work for me, hence this topic.

Thanks!

To directly answer your question, I think the action key is absent so that the Mail object is not directly coupled to the Action Mailer.

That said, I have a pending Rails PR that adds an after_delivery hook to Action Mailer that I would be curious if that would solve your use case?

I think it does. Is this implying that observers/interceptor will be kind of deprecated? It seems that these new callbacks and observers/interceptors duplicates each other.

I think the action key is absent so that the Mail object is not directly coupled to the Action Mailer.

I think you’re right, but I was kind of thinking of a way to pass custom attributes that will be later placed into the payload of the triggered event.

That said, I thought using instrumentation was the “best” way to logs things / manipulate data after an email is sent.

Is this implying that observers/interceptor will be kind of deprecated?

Not deprecated, maybe less necessary when working within Rails (e.g. mutating models, etc.); observers/Interceptors are Mail hooks and there are probably valid reasons why someone might want to specifically observe/intercept in Mail. But hopefully this PR helps make that separation clearer (Rails stuff can stay in Action Mailer; Mail stuff can go in Mail).

I thought using instrumentation was the “best” way to logs things / manipulate data after an email is sent.

I think instrumentation is one of several workarounds to do that. Instrumentation is intended for logging. I think instrumentation is a bad way to mutate data or do anything complicated/error-able.

I think it’s a good generalizable rule that if you find instrumentation is the only way to hook into some Rails process that you consistently need to insert custom behavior into, there should be a hook/callback there.

I asked a Rails Core member about my PR because I was like “This seems like a frequent need so I feel like I’m not understanding something about why this doesn’t already exist?” and they were like “Oh yeah, that isn’t an uncommon feeling. That’s what we do.”