Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Mailer] [Sendgrid] Add template support #41714

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

Conversation

OskarStark
Copy link
Contributor

@OskarStark OskarStark commented Jun 15, 2021

Q A
Branch? 5.4
Bug fix? no
New feature? yes
Deprecations? no
Tickets ---
License MIT
Doc PR TODO

Documentation: https://sendgrid.com/docs/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates/#send-a-transactional-email

You can now do the following:

$email = new Email();
$email->addTo($'[email protected]');
$email->text('text');
$email->html('<html></html>');
$email->getHeaders()->addTextHeader('X-Template-ID', 'd-0aac27809ad64ae98d5ebaf896e58b33');
$email->getHeaders()->addTextHeader('X-Dynamic-Template-Data', json_encode(['price' => '42 €']));

I am however not sure about the json_encode/json_decode for handling an array, any proposal?
I also tried to use sth. like:

$email->getHeader->addArrayHeader('X-Dynamic-Template-Data', ['price' => '42 €']);

but I am not sure about the spec and if I am allowed to add a new kind of header to the Mime component 🤔

Note that you need to add sth. like:

$email->text('text');
$email->html('<html></html>');

otherwise you will receive an exception:
CleanShot 2021-06-15 at 13 49 46@2x

@stof
Copy link
Member

stof commented Jun 15, 2021

I'm not sure we want to add this to the component. The code you write is strongly tied to the Sendgrid mailer and would break when using another transport.

@OskarStark
Copy link
Contributor Author

I'm not sure we want to add this to the component. The code you write is strongly tied to the Sendgrid mailer and would break when using another transport.

What do you mean, I only set headers on a mime email, so it would not break with other transports. The headers are then only interpreted by the SendgridApiTransport 🤷‍♂️

@OskarStark OskarStark changed the title [Mailer] Add Sendgrid template support [Mailer] [Sendgrid] Add template support Jun 15, 2021
@stof
Copy link
Member

stof commented Jun 15, 2021

@OskarStark but the code you wrote in your PR description would not work if you configure the mailer with another transport (it would send an email with <html></html> as content, which will be consider a bug by any product manager in the world).

@OskarStark
Copy link
Contributor Author

OskarStark commented Jun 15, 2021

In this case documenting it and tell the people to write valid text and html content as fallback?
I mean if I send an html mail and no text fallback the output would be very bad in a text email client, but the mail is send and received.... not sure about your concerns, while I definitely agree with:

it would send an email with as content, which will be consider a bug by any product manager in the world

Another case about headers, if I can set x-sg-eid on transport A, it is not allowed to be overwritten by transport B, in this case Sendgrid, which will end up in different results, too:

// these headers can't be overwritten according to Sendgrid docs
// see https://sendgrid.api-docs.io/v3.0/mail-send/mail-send-errors#-Headers-Errors
$headersToBypass = ['x-sg-id', 'x-sg-eid', 'received', 'dkim-signature', 'content-transfer-encoding', 'from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'reply-to'];
foreach ($email->getHeaders()->all() as $name => $header) {
if (\in_array($name, $headersToBypass, true)) {
continue;
}

@OskarStark
Copy link
Contributor Author

What about adding

$email->setNoContent(true)

to explicitly mark this email without content?

@stof
Copy link
Member

stof commented Jun 15, 2021

In this case documenting it and tell the people to write valid text and html content as fallback?

but if they write the HTML and text body in their app, there is no point using a sendgrid template managing that content on sendgrid (it might even be worse if they get out of sync)

to explicitly mark this email without content?

that would still make your code work properly only with the SendgridTransport, by adding features in that transport that bypass the component abstraction.

@OskarStark
Copy link
Contributor Author

but if they write the HTML and text body in their app, there is no point using a sendgrid template managing that content on sendgrid (it might even be worse if they get out of sync)

I agree

that would still make your code work properly only with the SendgridTransport, by adding features in that transport that bypass the component abstraction.

But it would make clear to the developer that it can be used across transports but without content IF the other transport does not understand that header.

I mean what would be the solution? Our Mailer cannot support such things? Abstractions are nice, but always limit the power to the lowest feature set 🤷 Thats why I wanted to work around this limitation using a common way of dealing with custom things: headers.

@stof
Copy link
Member

stof commented Jun 15, 2021

@OskarStark to me, email templates are not something you can abstract easily. Some provider maintain templates in their own system with a parameter in the API call (as done by Sendgrid) or with a separate API endpoint. Others are using the email body as template source, with a different syntax each for the templating language.

And some of the features of the components are also incompatible with that (using the DkimSigner on an email which will have its content replaced on the provider server when applying the template won't work for instance).

@OskarStark
Copy link
Contributor Author

I agree, this is just my first idea on how to implement it.

Any advice how this can be done? I am open for ideas to extend the Symfony mailer ecosystem this way.

@OskarStark
Copy link
Contributor Author

OskarStark commented Jun 16, 2021

Btw. isn't this the same problem we currently have with options in Notifier? I can create a ChatMessage, but in case I add TelegramOptions to this ChatMessage it cannot be send by another transport anymore.

/**
* @see https://core.telegram.org/bots/api
*/
protected function doSend(MessageInterface $message): SentMessage
{
if (!$message instanceof ChatMessage) {
throw new UnsupportedMessageTypeException(__CLASS__, ChatMessage::class, $message);
}
if ($message->getOptions() && !$message->getOptions() instanceof TelegramOptions) {
throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, TelegramOptions::class));
}

And if we would remove the options check we would only send the plain message via another transport, but additional tied information, which are located in the options, would be ignored by another transport.

@fabpot
Copy link
Member

fabpot commented Jun 17, 2021

As I mentioned in some other issues/PRs, I'm against supporting specific features of each mailer. The main goal of the component is to be able to switch from one provider to another one or been mix them (round-robin). If we find an abstraction that would work for the vast majority of the current providers, why not, but having specific features is a no-go for me.

@OskarStark
Copy link
Contributor Author

Fine, but we currently do the same thing with options, if I add some kind of Options to a ChatMessage, I cannot use it with any other transport.

@OskarStark OskarStark closed this Jun 17, 2021
@OskarStark OskarStark deleted the feature/sendgrid-api-transport-template-id branch June 17, 2021 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants