通过 Exchange Online (Office 365) 使用 System.Net.Mail 发送 SMTP 电子邮件

发布于 2024-11-14 01:24:30 字数 1056 浏览 7 评论 0原文

我们正在测试新的 Office 365 beta,我在 Exchange Online 服务上有一个邮件帐户。现在我正在尝试连接一个 LOB 应用程序,该应用程序可以从我的测试帐户发送 smtp 电子邮件。

但是,Exchange 365 平台要求在端口 587 上进行 TLS 加密,并且 System.Net.Mail 的一项“功能”不允许隐式 SSL 加密。

有人设法让 C# 通过这个平台发送邮件吗?

我有以下应该发送邮件的基本代码 - 任何建议将不胜感激。

SmtpClient server = new SmtpClient("ServerAddress");
server.Port = 587;
server.EnableSsl = true;
server.Credentials = new System.Net.NetworkCredential("[email protected]", "password");
server.Timeout = 5000;
server.UseDefaultCredentials = false;

MailMessage mail = new MailMessage();
mail.From = new MailAddress("recipent@anyaddress");
mail.To.Add("[email protected]");
mail.Subject = "test out message sending";
mail.Body = "this is my message body";
mail.IsBodyHtml = true;

server.Send(mail);

We are testing the new Office 365 beta, and i have a mail account on the Exchange Online service. Now I'm trying to connect a LOB application that can send smtp emails from my test account.

However the Exchange 365 platform requires TLS encryption on port 587, and there is a 'feature' of System.Net.Mail that does not permit Implicit SSL encryption.

Has anyone managed to get C# sending mails via this platform?

I have the following basic code that should send the mail - any advice would be appreciated.

SmtpClient server = new SmtpClient("ServerAddress");
server.Port = 587;
server.EnableSsl = true;
server.Credentials = new System.Net.NetworkCredential("[email protected]", "password");
server.Timeout = 5000;
server.UseDefaultCredentials = false;

MailMessage mail = new MailMessage();
mail.From = new MailAddress("recipent@anyaddress");
mail.To.Add("[email protected]");
mail.Subject = "test out message sending";
mail.Body = "this is my message body";
mail.IsBodyHtml = true;

server.Send(mail);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

撞了怀 2024-11-21 01:24:30

修复了上面工作代码中的一些拼写错误:

MailMessage msg = new MailMessage();
msg.To.Add(new MailAddress("[email protected]", "SomeOne"));
msg.From = new MailAddress("[email protected]", "You");
msg.Subject = "This is a Test Mail";
msg.Body = "This is a test message using Exchange OnLine";
msg.IsBodyHtml = true;

SmtpClient client = new SmtpClient();
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("your user name", "your password");
client.Port = 587; // You can use Port 25 if 587 is blocked (mine is!)
client.Host = "smtp.office365.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
try
{
    client.Send(msg);
    lblText.Text = "Message Sent Succesfully";
}
catch (Exception ex)
{
    lblText.Text = ex.ToString();
}

我有两个使用上面代码的 Web 应用程序,并且都工作正常,没有任何问题。

Fixed a few typos in the working code above:

MailMessage msg = new MailMessage();
msg.To.Add(new MailAddress("[email protected]", "SomeOne"));
msg.From = new MailAddress("[email protected]", "You");
msg.Subject = "This is a Test Mail";
msg.Body = "This is a test message using Exchange OnLine";
msg.IsBodyHtml = true;

SmtpClient client = new SmtpClient();
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("your user name", "your password");
client.Port = 587; // You can use Port 25 if 587 is blocked (mine is!)
client.Host = "smtp.office365.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
try
{
    client.Send(msg);
    lblText.Text = "Message Sent Succesfully";
}
catch (Exception ex)
{
    lblText.Text = ex.ToString();
}

I have two web applications using the above code and both work fine without any trouble.

栖竹 2024-11-21 01:24:30

在 2020 年,这些代码似乎返回异常为

System.Net.Mail.SmtpStatusCode.MustIssueStartTlsFirstThe SMTP 服务器需要安全连接或客户端未经身份验证。服务器响应为:5.7.57 SMTP;客户端未经过身份验证,无法在 MAIL FROM 期间发送匿名邮件

