Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mail customization callbacks are invoked too late #22982

Closed
Alexander-- opened this issue Feb 1, 2018 · 2 comments
Closed

Mail customization callbacks are invoked too late #22982

Alexander-- opened this issue Feb 1, 2018 · 2 comments

Comments

@Alexander--
Copy link
Contributor

  • Laravel Version: 5.5
  • PHP Version: 7

Description:

I am trying to customize the way Laravel composes my email messages. For example, I'd like to encode the message and embedded text files with base64 (because default quoted-printable encoding wastes too much space with non-ascii text).

Unfortunately, Laravel/Illuminate hooks for customizing SwiftMessage are applied too late, after many properties of message are set in stone.

Steps To Reproduce:

I have extended the Mailable class:

class BaseMessage extends Mailable
{
    public function build() {
        return $this
            ->withSwiftMessage(function(\Swift_Message $msg) {
                $msg->setEncoder(new \Swift_Mime_ContentEncoder_Base64ContentEncoder());
            });
            ->view('_mail.sample_email');
    }
}

Unfortunately, the code above does not accomplish anything (the non-ascii parts of mail are still encoded with quoted-printable).

Quick research shows, that send function of Mailable is calling runCallbacks after the message is already built.

Here goes a second try: I override send and try to register callbacks as early as possible:

public function send(MailerContract $mailer)
    {
        Container::getInstance()->call([$this, 'build']);

        $this->withSwiftMessage(function(\Swift_Message $msg) {
            $msg->setEncoder(new \Swift_Mime_ContentEncoder_Base64ContentEncoder());
        });

        $mailer->send($this->buildView(), $this->buildViewData(), function ($message) {
            $this
                ->runCallbacks($message)
                ->buildFrom($message)
                ->buildRecipients($message)
                ->buildSubject($message)
                ->buildAttachments($message);
        });
    }

The code above successfully encodes attachments, but primary message body (contained in _mail.sample_email') is still encoded in quoted-printable instead of base64.

This appears to happen because Illuminate\Mail\Mailer calls user-supplied callback after invoking addContent on SwiftMailer message.

Perhaps, I might be able to implement my custom mailer, and/or muck around with internal structure of SwiftMessages but that's way too much setup to customize few emails.

Seems like the ability to customize emails is more or less broken, so maybe there is no harm in changing the code to invoke call_user_func a couple lines earlier.

@themsaid
Copy link
Member

themsaid commented Feb 1, 2018

Feel free to open a PR with your suggested changes, however as far as I understand this might be a breaking change so you'd need to target 5.6

@themsaid themsaid closed this as completed Feb 1, 2018
@themsaid
Copy link
Member

themsaid commented Feb 1, 2018

Closing since it's not a bug but rather a feature/enhancement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants