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

Issue fork mimemail-3408278

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

pawel.traczynski created an issue. See original summary.

pawel.traczynski’s picture

Title: Mimemail runs all http headers through UnstructuredHeader() while it should not » Mimemail runs all email headers through UnstructuredHeader() while it should not
tr’s picture

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.

pawel.traczynski’s picture

Could 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 time 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.

So to summarize as a result, its possible to send email with 'Date' header using Drupal Core as it correctly handles it. But its not possible to send such email using MimeMail because of the bug that I have pointed outr in my patch.

pawel.traczynski’s picture

Can we have this resolved please?

pawel.traczynski’s picture

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.

joelpittet’s picture

@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 that might inadvertently do what you are asking for, give it a try if you agree with the approach.

joelpittet’s picture

Version: 8.x-1.0-alpha6 » 8.x-1.x-dev
Status: Active » Needs review

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)

pawel.traczynski’s picture

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?

mark_fullmer’s picture

I have an Merge Request that might inadvertently do what you are asking for, give it a try if you agree with the approach.

I was able to reproduce the problem, following the method outlined above, on the latest version of this module. The recently-merged #3257799: RfcComplianceException: RFC 2822 Return-Path does not prevent the error.

I'm not opposed to adding this skip logic, as it will not adversely affect any values sent as a string, but I would point out that while it may bypass the Symfony problem, depending on the mailer being used, there may still be a problem. For example, if sites are using the default phpmailer used by mimemail, they will get a downstream error:

TypeError: trim(): Argument #1 ($string) must be of type string, DateTime given in trim() (line 4460 of /app/vendor/phpmailer/phpmailer/src/PHPMailer.php).

Converting this to a merge request to show passing tests...

mark_fullmer’s picture

Version: 8.x-1.x-dev » 2.0.x-dev

mark_fullmer’s picture

Status: Needs review » Fixed

Now that this issue is closed, please review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, please credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

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