Dynamic template data for multiple recipients
JayCunha opened this issue · comments
Actual Behaviour
Right now, I can only send dynamic template data for one recipient at a time. Example of my code:
{
"personalizations": [
{
"to": [
{
"email": "john.doe@example.com",
"name": "John Doe"
}
],
"dynamic_template_data": {
"firstName": "John",
"lastName": "Doe"
},
"subject": "Hello, World!"
}
],
"from": {
"email": "noreply@johndoe.com",
"name": "John Doe"
},
"reply_to": {
"email": "noreply@johndoe.com",
"name": "John Doe"
},
"template_id": "<<YOUR_TEMPLATE_ID>>"
}
Expected Behaviour
I want to send dynamic template data for each recipient, but I don't know how. The idea is to send personalized e-mails for multiple recipients one at a time, instead of sending emails one by one. I tried to search for an example but I couldn't find it. Do you have any?
Yes, you can send one mail to multiple recipient. I have faced same problem but I have solved the issue. Just use separate personalizations.
Example Json:
{
"personalizations": [
{
"to": [
{
"email": "john.doe@example.com",
"name": "John Doe"
}
],
"dynamic_template_data": {
"firstName": "John",
"lastName": "Doe"
},
"subject": "Hello, World!"
},
{
"to": [
{
"email": "john.doe@example.com",
"name": "John Doe"
}
],
"dynamic_template_data": {
"firstName": "John",
"lastName": "Doe"
},
"subject": "Hello, World!"
}
],
"from": {
"email": "noreply@johndoe.com",
"name": "John Doe"
},
"reply_to": {
"email": "noreply@johndoe.com",
"name": "John Doe"
},
"template_id": "<<YOUR_TEMPLATE_ID>>"
}
Since this issue hasn't been closed, how do I inject my dynamic template data into the model when using the SendGridMessage
object in C#?
var mail = new SendGridMessage
{
Attachments = new List<Attachment>(),
From = new EmailAddress()
{
Email = emailConfig.FromAddress,
Name = emailConfig.FromName
},
TemplateId = EmailConstants.ConfirmationEmailTemplateId,
Subject = subject
};
mail.Personalizations = new List<Personalization>() {
TemplateData = ???
};
For you reference:-
public virtual async Task<bool> SendEmailPersonalized<TValue>(Dictionary<string, string> to, string templateId, Dictionary<string, TValue> templateData, string? fromName = null, string? fromEmail = null)
{
var msg = new SendGridMessage();
msg.SetFrom(new EmailAddress(fromEmail ?? sendGridOptions.FromEmail, fromName ?? sendGridOptions.FromName));
msg.SetTemplateId(templateId);
msg.Personalizations = new List<Personalization>();
foreach (var r in to)
{
msg.Personalizations.Add(new Personalization()
{
Tos = new List<EmailAddress>() { new EmailAddress(r.Key, r.Value) },
TemplateData = templateData[r.Key]
});
}
var response = await sendGridClient.SendEmailAsync(msg);
if (response.StatusCode >= System.Net.HttpStatusCode.OK && response.StatusCode <= System.Net.HttpStatusCode.IMUsed)
{
return true;
}
logger.LogWarning("SendEmail returned a negative status. Response: {@response} for {@to} address. TemplateId: {@templateId}", response, to, templateId);
return false;
}
//-------------------------------
//Caller of above function
//-------------------------------
foreach (var t in alertsList)
{
await _emailService.SendEmailPersonalized(
t.AlertRecipient.ToDictionary(a => a.Email??Notifications.CommonData.Empty_UserEmail_Replacement, a => a.Name??Notifications.CommonData.Empty_UserName_Replacement)
,alertType.TemplateId!
,t.AlertRecipient.ToDictionary(a => a.Email?? Notifications.CommonData.Empty_UserEmail_Replacement, a => new CampaignGoalAchieved
{
DonorName = a.Name??Notifications.CommonData.Empty_UserName_Replacement,
CampaignName = "Test Campaign Name",
CampaignLink = "http://sample.com",
GoalAchieved = "25"
})
, alertType.Sender
, alertType.SenderEmail
);
t.Status = Notifications.AlertStatus.Processed;
await UpdateAlertAsync(_Mapper.Map<Alert, AlertDto>(t));
}
I also had issues with it.
The docs are pretty disappointing :(
What worked for me -
create a separate object for each email. Not using the personalization key.
example:
const yourArrayOfEmails = [{someData: 1, email: 'a@hi.com'}, {someData: 2, email: 'b@hi.com'}]
yourArrayOfEmails.map(emailDetails => {
return {
from: {
email: EMAIL_FROM,
name: EMAIL_NAME,
},
templateId: EMAIL_TEMPLATE_ID,
// dynamic
to: emailDetails.email,
dynamicTemplateData: {
someData: emailDetails.someData,
},
}
})