此代码对我有用。

            using (SmtpClient client = new SmtpClient()
            {
                Host = "smtp.office365.com",
                Port = 587,
                UseDefaultCredentials = false, // This require to be before setting Credentials property
                DeliveryMethod = SmtpDeliveryMethod.Network,
                Credentials = new NetworkCredential("[email protected]", "password"), // you must give a full email address for authentication 
                TargetName = "STARTTLS/smtp.office365.com", // Set to avoid MustIssueStartTlsFirst exception
                EnableSsl = true // Set to avoid secure connection exception
            })
            {

                MailMessage message = new MailMessage()
                {
                    From = new MailAddress("[email protected]"), // sender must be a full email address
                    Subject = subject,
                    IsBodyHtml = true,
                    Body = "<h1>Hello World</h1>",
                    BodyEncoding = System.Text.Encoding.UTF8,
                    SubjectEncoding = System.Text.Encoding.UTF8,

                };
                var toAddresses = recipients.Split(',');
                foreach (var to in toAddresses)
                {
                    message.To.Add(to.Trim());
                }

                try
                {
                    client.Send(message);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

In year of 2020, these code seems to return exception as

System.Net.Mail.SmtpStatusCode.MustIssueStartTlsFirst or The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM

This code is working for me.

            using (SmtpClient client = new SmtpClient()
            {
                Host = "smtp.office365.com",
                Port = 587,
                UseDefaultCredentials = false, // This require to be before setting Credentials property
                DeliveryMethod = SmtpDeliveryMethod.Network,
                Credentials = new NetworkCredential("[email protected]", "password"), // you must give a full email address for authentication 
                TargetName = "STARTTLS/smtp.office365.com", // Set to avoid MustIssueStartTlsFirst exception
                EnableSsl = true // Set to avoid secure connection exception
            })
            {

                MailMessage message = new MailMessage()
                {
                    From = new MailAddress("[email protected]"), // sender must be a full email address
                    Subject = subject,
                    IsBodyHtml = true,
                    Body = "<h1>Hello World</h1>",
                    BodyEncoding = System.Text.Encoding.UTF8,
                    SubjectEncoding = System.Text.Encoding.UTF8,

                };
                var toAddresses = recipients.Split(',');
                foreach (var to in toAddresses)
                {
                    message.To.Add(to.Trim());
                }

                try
                {
                    client.Send(message);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
ら栖息 2024-11-21 01:24:30

快速回答:FROM 地址必须与您发送邮件的帐户完全匹配,否则您将收到错误 5.7.1 客户端无权作为此发件人发送。

我的猜测是,这可以防止您的 Office 365 帐户进行电子邮件欺骗,否则您可能可以发送为 [电子邮件受保护]

另一件要尝试的事情是在身份验证中,在第三个字段中填写域,例如

Dim smtpAuth = New System.Net.NetworkCredential(
    "TheDude", "hunter2password", "MicrosoftOffice365Domain.com")

如果这不起作用,请仔细检查您是否可以登录到帐户:https://portal.microsoftonline.com

另一件需要注意的是,您的防病毒解决方案可能会作为反垃圾邮件解决方案阻止对端口 25 和 587 的编程访问。诺顿和迈克菲可能会默默地阻止对这些端口的访问。只有启用 Mail 和 Socket 调试才能让您注意到它(见下文)。

最后要注意的一点是,Send 方法是异步。如果你打电话

Dispose

immediately after you call send, your are more than likely closing your connection before the mail is sent. Have your smtpClient instance listen for the OnSendCompleted event, and call dispose from there. You must use SendAsync method instead, the Send method does not raise this event.


详细答案:使用 Visual Studio(VB.NET 或 C# 无关紧要),我制作了一个简单的表单,其中包含一个创建邮件消息的按钮,与上面的类似。然后我将其添加到 application.exe.config (在我的项目的 bin/debug 目录中)。这使得“输出”选项卡能够具有详细的调试信息。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.diagnostics>
        <sources>
            <source name="System.Net">
                <listeners>
                    <add name="System.Net" />
                </listeners>
            </source>
            <source name="System.Net.Sockets">
                <listeners>
                    <add name="System.Net" />
                </listeners>
            </source>
        </sources>
        <switches>
            <add name="System.Net" value="Verbose" />
            <add name="System.Net.Sockets" value="Verbose" />
        </switches>
        <sharedListeners>
            <add name="System.Net"
              type="System.Diagnostics.TextWriterTraceListener"
              initializeData="System.Net.log"
            />
        </sharedListeners>
        <trace autoflush="true" />
    </system.diagnostics>
</configuration>

Quick answer: the FROM address must exactly match the account you are sending from, or you will get a error 5.7.1 Client does not have permissions to send as this sender.

My guess is that prevents email spoofing with your Office 365 account, otherwise you might be able to send as [email protected].

Another thing to try is in the authentication, fill in the third field with the domain, like

Dim smtpAuth = New System.Net.NetworkCredential(
    "TheDude", "hunter2password", "MicrosoftOffice365Domain.com")

If that doesn't work, double check that you can log into the account at: https://portal.microsoftonline.com

Yet another thing to note is your Antivirus solution may be blocking programmatic access to ports 25 and 587 as a anti-spamming solution. Norton and McAfee may silently block access to these ports. Only enabling Mail and Socket debugging will allow you to notice it (see below).

One last thing to note, the Send method is Asynchronous. If you call

Dispose

immediately after you call send, your are more than likely closing your connection before the mail is sent. Have your smtpClient instance listen for the OnSendCompleted event, and call dispose from there. You must use SendAsync method instead, the Send method does not raise this event.


Detailed Answer: With Visual Studio (VB.NET or C# doesn't matter), I made a simple form with a button that created the Mail Message, similar to that above. Then I added this to the application.exe.config (in the bin/debug directory of my project). This enables the Output tab to have detailed debug info.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.diagnostics>
        <sources>
            <source name="System.Net">
                <listeners>
                    <add name="System.Net" />
                </listeners>
            </source>
            <source name="System.Net.Sockets">
                <listeners>
                    <add name="System.Net" />
                </listeners>
            </source>
        </sources>
        <switches>
            <add name="System.Net" value="Verbose" />
            <add name="System.Net.Sockets" value="Verbose" />
        </switches>
        <sharedListeners>
            <add name="System.Net"
              type="System.Diagnostics.TextWriterTraceListener"
              initializeData="System.Net.log"
            />
        </sharedListeners>
        <trace autoflush="true" />
    </system.diagnostics>
</configuration>
沉鱼一梦 2024-11-21 01:24:30

Office 365使用两台服务器,smtp服务器和保护扩展服务器。

第一个服务器是 smtp.office365.com(smtp 客户端的属性 Host),第二个服务器是 STARTTLS/smtp.office365.com(smtp 客户端的属性 TargetName)。另一件事是必须在设置网络凭据之前放置 Usedefaultcredential =false 。

client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("[email protected]", "Password");
client.Host = "smtp.office365.com";
client.EnableSsl = true;
client.TargetName = "STARTTLS/smtp.office365.com";
client.Port = 587;

client.Send(mail);

Office 365 use two servers, smtp server and protect extended sever.

First server is smtp.office365.com (property Host of smtp client) and second server is STARTTLS/smtp.office365.com (property TargetName of smtp client). Another thing is must put Usedefaultcredential =false before set networkcredentials.

client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("[email protected]", "Password");
client.Host = "smtp.office365.com";
client.EnableSsl = true;
client.TargetName = "STARTTLS/smtp.office365.com";
client.Port = 587;

client.Send(mail);
信愁 2024-11-21 01:24:30

你见过这个吗?
使用 Smtp.mail.microsoftonline.com 发送电子邮件

设置 Credentials 之后设置 UseDefaultCredentials 将重置您的 Credentials 属性。

Have you seen this?
Sending email using Smtp.mail.microsoftonline.com

Setting the UseDefaultCredentials after setting the Credentials would be resetting your Credentials property.

你与清晨阳光 2024-11-21 01:24:30

我已经将用于处理 smtp.google.com:587 的 C# 代码移植到通过 Office365 工作,但没有成功。尝试了使用 Ssl 之前/之后的所有凭据组合以及互联网上提出的几乎所有建议 - 没有成功(出现 5.7.1 .... 错误)。

终于在 .Send(message) 之前从某个地方得到了这一行作为最后的手段,

smtpClient.TargetName = "STARTTLS/smtp.office365.com";

从那时起 - 每个 send() 都取得了巨大的成功。

I've ported c# code used to work against smtp.google.com:587 to work via office365 without success. Tried all combinations of Credential before/after using Ssl and almost every recommendation made on the Internet - w/o success (got 5.7.1 .... error).

Finally got this line from somewhere as last resort, just before .Send(message)

smtpClient.TargetName = "STARTTLS/smtp.office365.com";

Since then - every send() is big success.

心作怪 2024-11-21 01:24:30

对于一些可能正在此线程中搜索此问题答案的人来说,这是一个旁注。 (在实施此解决方案之前,请务必阅读底部的警告。)我在为我的 MS Office 365 订阅没有用户或域的客户发送电子邮件时遇到问题。我尝试通过我的[电子邮件受保护] 365 帐户,但 .NET 邮件消息是从 [电子邮件受保护] 发送的。这是当我弹出“5.7.1客户端没有权限”错误时。为了补救,MailMessage 类需要将 Sender 属性设置为我提供的 SMTP 凭据在 O365 中具有“发送为”权限的电子邮件地址。我选择使用我的主帐户电子邮件 ([电子邮件受保护] ),如下面的代码所示。请记住,我可以使用我的 O365 帐户有权“发送为”的任何电子邮件地址(即 [电子邮件受保护][电子邮件受保护],等)

using System;
using System.Net.Mail;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
         using (
            MailMessage message = new MailMessage
            {
               To = { new MailAddress("[email protected]", "Recipient 1") },
               Sender = new MailAddress("[email protected]", "Me"),
               From = new MailAddress("[email protected]", "Client"),
               Subject=".net Testing"
               Body="Testing .net emailing",
               IsBodyHtml=true,
            }
         )
         {
            using (
               SmtpClient smtp = new SmtpClient
               {
                  Host = "smtp.office365.com",
                  Port = 587,
                  Credentials = new System.Net.NetworkCredential("[email protected]", "Pa55w0rd"),
                  EnableSsl = true
               }
            )
            {
               try { smtp.Send(message); }
               catch (Exception excp)
               {
                  Console.Write(excp.Message);
                  Console.ReadKey();
               }
            }
         }
      }
   }
}

请注意,SmtpClient 是一次性的,并且能够使用 .NET Framework 4 中的 using 块
.NET Framework 2 到 3.5 的用户应使用 SmtpClient...

SmtpClient smtp = new SmtpClient
{
   Host = "smtp.office365.com",
   Port = 587,
   Credentials = new System.Net.NetworkCredential("[email protected]", "Pa55w0rd"),
   EnableSsl = true
};
try { smtp.Send(message); }
catch (Exception excp)
{
   Console.Write(excp.Message);
   Console.ReadKey();
}

生成的电子邮件标头将如下所示:

Authentication-Results: spf=none (sender IP is )  
   [email protected];  
Received: from MyPC (192.168.1.1) by  
   BLUPR13MB0036.namprd13.prod.outlook.com (10.161.123.150) with Microsoft SMTP  
   Server (TLS) id 15.1.318.9; Mon, 9 Nov 2015 16:06:58 +0000  
MIME-Version: 1.0  
From: Client <[email protected]>  
Sender: Me <[email protected]>  
To: Recipient 1 <[email protected]>  

-- 小心 --
请注意,某些邮件客户端可能会将发件人地址显示为注释。例如,Outlook 将在阅读窗格的标题中显示以下内容:

[电子邮件受保护]>代表客户[电子邮件受保护]>

但是,只要收件人使用的电子邮件客户端不是完全垃圾,这就不应该影响回复地址。回复应仍使用发件人地址。为了涵盖所有基础,您还可以利用 MailMessage.ReplyToList 属性为客户端提供使用正确回复地址的一切机会。

另外,请注意,某些电子邮件服务器可能会直接拒绝代表其他公司站点发送的任何电子邮件,这些网站具有域所有者策略限制。请务必彻底测试并寻找任何反弹。我可以告诉您,我的个人 Hotmail (mail.live.com) 电子邮件帐户会拒绝我代表某个客户发送的邮件,但其他客户则可以正常处理。尽管我怀疑它与我客户的域 TXT“spf1”记录有关,但我不知道为什么它会拒绝代表一个域而不是另一个域发送的电子邮件。也许有了解的人可以解释一下这个问题吗?

Here is a side note for some that may be searching this thread for an answer to this problem. (Be sure to read cautions at the bottom before implementing this solution.) I was having trouble sending emails for a client to which my MS Office 365 subscription did not have a user or domain for. I was trying to SMTP through my [email protected] 365 account but the .NET mail message was addressed from [email protected]. This is when the "5.7.1 Client does not have permissions" error popped up for me. To remedy, the MailMessage class needed to have the Sender property set to an email address that my supplied SMTP credentials had permission in O365 to "Send As". I chose to use my main account email ([email protected]) as seen in the code below. Keep in mind I could have used ANY email address my O365 account had permission to "send as" (i.e. [email protected], [email protected], etc.)

using System;
using System.Net.Mail;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
         using (
            MailMessage message = new MailMessage
            {
               To = { new MailAddress("[email protected]", "Recipient 1") },
               Sender = new MailAddress("[email protected]", "Me"),
               From = new MailAddress("[email protected]", "Client"),
               Subject=".net Testing"
               Body="Testing .net emailing",
               IsBodyHtml=true,
            }
         )
         {
            using (
               SmtpClient smtp = new SmtpClient
               {
                  Host = "smtp.office365.com",
                  Port = 587,
                  Credentials = new System.Net.NetworkCredential("[email protected]", "Pa55w0rd"),
                  EnableSsl = true
               }
            )
            {
               try { smtp.Send(message); }
               catch (Exception excp)
               {
                  Console.Write(excp.Message);
                  Console.ReadKey();
               }
            }
         }
      }
   }
}

