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

问题描述:

我们正在测试新的Office 365测试版,并且我在Exchange Online服务上有一个邮件帐户。现在我试图连接一个可以从我的测试帐户发送smtp电子邮件的LOB应用程序。通过Exchange Online(Office 365)使用System.Net.Mail发送SMTP电子邮件

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

有没有人设法让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("[email protected]"); 
mail.To.Add("[email protected]"); 
mail.Subject = "test out message sending"; 
mail.Body = "this is my message body"; 
mail.IsBodyHtml = true; 

server.Send(mail); 
+2

它给出了什么错误? – BugFinder 2011-06-05 17:51:52

+0

是的你得到一个超时 - 这显然是默认的失败 – 2011-06-06 10:10:34

+0

所以即时通讯开始怀疑这是甚至可能使用C#和System.Net.Mail命名空间通过SSL设置的限制。看起来Exchange有它在Office 365上公开的webservices,很多文章都讨论了如何利用它来处理邮箱等。但是我真的不想将整个邮箱公开给我的LOB应用程序。 SMTP中的'S'代表'简单' - 我不相信微软安装的微软邮件服务器不能与微软的编程语言一起工作。请有人告诉我在这里错过了一些东西! – 2011-06-22 11:07:31

你见过这个吗? Sending email using Smtp.mail.microsoftonline.com

设置凭证后设置UseDefaultCredentials将重置您的凭证属性。

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

我的猜测是,它可以防止用您的Office 365帐户欺骗电子邮件,否则您可能会以[email protected]的身份发送邮件。

另一件事,试图在身份验证,填写带有域的第三场,像

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

如果不工作,仔细检查您可以登录到帐户:https://portal.microsoftonline.com

还有一点要注意的是,您的防病毒解决方案可能会阻止程序化访问端口25和587作为反垃圾邮件解决方案。诺顿和McAfee可能会默默阻止对这些端口的访问。只有启用邮件和套接字调试才能让你注意到它(见下文)。

最后要注意的一点,发送方法是异步。如果您在致电发送后立即致电

Dispose
,则在发送邮件之前,您很可能会关闭连接。让你的smtpClient实例监听OnSendCompleted事件,并从那里调用dispose。您必须改用SendAsync方法,Send方法不会引发此事件。


详细答案:与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> 
+1

我假设'hunter2password'不是你的密码? – rhughes 2014-05-20 06:31:54

+2

呃,是的,那就是对irc meme的那个旧的引用。我的密码是***************。 Src:http://ars.userfriendly.org/cartoons/?id=19990814 – 2014-05-20 17:40:11

+1

如果您将MailMessage.Sender属性添加到O365授权的“代理发送”电子邮件中,MailMessage.From不一定是主要帐户电子邮件地址。有关详细信息,请参阅此主题中的我的文章:http://*.com/a/33613150/2464869 – ShaneLS 2015-11-09 17:16:07

最后,作品!

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

修正了一些错别字在上面的工作代码:

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应用程序,并没有任何麻烦都工作得不错。

+0

您运行的是哪个版本的Office 365。我暂时没有看过这段代码,但是我们正在准备从小型商业计划P1移植到企业计划E1,我想知道我的初始问题是否由我们在P1计划中引起。 – 2013-08-07 16:10:35

+0

不幸的是,此代码不再适用于Office 365。出现的错误消息是SMTP服务器需要安全连接或客户端未通过身份验证。服务器响应是:5.7.57 SMTP;客户端未通过身份验证发送匿名邮件来自[HE1PR05CA0133.eurprd05.prod.outlook.com] – 2018-01-30 00:02:35

我已经移植了c#代码,用于对付smtp.google.com:587以通过office365工作,但没有成功。在使用Ssl之前/之后尝试了所有的Credential组合,以及几乎所有在互联网上提出的建议 - 无法成功(得到5.7.1 ....错误)。

终于得到了这条线从某处作为最后的手段,只是

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

自此之前。发送(消息) - 每发送()是大获成功。

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

第一台服务器是smtp.office365.com(属性是smtp客户端的主机),第二台服务器是STARTTLS/smtp.office365.com(smtp客户端的属性TargetName)。另一件事是必须在设置networkcredentials之前放置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) 
+0

smtp.office365.com是两个以上的服务器。 – 2016-03-02 14:59:09

以下是一些可能在搜索此主题以解答此问题的附注。 (在实施此解决方案之前,请务必阅读底部的注意事项。)我无法为MS Office 365订阅没有用户或域的客户端发送电子邮件。我尝试通过我的[email protected] 365帐户尝试SMTP,但.NET邮件消息的地址是[email protected]。这是当“5.7.1客户端没有权限”错误弹出为我。要解决此问题,MailMessage类需要将发件人属性设置为我提供的SMTP凭据在O365中“发送”的许可权的电子邮件地址。我选择使用我的主帐户电子邮件([email protected]),如下面的代码所示。请记住,我可以使用任何电子邮件地址我O365帐户有权限“发送为”(即[email protected][email protected]等)

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仅仅是一次性的,并且能够使用Using块中的.NET Framework 3.5通过.NET框架2的4
用户应使用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将沿着显示在阅读窗格中的头几行内容:客户名义<客户@ ClientDomain的

我<[email protected]>。com >

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

此外,请注意,某些电子邮件服务器可能会拒绝任何发送代表另一家公司选址域所有者策略限制的电子邮件。一定要彻底测试并寻找任何反弹。我可以告诉你,我个人的Hotmail(mail.live.com)电子邮件帐户是拒绝我代表我的某个客户发送的邮件,但其他客户通过罚款。尽管我怀疑它与我的客户的域名TXT“spf1”记录有关,但我没有回答为什么它会拒绝代表一个域名与另一个域名发送的电子邮件。也许有人知道可以揭示这个问题?

+0

只是一个说明 - 办公室365似乎不喜欢添加发件人标签 – markthewizard1234 2016-11-01 16:09:14