防止 SendGrid 消息中出现重复的电子邮件地址?

Prevent duplicate email addresses in SendGrid message?

使用 SendGrid for C# library 和 SendGrid API v3,如果您不小心两次包含相同的电子邮件地址,将导致电子邮件根本无法发送。

根据 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.

例如:

        var msg = new SendGridMessage();
        msg.AddTo("test@example.com");
        msg.AddBcc("test@example.com"); // duplicate email address, nothing will be sent

在发送电子邮件之前,我想检查 SendGrid Personalizations 并删除任何重复的电子邮件。

这是我目前的代码:

        var msg = new SendGridMessage();
        msg.AddTo("test@example.com");
        msg.AddBcc("test@example.com"); //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)
            {

            }
        }

我一直在寻找将重复电子邮件地址减少到一个唯一地址的最佳方法。有没有人找到一个很好的方法来强制使用 SendGrid 没有重复的电子邮件地址?

最好不要添加它们,方法是维护一个包含您已添加的所有电子邮件的列表,从“收件人”列表开始。如果你做不到,你必须在事后删除它们,创建上面的超级列表,然后通过 CC 和 BCC 删除已经在超级列表中的那些。

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);
   }
}

如果您想使用上面的代码来完成此操作,则在获得重复项列表后,您必须 foreach 每个 p.Tosp.CCs 等。然后检查当前 EmailAddress 的重复项列表。如果它是重复的,则将其从列表中删除。您永远不必检查 To 列表,因为您总是想要这些。

我认为如果您为他们的 API 构建自己的客户端并在您的实现中执行如下操作,则处理起来会更容易:

var personalization = new Personalization();
personalization.To = GetEmailAddresses(emails);
personalization.Cc = GetEmailAddresses(emails, personalization.To);
personalization.Bcc = GetEmailAddresses(emails, personalization.To.Concat(personalization.Cc));

private IEnumerable<EmailAddress> GetEmailAddresses(IEnumerable<string> emails, IEnumerable<EmailAddress> existingReceptients){
    return emails?.Select(email => new EmailAddress{ Email = email })
      .Where(new => existingReceptients?.Any(existing => existing.Email == new.Email) != true);
}