Problem/Motivation

We currently don't log the sending of order receipts, I think it's a really nice to have feature.

The problem is that we can only react to an email being sent via a hook_mail_alter() but unfortunately, that happens too early and the log module wouldn't be able to know whether the email was successfully sent.

So I think we need to introduce a new event that allows us to access the email params and the $message array.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jsacksick created an issue. See original summary.

jsacksick’s picture

Status: Active » Needs review
FileSize
11.83 KB

The attached patch adds 2 log templates (one for when the email fails to be sent, and the other one on success).

I'm wondering whether we should create a log template per email sent? vs reusing a "generic" one, although we only send the order receipt from Commerce.

Also, the event subscriber that reacts to the email being sent just checks whether the mail id starts with "order_", so any other integration sending an email with an ID starting with "order_" is going to be logged.

The log templates could be improved, as well as the naming of the event introduced when an email is sent through the Commerce mail handler. (currently called PostMailSend), since it's fired AFTER the email is sent.

These are 2 log templates that were created:

Mail "{{ id }}" failed to be sent to {{ to_email }}.
Mail "{{ id }}" successfully sent to {{ to_email }}.
mglaman’s picture

  1. +++ b/modules/log/commerce_log.commerce_log_templates.yml
    @@ -27,3 +27,11 @@ order_assigned:
    +order_mail_success:
    +  category: commerce_order
    +  label: 'Mail successfully sent'
    +  template: '<p>Mail "{{ id }}" successfully sent to {{ to_email }}.</p>'
    
    +++ b/modules/log/src/EventSubscriber/MailEventSubscriber.php
    @@ -0,0 +1,58 @@
    +    $template_id = (bool) $message['result'] ? 'order_mail_success' : 'order_mail_failure';
    +    $log_params = ['id' => $params['id'], 'to_email' => $message['to']];
    

    We could provide specific logs for known email key IDs and fallback to this if none exists.

    Maybe follow a pattern of `mail_${key}`? That way users can also provide log templates for custom emails they send through our mail handler.

    So provide a default `mail_order_receipt`, then someone could provide `mail_order_shipped` if they send an `order_shipped` email through our service (I currently do this.)

    So we can check if the definition exists and use that or the fallback for the SUCCESS, and the generic failure on any failure.

  2. +++ b/modules/log/src/EventSubscriber/MailEventSubscriber.php
    @@ -0,0 +1,58 @@
    +class MailEventSubscriber implements EventSubscriberInterface {
    ...
    +    if (!isset($params['order']) || strpos($params['id'], 'order_') !== 0) {
    +      return;
    +    }
    

    This only handles order mail, so maybe we should rename it as such?

  3. +++ b/modules/log/src/EventSubscriber/MailEventSubscriber.php
    @@ -0,0 +1,58 @@
    +  /**
    +   * The log storage.
    +   *
    +   * @var \Drupal\commerce_log\LogStorageInterface
    +   */
    +  protected $logStorage;
    ...
    +  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    +    $this->logStorage = $entity_type_manager->getStorage('commerce_log');
    

    I've stopped grabbing entity storage in constructors, as it adds a little bit of overhead fetching the storage when it may not be used.

    When collecting event subscribers, this will always be constructed and always fetch and instantiate the log storage.

jsacksick’s picture

FileSize
15.91 KB
10.92 KB

Attached patch is addressing the feedbacks from #3.

mglaman’s picture

Status: Needs review » Reviewed & tested by the community

🥳 looks great to me, this will definitely help customer support users

rszrama’s picture

Status: Reviewed & tested by the community » Needs review

I like the idea of logging failures, but it may be confusing what success or failure means in this context. A log message of:

Order receipt email sent to @mail (Result: "failure").

Makes me wonder why the log says it was sent if the result was a failure; did it actually send? was the failure a lack of receipt by the customer? an error from an external email service? In reality, it just didn't send. I'm open to suggestions, but it seems better to have:

Order receipt email sent to john.doe@example.com.

Order receipt email failed to send to john.doe@example.com.

The problem is that seems to violate the expectation of log message templates. I can't tell if we'd have to register two templates per mail (successful send vs. failure) or perhaps just implement a single failure template for any email:

Failed to send [email type] to john.doe@example.com.

Using a specific template for failures may make it easier to add contextual links to log messages in the future (e.g. a link or button to attempt to redeliver that email in the stream), though I'm dependent on you to know what's really possible there.

jsacksick’s picture

FileSize
14.41 KB
8.47 KB

Makes sense! Attached patch addresses the comment from #6 and also introduces a generic log template for "generic" order emails so that we still provide a message if no log template exists, both in case of failure and success.

rinasek’s picture

Status: Needs review » Reviewed & tested by the community

Looking good to me.

rszrama’s picture

+1

  • mglaman committed ab9ef8b on 8.x-2.x authored by jsacksick
    Issue #3136999 by jsacksick, mglaman, rszrama, rinasek: Log a message to...
mglaman’s picture

Status: Reviewed & tested by the community » Fixed

🥳 Committed!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.