Please note SmtpClient is only disposable and able to use the Using block in .NET Framework 4
Users of .NET Framework 2 through 3.5 should use SmtpClient as such...

SmtpClient smtp = new SmtpClient
{
   Host = "smtp.office365.com",
   Port = 587,
   Credentials = new System.Net.NetworkCredential("[email protected]", "Pa55w0rd"),
   EnableSsl = true
};
try { smtp.Send(message); }
catch (Exception excp)
{
   Console.Write(excp.Message);
   Console.ReadKey();
}

The resulting email's header will look something like this:

Authentication-Results: spf=none (sender IP is )  
   [email protected];  
Received: from MyPC (192.168.1.1) by  
   BLUPR13MB0036.namprd13.prod.outlook.com (10.161.123.150) with Microsoft SMTP  
   Server (TLS) id 15.1.318.9; Mon, 9 Nov 2015 16:06:58 +0000  
MIME-Version: 1.0  
From: Client <[email protected]>  
Sender: Me <[email protected]>  
To: Recipient 1 <[email protected]>  

-- Be Cautious --
Be aware some mail clients may display the Sender address as a note. For example Outlook will display something along these lines in the Reading Pane's header:

Me <[email protected]> on behalf of Client <[email protected]>

However, so long as the email client the recipient uses isn't total garbage, this shouldn't effect the Reply To address. Reply To should still use the From address. To cover all your bases, you can also utilize the MailMessage.ReplyToList property to afford every opportunity to the client to use the correct reply address.

