C# 将一个收件人添加到MailMessage但将标题添加到电子邮件客户端查看所有收件人

C# 将一个收件人添加到MailMessage但将标题添加到电子邮件客户端查看所有收件人,c#,email,smtp,C#,Email,Smtp,我目前正在从事一个C#项目,我正在制作自己的SMTP服务器。这是一个比较少的工作,但我正试图使它的工作,我可以发送电子邮件给多个收件人,在不同的领域 我最初这样做是为了创建一个mailmessage对象,并运行以下命令来添加每个收件人 MailMessage message = new MailMessage(); message.To.add("someone@domain1.com"); message.To.add("someone@domain2.com"); 如果使用不同的域,但通过

我目前正在从事一个C#项目,我正在制作自己的SMTP服务器。这是一个比较少的工作,但我正试图使它的工作,我可以发送电子邮件给多个收件人,在不同的领域

我最初这样做是为了创建一个
mailmessage
对象,并运行以下命令来添加每个收件人

MailMessage message = new MailMessage();
message.To.add("someone@domain1.com");
message.To.add("someone@domain2.com");
如果使用不同的域,但通过google应用程序服务器,我会得到MX记录,它是
ALT2.ASPMX.L.google.COM
。当通过上面的收件人添加发送邮件时,google会发回一个错误,因为他们不允许通过一个SMTP会话进行跨域发送

因此,我对它进行了修改,为每个收件人发送了一封单独的电子邮件,我获得了每个域的MX记录,因此我也使用了不同的SMTP会话。因此,对于我收到的每个收件人,只有一条
消息.To.add
。我想做的是添加一个标题,这样它仍然可以显示电子邮件收件人仍然要
someone@domain1.com
someone@domain2.com

因此,就MailMessage组件而言,只有一个收件人,但邮件头显示多个收件人,因此,当收到的邮件在其客户端中查看电子邮件时,它会显示电子邮件发送到的所有收件人

下面是我必须发送电子邮件的代码

MXLookup mxLookup = new MXLookup();
                    List<string> recipients = addRecipientsToEmail(message.emailRecipients);
                    foreach (string recipient in recipients)
                    {
                        string domain = Classes.CommonTasks.getDomainFromEmail(recipient);
                        string[] mxRecords = mxLookup.getMXRecords(Classes.CommonTasks.getDomainFromEmail(domain));
                        if (mxRecords != null)
                        {
                            MailMessage composedMail = new MailMessage();
                            composedMail.From = new MailAddress(message.EmailFromAddress);
                            composedMail.To.Add(recipient);
                            composedMail.Subject = message.subject;
                            composedMail.Body = message.EmailBody;
                            composedMail.Headers.Add(getHeaders(recipients));

                            if (message.contentType.ToString().Contains("text/html"))
                            {
                                composedMail.IsBodyHtml = true;
                            }

                            SmtpClient smtp = new SmtpClient(mxRecords[0]);
                            smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                            smtp.Port = 25;
                            if (Configuration.emailConfig.useSmtpMaxIdleTime)
                            {
                                smtp.ServicePoint.MaxIdleTime = 1;
                            }
                            library.logging(methodInfo, string.Format("Sending email via MX Record: {0}", mxRecords[0]));
                            smtp.Send(composedMail);
                            updateEmailStatus(message.emailID, EmailStatus.Sent);
                            library.logging(methodInfo, string.Format("Successfully sent email ID: {0}", message.emailID));

                        }

                        else
                        {
                            string error = string.Format("No MX Record found for domain: {0}", domain);
                            library.logging(methodInfo, error);
                            library.setAlarm(error, CommonTasks.AlarmStatus.Warning, methodInfo);
                        }
MXLookup MXLookup=新建MXLookup();
列表收件人=将收件人添加到电子邮件(message.emailRecipients);
foreach(收件人中的字符串收件人)
{
字符串域=Classes.CommonTasks.getDomainFromEmail(收件人);
string[]mxRecords=mxLookup.getMXRecords(Classes.CommonTasks.getDomainFromEmail(domain));
if(mxRecords!=null)
{
MailMessage composedMail=新邮件();
composedMail.From=新邮件地址(message.EmailFromAddress);
composedMail.To.Add(收件人);
composedMail.Subject=message.Subject;
composedMail.Body=message.EmailBody;
Add(getHeaders(recipients));
if(message.contentType.ToString()包含(“text/html”))
{
composedMail.IsBodyHtml=true;
}
SmtpClient smtp=新的SmtpClient(mxRecords[0]);
smtp.DeliveryMethod=SmtpDeliveryMethod.Network;
smtp.Port=25;
if(Configuration.emailConfig.UseSMTMaxidleTime)
{
smtp.ServicePoint.MaxIdleTime=1;
}
logging(methodInfo,string.Format(“通过MX记录发送电子邮件:{0}”,mxRecords[0]);
smtp.Send(composedMail);
updateEmailStatus(message.emailID,EmailStatus.Sent);
logging(methodInfo,string.Format(“已成功发送电子邮件ID:{0}”,message.emailID));
}
其他的
{
string error=string.Format(“没有为域{0}找到MX记录”,域);
日志记录(methodInfo,错误);
library.setAlarm(错误,CommonTasks.AlarmStatus.Warning,methodInfo);
}
下面是我的getHeaders函数

private NameValueCollection getHeaders(List<string> emailRecipients)
{
    string headers = "";
    NameValueCollection headersArray = new NameValueCollection();
    foreach (string recipient in emailRecipients)
    {
        headers += string.Format("{0}, ", recipient);
    }
    headersArray.Add("To", headers);
    return headersArray;
}
private NameValueCollection getHeaders(列出电子邮件收件人)
{
字符串标题=”;
NameValueCollection标头数组=新的NameValueCollection();
foreach(emailRecipients中的字符串收件人)
{
headers+=string.Format(“{0},”,收件人);
}
headersArray.Add(“To”,headers);
返回磁头阵列;
}

感谢您提供的任何帮助。

Boardy,首先,我要说的是,我理解您为什么要使用自己的SMTP服务器而不是中继。我们正在做同样的事情,因为我们需要实时处理电子邮件故障,而不必依赖于死信或NDR。只有在您控制传输通道的情况下,这才是切实可行的

您在这里遇到的问题是,无法将RCPT to命令和“to”头分开。如果您查看wireshark log for Exchange(即,发送如上所述的电子邮件),它将有两个端口25(可能是)会话,一次到域1,另一次到域2。在第一次会话中,RCPT to将someone1@domain1.com标题和标题将是:someone1@domain1.com, somenone2@domain2.com.对于第二个会话,To报头将相同,但RCPT To将为someone2@domain2.com。在.net类中,要集合实际上是RCPT TO,我们似乎无法访问TO标头。当然,如果您尝试这样做并实际添加两个收件人,domain1将为您提供中继错误someone@domain2.com(反之亦然)。理想情况下,我们可以将RCPT集合设置为收件人和收件人(和抄送)集合可以是基于RCPT信息的默认标题包装器,也可以被覆盖。目前,使用.net类无法真正实现您自己的邮件服务器

我已经为此挣扎了几年。最近,随着我们开始使用CC和多Tos,这已经成为一个问题,因此我正在寻找解决方案。目前我正在考虑使用自定义套接字实现或使用Rebex。它们似乎具备我所需的功能,但我不能说我已经让它按我所希望的方式工作。当然,如果有一些很棒的反射技巧(就像我们对FQDN所做的那样)