Search code examples
c#sendgridasp.net-core-2.1sendgrid-api-v3

Prevent duplicate email addresses in SendGrid message?


Using SendGrid for C# library and SendGrid API v3, if you accidentally include the same email address twice, it results in the email not being sent at all.

Per the SendGrid documentation:

All of the recipients in a single personalization object (either in the to, cc, or bcc fields) will see exactly the same email, as defined by the data in that personalization, as such we do not allow duplicate emails between these 3 arrays in a single personalization.

For example:

        var msg = new SendGridMessage();
        msg.AddTo("[email protected]");
        msg.AddBcc("[email protected]"); // duplicate email address, nothing will be sent

Prior to sending emails, I would like to check the SendGrid Personalizations and remove any duplicate emails.

Here's the code I have so far:

        var msg = new SendGridMessage();
        msg.AddTo("[email protected]");
        msg.AddBcc("[email protected]"); //has a duplicate email address, nothing will be sent

        foreach (var p in msg.Personalizations)
        {
            var emails = new List<EmailAddress>();
            emails.AddRange(p.Tos);
            emails.AddRange(p.Ccs);
            emails.AddRange(p.Bccs);

            // find duplicates
            var duplicates = emails.GroupBy(x => x.Email)
                            .Where(g => g.Count() > 1)
                            .Select(y => y.Key)
                            .ToList();

            // remove all but one...
            // remove duplicates from Bccs first, then Ccs, then Tos
            foreach (var d in duplicates)
            {

            }
        }

I'm stuck on the best way to reduce the duplicate email addresses down to one unique one. Has anyone found a good way to enforce having no duplicate email addresses with SendGrid?


Solution

  • It's best to not add them by maintaining a list of all the emails you've already added, starting with the To list. If you can't do that and you have to remove them after the fact, create that uber list above, and then go through the CC and then the BCC removing ones that are already in the uber list.

    var existingEmails = new HashSet<String>();
    
    foreach (String email in MyToList)
    {
       if(!existingEmails.ContainsKey(email)
       {
           msg.AddTo(email);
           existingEmails.Add(email);
       }
    }
    
    foreach (String email in MyCCList)
    {
       if(!existingEmails.ContainsKey(email)
       {
           msg.AddCC(email);
           existingEmails.Add(email);
       }
    }
    
    foreach (String email in MyBCCList)
    {
       if(!existingEmails.ContainsKey(email)
       {
           msg.AddBCC(email);
           existingEmails.Add(email);
       }
    }
    

    If you want to do it with the code you have above you'll have to foreach each of the p.Tos and p.CCs etc. after you obtain the duplicates list. Then check the duplicates list for the current EmailAddress. If it's a duplicate then remove it from the list. You should never have to check the To list as you always want those.