craigpaul / laravel-postmark

A Postmark adapter for Laravel
MIT License
204 stars 23 forks source link

Use different POSTMARK_SECRET & POSTMARK_SERVER? #149

Open christoph-werker opened 2 months ago

christoph-werker commented 2 months ago

Detailed description

I have software that manages client orders, and depending on the order, I need to use a specific POSTMARK_SECRET and POSTMARK_SERVER. Maybe I overlooked something, but how can I accomplish that?

Your environment

Include as many relevant details about the environment you experienced the bug in and how to reproduce it.

craigpaul commented 2 months ago

Hey @christoph-werker, is this something that was made possible by #134?

christoph-werker commented 2 months ago

Hi @craigpaul ,

That was fast. 💪 Tbo I'm not sure, because I need also to set another API-Key not just the Server-Id.

Furthermore what could be an elegant way to implement this? Without redundant code?

craigpaul commented 2 months ago

@christoph-werker The X-Postmark-Server-Token header is your API key, not the server ID (I'm not actually sure you supply a server ID when sending a transactional email, just the token, which determines the server to use, to my knowledge), but regardless I just realized you had provided the fact that you're on Laravel 8 with v2.11 of this package so that changes things. There isn't a built in way to do that, but I can provide an overview of how I've done it in the past before this existed (fair warning, it's not simple unfortunately).

We started off with creating a custom EmailChannel class that extended the MailChannel from Laravel. In the send method, before we passed it back to the parent to actually send the email, we would update the configuration and re-build the mail manager by re-assigning the $this->mailer dependency. It looks a little something like this at a high level:

$secret = '...'; // your updated secret

config()->set('mail.driver', 'postmark-custom');
config()->set('mail.default', 'postmark-custom');
config()->set('postmark.secret', $secret); // `services.postmark.secret` also works in this version of the package

app('mail.manager')->extend('postmark-custom', function () use ($secret) {
    return new PostmarkTransport(
        app(Factory::class),
        config()->get('mail.mailers.postmark.message_stream_id'),
        [],
        $secret,
    );
});

$this->mailer = app()->make('mail.manager');

The problem with doing this in a long running process like a queue worker/Horizon is that those configuration changes stick around for the next email being sent through that process, so you also need a way to reset $this->mailer back to the default mail driver. Hope that might spark an idea, but if you have further questions let me know.