Mimemail runs all http headers through UnstructuredHeader() while it should not

Created on 12 December 2023, about 1 year ago

Problem/Motivation

Mimemail runs all email headers through UnstructuredHeader() which requires string input. This class is used for converting non-ASCII characters to an RFC compliant strings. The problem is that in Drupal 8 and newer, not all headers are required to be strings - some header values are objects for example.

Steps to reproduce

1. Create custom hook_mail implementation like so:

/**
 * Implements hook_mail().
 */
function modulename_mail($key, &$message, $params) {
  if ($key == 'message') {
    // Set date header, which is expected to be DateTimeInterface.
    // See: https://github.com/symfony/mime/blob/6.3/Header/Headers.php#L114
    $message['headers']['Date'] = new DateTime();

    // Set subject.
    $message['subject'] = $params['subject'];

    // Set body.
    foreach ($params['body'] as $body_part) {
      $message['body'][] = $body_part;
    }
  }
}

2. Send any email message using the above hook while using Drupal's default PHP mailer. The email will send fine and it will contain 'Date' header with the right value.

3. Now enable the mimemail for the above hook and try to send the email again.

4. You will get an error:
TypeError: Symfony\Component\Mime\Header\UnstructuredHeader::__construct(): Argument #2 ($value) must be of type string, DateTime given, called in \web\modules\contrib\mimemail\src\Utility\MimeMailFormatHelper.php on line 795 in Symfony\Component\Mime\Header\UnstructuredHeader->__construct() (line 23 of \vendor\symfony\mime\Header\UnstructuredHeader.php).

The error happens because Mimemail tries to run the Date header, which is an object "value", through function that operates on strings.

Proposed resolution

Apply the patch attached. It fixes the problem

πŸ› Bug report
Status

Active

Version

1.0

Component

Code

Created by

πŸ‡΅πŸ‡±Poland pawel.traczynski Warsaw

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pawel.traczynski
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.6
    last update about 1 year ago
    1 pass, 7 fail
  • πŸ‡ΊπŸ‡ΈUnited States tr Cascadia

    Well no, an object is not a valid value for the message array. In the Drupal API this array is defined to be the same as the PHP mail() function arguments. What you should do in your hook is convert your date to a string.

  • πŸ‡΅πŸ‡±Poland pawel.traczynski Warsaw

    Unfortunately you are wrong.

    I suggest you test it without the mimemail module enabled, so just using Drupal Core PHP Mailer:

    1. Send email with 'Date' email header set to DateTimeInterface $message['headers']['Date'] = new DateTime();. The email will send correctly.

    2. Now send another email but this set 'Date header to any string date, like a result of date('r') $message['headers']['Date'] = date('r'); You will get this error:

    TypeError: Symfony\Component\Mime\Header\Headers::addDateHeader(): Argument #2 ($dateTime) must be of type DateTimeInterface, string given, called in \vendor\symfony\mime\Header\Headers.php on line 152 in Symfony\Component\Mime\Header\Headers->addDateHeader() (line 114 of \vendor\symfony\mime\Header\Headers.php).
    
    Symfony\Component\Mime\Header\Headers->addHeader('Date', 'Wed, 13 Dec 2023 08:29:21 +0100') (Line: 102)
    Drupal\Core\Mail\Plugin\Mail\PhpMail->mail(Array) (Line: 50)
    Drupal\mailsystem\Adapter->mail(Array) (Line: 307)
    Drupal\Core\Mail\MailManager->doMail('mymodule', 'mykey', 'user@example.com', 'pl', Array, NULL, 1) (Line: 180)
    Drupal\Core\Mail\MailManager->Drupal\Core\Mail\{closure}() (Line: 592)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 181)
    Drupal\Core\Mail\MailManager->mail('mymodule', 'mykey', 'user@example.com', 'pl', Array, NULL, 1) (Line: 70)

    As you can see a DateTimeInterface object is expected, NOT a string.

  • πŸ‡΅πŸ‡±Poland pawel.traczynski Warsaw

    Can we have this resolved please?

  • πŸ‡΅πŸ‡±Poland pawel.traczynski Warsaw

    How can I help further, despite the patch provided, to have this fixed? If you don't have time then add me as a maintainer and I will fix it.

  • πŸ‡¨πŸ‡¦Canada joelpittet Vancouver

    @pawel.traczynski starting a reply with

    Unfortunately you are wrong.

    is not a great way to start a constructive discussion, I'd bet @TR stopped reading after that line... doesn't matter how correct you may or may not be.

    I have an Merge Request here https://www.drupal.org/project/mimemail/issues/3257799#comment-15486431 πŸ› RfcComplianceException: RFC 2822 Needs work that might inadvertently do what you are asking for, give it a try if you agree with the approach.

  • Status changed to Needs review 10 months ago
  • πŸ‡¨πŸ‡¦Canada joelpittet Vancouver

    A couple things on the issue correct: all patches should be applied against the dev branch, so changing the version to the dev branch. And since there is a patch on the issue it's good to have the status as "Needs Review" (also used to trigger tests to run against the patch)

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 10.2.x + Environment: PHP 8.1 & MySQL 5.7
    last update 10 months ago
    28 pass
  • πŸ‡΅πŸ‡±Poland pawel.traczynski Warsaw

    Thanks @joelpittet. I found the first reply starting with "Well, no" to not be good start of a constructive conversation either but I see the point. I have provided patch and solution. Has it been integrated into the module?

Production build 0.71.5 2024