Also, be aware that some email servers may flat out reject any emails that are Sent On Behalf of another company siting Domain Owner Policy Restrictions. Be sure to test thoroughly and look for any bounce backs. I can tell you that my personal Hotmail (mail.live.com) email account is one that will reject messages I send on behalf of a certain client of mine but others clients go through fine. Although I suspect that it has something to do with my client's domain TXT "spf1" records, I do not have an answer as to why it will reject emails sent on behalf of one domain versus another. Maybe someone who knows can shed some light on the subject?

眼波传意 2024-11-21 01:24:30

我的工作与:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

I got mine working with:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
彩虹直至黑白 2024-11-21 01:24:30

2023 年 2 月:

这是两年内我第二次必须查看有关此主题的所有问答,对我来说,这是第二次解决方案是禁用安全默认值 在 AD 中以启用 SMTP 身份验证。

如果您仍然遇到这些问题:

  1. 转到Azure并切换到您的目录
  2. 选择Active Directory --> 属性
  3. 在底部,点击“管理安全默认值
  4. 禁用并保存。

给它几分钟,然后再次尝试您的代码,如果您按照说明和所有 SO 问题进行操作,那么它现在应该可以工作......并且,请注意您的安全配置。

我希望它有帮助

FEB/2023:

It is the second time in two years that I have to review all Q&A regarding this topic and it is the second time that for me the solution is to disable Security Defaults in AD in order to enable SMTP auth.

