Problem/Motivation

Backward compatibility mails does not work with multiple to addresses.
If emails are sending like this I am getting Email "mail@test.com, mail2@test.com" does not comply with addr-spec of RFC 2822. error message.

The same is true when putting multiple addresses in other fields such as cc, bcc, from, etc. The same is true if using a display name Joe Bloggs<joe.bloggs@example.com>.

Steps to reproduce

Send mail to multiple addresses separated by , (comma):

$mail_manager = \Drupal::service('plugin.manager.mail');
$mail_manager->mail('module', 'key', 'mail@test.com, mail2@test.com', 'en');

Proposed resolution

We would like to have a utility function that convert from "an encoded email address in the form of a string separated by commas" to an array of symfony Address objects. We can then use this function whenever we convert an address in BC mode.

However this is fairly complex code, with lots of different cases to consider. So ideally we would find some existing library code that already does it and use that.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

DavorHorvacki created an issue. See original summary.

holo96’s picture

Issue summary: View changes
adamps’s picture

Status: Active » Postponed (maintainer needs more info)

Thanks for the report. Please can you add more detail to the issue summary - how are you sending the mail, what exact steps did you follow?

holo96’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)

Seems like I cannot recreate this issue in latest dev release.
So guess it is fixed.

holo96’s picture

Status: Closed (won't fix) » Active

Sorry for bothering you. I've actually recreated issue.
I am sending emails from my own hook and function.
Hook is not important as code does not get to hook.

example code:

$mail_manager = \Drupal::service('plugin.manager.mail');
$mail_manager->mail('module', 'key', 'mail@test.com, mail2@test.com', 'en', [
  'title' => 'test',
  'message' => 'test',
], NULL, TRUE);
adamps’s picture

Issue summary: View changes

OK thanks I understand now.

It's not easy to fix - parsing of an address string is complex, not just explode on commas. The address string can contain display names marked by <> and they can have a comma within them. There is code in swiftmailer which was difficult to maintain because the standards for allowed email addresses were gradually growing.

You can avoid the problem if you write an email builder, see documentation https://www.drupal.org/docs/contributed-modules/symfony-mailer-0/emailbu....

imclean’s picture

Such specialist functions should probably be offloaded to a library rather than maintain it within Drupal. Symfony has an issue where Christophe Coevoet states:

I'm fine with adding support for that in symfony/mime. But I would create a new method instead of accepting either a string or an array of strings in the same method.

imclean’s picture

That said, the example in #5 uses the current mail method which appears to only allow a small subset of possible email address formats. How does core verify this?

adamps’s picture

How does core verify this?

I believe core does not do any verification - PhpMail simply passes the value to the in-built PHP mail() function. So it will accept whatever formats PHP accepts, which appears to be quite broad.

Such specialist functions should probably be offloaded to a library rather than maintain it within Drupal

Yes I agree, I don't really expect to accept a patch for this. I've been leaving it open so that people can find the existing issue, rather than them creating a new one.

adamps’s picture

Priority: Normal » Major
Issue summary: View changes

OK when I said

Yes I agree, I don't really expect to accept a patch for this. I've been leaving it open so that people can find the existing issue, rather than them creating a new one.

I'd like to correct myself. It would be fine to have a patch if we could find some library code to use for it.

altagrade’s picture

Hitting the same issue here. Hopefully, this will be fixed soon.

jprj’s picture

I hit this issue with Drupal's contact form (the contact module in core). The instructions are explicit on the contact form: "To specify multiple recipients, separate each email address with a comma." However this produces the problem described.

adamps’s picture

Status: Active » Needs review
StatusFileSize
new4 KB

OK we could have a very simple version that just splits on comma - still seems better than nothing. Here's a patch for that - comments welcome please.

imclean’s picture

+++ b/src/MailerHelper.php
@@ -66,6 +66,16 @@ class MailerHelper implements MailerHelperInterface {
+    foreach (explode(',', $encoded as $part) {
+      $addresses[] = new Address($part);
+    }
+    return $addresses ?: [];
+  }

Would it be worth using imap_rfc822_parse_adrlist(), as questionable as it is, if it's available?

Something like this:

  /**
   * {@inheritdoc}
   */
  public function parseAddress(string $encoded) {
    if (function_exists('imap_rfc822_parse_adrlist')) {
      $addressList = imap_rfc822_parse_adrlist($encoded, '');
      // Clear any IMAP errors.
      imap_errors();

      foreach ($addressList as $address) {
        $name = property_exists($address, 'personal') ? $address->personal : '';
        $email = $address->mailbox . '@' . $address->host;
        $addresses[] = new Address($email, $name);
      }
    }
    else {
      foreach (explode(',', $encoded as $part) {
        $addresses[] = new Address($part);
      }
    }
    return $addresses ?: [];
  }

See: https://www.php.net/manual/en/function.imap-rfc822-parse-adrlist.php

+++ b/src/MailerHelperInterface.php
@@ -10,7 +10,28 @@ use Drupal\Core\Config\Entity\ConfigEntityInterface;
+   * library to encoded once more during sending! New code should store

Should this be "be encoded"?

adamps’s picture

@imclean It certainly seems worth looking at thanks. Would you be willing to create a working patch?

Do you know much about the problems with the library? It would be useful to know if there are any cases where it might actually be worse than splitting on comma.

I tend to prefer only supporting one way of doing things. Could we even have a hard dependency on the PHP IMAP module? When we come to write tests (hopefully soon) we should at least have it as a dev dependency.

Presumably we should not just ignore errors - I think we should create an error/exception of some sort. Already the symfony mailer library does that if it can't create the Address structure.

adamps’s picture

Thinking some more, I have some doubts about the PHP IMAP module.

  1. You have noted that the quality is questionable
  2. If we force require the module it would create work for all sites and yet be used only for migration in code we plan to remove.
  3. Supporting both options is harder to maintain and test. Each site/developer would only presumably test one of them, but it would vary which one. We might get bug reports that are confusing and hard to debug.

What are your thoughts?

imclean’s picture

I tend to agree. The IMAP library is not something which should be required in which case there's not much point for a BC only layer. It's also rfc822 only, not 5322.

Alternatively, some basic checking for a name part could be included. This can be as simple as checking for angle brackets and using everything outside them as the name, removing any quotes. I can provide an example in the next day or so.

adamps’s picture

I can provide an example in the next day or so.

Thanks for the offer. In swiftmailer module there was swiftmailer_parse_mailboxes() however as noted in #6 it was difficult to maintain. I am reluctant to start this journey again.

I propose that we commit the fix in the latest patch (I'll fix the comment as you suggest). People could then raise another issue for further enhancement, however it would quite likely not be fixed as this function is just a migration aid. The preferred approach is to create a Mailer Policy using this module, waiting on #3270172: Address policy should support multiple addresses.

adamps’s picture

Looks like I didn't test the first patch😃.

I would appreciate another review thanks.

  • AdamPS committed dfa04fc on 1.x
    Issue #3254085 by AdamPS, DavorHorvacki, imclean: Sending mails to...
adamps’s picture

Status: Needs review » Fixed

OK, let's get this is so other issues can use it. If there are any further concerns we can handle in a follow on issue.

Status: Fixed » Closed (fixed)

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

tarasiadis’s picture

I'm trying to use patch as below and I get error.

"drupal/symfony_mailer": {
"Sent multiple emails": "https://www.drupal.org/files/issues/2022-03-17/symfony_mailer.multiple-a..."
}

and get bellow error
Could not apply patch! Skipping. The error was: Cannot apply patch https://www.drupal.org/files/issues/2022-03-17/symfony_mailer.multiple-a...

[Exception]
Cannot apply patch Sent multiple emails (https://www.drupal.org/files/issues/2022-03-17/symfony_mailer.multiple-a...)!

And after that I remove this patch to get it back to normal I have problem with drush cr. I get
[warning] Drush command terminated abnormally.

tarasiadis’s picture

I think that there is a conflict with Symfony Mailer Back-compatibility. When I have disable it I can use drush.

tarasiadis’s picture

Finally after applying patch with error...
I have disable Symfony Mailer Back-compatibility to be able work with my site.
But now I cannot enable it again. I'm wondering if the issue solved if I reinstall synfomy mailer at all but I cannot uninstall it as it is required by commerce base module.

Is there any plan for next version as dev?

tarasiadis’s picture

With new dev version my problem solved.

sjamate’s picture

Hi, I have encountered this same problem when configuring more than one email address as a recipient. I have tried to install the dev version of the module but it keeps failing me.

The error is: Error sending email: The email "example@gmail.com; example1@gmail.com" does not comply with RFC 2822 addr-spec.

I have tried to apply patch #19 but it doesn't let me apply it, understanding that it is because it is already merged with the dev version of the module.

Any idea why it might be failing me? Comment #26 says that with the dev version of the module it works, but not for me

Thank you!