laravel / ideas

Issues board used for Laravel internals discussions.
938 stars 28 forks source link

[Question] Allow non-ascii email addresses (for SMTP driver) #1685

Open golonix opened 5 years ago

golonix commented 5 years ago

Currently, there is a problem with sending emails to addresses that contains non-ascii characters on the local part of an address (before @). The problem exists with SMTP driver. SMTP driver uses Swift_SmtpTransport class as an email transport layer. This class's constructor calls parent's constructor and passes arguments that are resolved out of the Switfmailer's dependency container. One of the dependencies is address encoder. By default, it is an IDN address encoder, which allows non-ascii chars only on domain part of an address (after @) and that is causing the issue.

Swiftmailer's documentation suggests how to mitigate that issue:

Traditionally only ASCII characters have been allowed in email addresses. With the introduction of internationalized domain names (IDNs), non-ASCII characters may appear in the domain name. By default, Swiftmailer encodes such domain names in Punycode (e.g. xn--xample-ova.invalid). This is compatible with all mail servers.

RFC 6531 introduced an SMTP extension, SMTPUTF8, that allows non-ASCII characters in email addresses on both sides of the @ sign. To send to such addresses, your outbound SMTP server must support the SMTPUTF8 extension. You should use the Swift_AddressEncoder_Utf8AddressEncoder address encoder and enable the Swift_Transport_Esmtp_SmtpUtf8Handler SMTP extension handler:

$smtpUtf8 = new Swift_Transport_Esmtp_SmtpUtf8Handler();
$transport->setExtensionHandlers([$smtpUtf8]);
$utf8Encoder = new Swift_AddressEncoder_Utf8AddressEncoder();
$transport->setAddressEncoder($utf8Encoder);

However, even with those ammendments, issue still exists. It is related with some other dependency (Swift_Mime_SimpleHeaderFactory). I've raised that issue on Swiftmailer's Github (https://github.com/swiftmailer/swiftmailer/issues/898#issuecomment-503434250).

Question is: should we wait and see how Swiftmailer handles that or should we add a bypass and fix that issue on Laravel side until it is resolved in vendor?

danielbehrendt commented 3 years ago

This is still an issue. @golonix did you find a way to handle this in Laravel?

golonix commented 3 years ago

@danielbehrendt yes, I have a workaround for this. You need to redefine some of the dependencies in Swift DI container. In your AppServiceProvider::boot() (or in fact in any registered SP, but in the boot method), put:

\Swift_DependencyContainer::getInstance()
    ->register('transport.smtp')
    ->asNewInstanceOf('Swift_Transport_EsmtpTransport')
    ->withDependencies([
        'transport.buffer',
        'transport.smtphandlers',
        'transport.eventdispatcher',
        'transport.localdomain',
        'address.utf8addressencoder', // this is changed in relation to original definition
    ])

    ->register('transport.smtphandlers')
    ->asArray()
    ->withDependencies([
        'transport.authhandler',
        'transport.smtputf8handler', // this is added in relation to original definition
    ])

    ->register('mime.headerfactory')
    ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory')
    ->withDependencies([
        'mime.qpheaderencoder',
        'mime.rfc2231encoder',
        'email.validator',
        'properties.charset',
        'address.utf8addressencoder', // this is changed in relation to original definition
    ]);

With this you will be able to send a message to an email with non-ascii chars in the local part of the address, for example: Dörte@Sörensen.example.com.

But again, this is a workaround (maybe even not the best), not a solution for the problem. However, I hope it helps, at least for the time being.