0

私は現在、独自の SMTP サーバーを作成している C# プロジェクトに取り組んでいます。あまり機能していませんが、異なるドメインにある複数の受信者に電子メールを送信できる場所で機能させようとしています。

私は最初にそれを行ったので、MailMesssageオブジェクトを作成し、次を実行して各受信者を追加します

MailMessage message = new MailMessage();
message.To.add("someone@domain1.com");
message.To.add("someone@domain2.com");

異なるドメインがGoogleアプリサーバーを通過する場合、MXレコードはALT2.ASPMX.L.GOOGLE.COM. 上記の受信者を追加してメールを送信すると、1 つの SMTP セッションを介したクロスドメイン送信が許可されていないため、Google はエラーを返します。

したがって、受信者ごとに個別の電子メールが送信されるように作り直しました。各ドメインの MX レコードを取得するため、最終的には異なる SMTP セッションになります。message.To.addしたがって、受信した受信者ごとに 1 つしかありません。私がやろうとしているのは、ヘッダーを追加して、メールの受信者がまだsomeone@domain1.comsomeone@domain2.com.

したがって、MailMessage コンポーネントに関する限り、受信者は 1 人ですが、ヘッダーには複数の受信者が表示されるため、メールの受信者がクライアントで電子メールを表示すると、電子メールが送信されたすべての受信者が表示されます。

以下は、メールを送信するために必要なコードです。

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

以下は私の 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;
}

ご協力いただきありがとうございます。

4

1 に答える 1

1

Boardy、最初に、リレーではなく独自の SMTP サーバーを使用している理由を理解していると言わせてください。メールの失敗をリアルタイムで処理する必要があり、不正メールや NDR に依存する必要がないため、同じことを行っています。これは、伝送チャネルを制御する場合にのみ実用的です。

ここでの問題は、RCPT TO コマンドと「To」ヘッダーを分離する方法がないことです。Exchange の Wireshark ログ (つまり、上記で概説したメールの送信) を見ると、2 つのポート 25 (おそらく) セッションがあり、1 回はドメイン 1 に、もう 1 回はドメイン 2 に送信されます。最初のセッションでは、RCPT TOsomeone1@domain1.comになり、To ヘッダーはTo: someone1@domain1.com, somenone2@domain2.com になります。2 番目のセッションでは、To ヘッダーは同じですが、RCPT TOsomeone2@domain2.comになります。. .net クラスでは、To コレクションは実際には RCPT TO であり、To ヘッダーにアクセスできないようです。もちろん、それを試して実際に両方の受信者を追加すると、 domain1 は someone@domain2.com のリレーエラーを返します (逆も同様です)。理想的には、受信者として設定できる RCPT コレクションがあり、To (および CC) コレクションは、RCPT 情報に基づいてデフォルト設定されるか、オーバーライドできるヘッダー ラッパーにすることができます。現状では、.net クラスを使用して実際に独自のメール サーバーを実装する方法はありません。

私はこれに数年間苦労してきました。CC と複数の Tos を使い始めて最近問題になったので、解決策を探しています。現在、カスタム ソケット実装または Rebex の使用を検討しています。彼らは私が必要とするものを持っているようですが、私が望むようにまだ機能しているとは言えません. もちろん、これをネイティブに機能させるための優れたリフレクション トリック (FQDN の場合など) がある場合は、それを知っておくとよいでしょう。要するに、あなたの質問への答えは AFAIK, can't do thatです。Rebex での経験があれば投稿します。

于 2013-10-30T00:59:52.560 に答える