[SOLVED] SendGrid Dynamic Templates & Meteor Emails

Hi,

I’ve created a basic ‘Dynamic Template’ in SendGrid for email verification. It currently only contains a brief message and a button to click in order to verify the users’ email address.

The button needs to have the URL that Meteor generates in its ‘sendVerificationEmail’ function.

I’m struggling to get Meteor to use the dynamic template instead of Meteor’s default one. I can’t get Meteor to use SendGrid’s templates using Email.send either.

The verification emails send if I assign this header right before calling the Accounts.sendVerificationEmail function, but the email does not use the template that I have created:

Accounts.emailTemplates.headers = {
  "X-SMTPAPI": {
     "filters": {
        "templates": {
            "settings": {
                 "enable": 1,
                 "template_id": "X-XXXXXXXXXXXXXXXXXXX"
            }
         }
      },
      "sub": {
         "{{buttonVerificationLink}}": "https://www.google.com",
         "{{verificationLink}}": "https://www.google.com"
      }
   }
}

Similarly, Email.send will also send an email with this configuration (but will not use the template):

     Email.send({
        from,
        to: 'email@address.com',
        headers: {
          "X-SMTPAPI": {
            "filters": {
              "templates": {
                "settings": {
                  "enable": 1,
                  "template_id": "X-XXXXXXXXXXXXXXXXXXX"
                }
              }
            },
            "sub": {
              "{{buttonVerificationLink}}": "https://www.google.com",
              "{{verificationLink}}": "https://www.google.com" 
            }
          }
        }
      });

What am I missing? Has anyone else managed to get SendGrid’s dynamic templates working with Meteor’s Email package or with the email function (verify, reset password, etc)?

I found a few questions on Meteor & StackOverflow but had no luck with their solutions. Most of them are a few years old.

Small progress:

I can send and receive an email using Meteor’s HTTP package to make an API call to SendGrid. Method 2 on this StackOverflow answer: https://stackoverflow.com/questions/47217847/trigger-sendgrid-template-email-using-meteor.

I can also fill in the variables that I have added into the template (a fake verification link, like www.google.com).

I would be happy with this method if I could figure out to create a custom email verification link. Is that easy to do?

Some answers (like this and the answer it’s referencing) suggest using the Accounts.urls.verifyEmail function, but I cannot find any reference to this in the Meteor docs, so I assume this has been deprecated?

I’ve managed to get a working solution.

I could not get Meteor’s Email.send function to work but I don’t think it’s a Meteor issue / code issue. It seems the emails were getting blocked further down the email chain. Not sure why they were being blocked.

I got it working by using the SendGrid Web API v3 which is Method 2 in this SO answer.

It turns out ‘Accounts.urls.verifyEmail’ is still valid and usable - I just didn’t look hard enough in the docs!

So I use this to create my own token and URL:

        const tokenRecord = {
          token: Random.secret(),
          address: email,
          when: new Date()
        };
        
        Meteor.users.update(userId, {$push: {'services.email.verificationTokens': tokenRecord}});
        
        const verifyEmailUrl = Accounts.urls.verifyEmail(tokenRecord.token);

As mentioned in this answer.

And then I use this code to send the email using the SendGrid API:

  // api_mail_url = "https://api.sendgrid.com/v3/mail/send"
  const endpoint = Meteor.settings.private.sendgrid.api_mail_url; 
  const options = {
    headers: {
      "Authorization": `Bearer ${Meteor.settings.private.sendgrid.api_key}`,
      "Content-Type": "application/json"
    },
    data: {
      personalizations: [
        {
          to: [{
            email: email
          }],
          // these are the variables created in the SendGrid template
          dynamic_template_data: {
            "verificationLink": url
          }
        },
      ],
      from: {
        email: Accounts.emailTemplates.from
      },
      // SendGrid dynamic template ID (get this from your SendGrid portal)
      template_id: Meteor.settings.private.sendgrid.templates.email_verification
    }
  };

  const result = HTTP.post(endpoint, options);