If you still have these problems:

  1. Go to Azure and switch to your directory
  2. Select Active Directory --> Properties
  3. At the bottom, click on "Manage security defaults"
  4. Disable it and save.

Give it a couple of minutes and try your code again, if you followed the instructions and all SO questions then it should work now... And, please, take care about your security configuration.

I hope it helps

故事与诗 2024-11-21 01:24:30

最后,有效!

smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = credentials; 之后
然后问题就解决了!

            SmtpClient smtpClient = new SmtpClient(smtpServerName);                          
            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(smtpUName, smtpUNamePwd);

            smtpClient.Credentials = credentials;
            smtpClient.UseDefaultCredentials = false;  <-- Set This Line After Credentials

            smtpClient.Send(mailMsg);
            smtpClient = null;
            mailMsg.Dispose();

Finally, Works!

Put smtpClient.UseDefaultCredentials = false;
after smtpClient.Credentials = credentials;
then problem resolved!

            SmtpClient smtpClient = new SmtpClient(smtpServerName);                          
            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(smtpUName, smtpUNamePwd);

            smtpClient.Credentials = credentials;
            smtpClient.UseDefaultCredentials = false;  <-- Set This Line After Credentials

            smtpClient.Send(mailMsg);
            smtpClient = null;
            mailMsg.Dispose();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文