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

时间:2011-06-05 17:50:05

标签: c# exchange-server office365 sendmail system.net.mail

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

但是,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("username@mydomain.com", "password");
server.Timeout = 5000;
server.UseDefaultCredentials = false;

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

server.Send(mail);

8 个答案:

答案 0 :(得分:45)

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

MailMessage msg = new MailMessage();
msg.To.Add(new MailAddress("someone@somedomain.com", "SomeOne"));
msg.From = new MailAddress("you@yourdomain.com", "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应用程序,两者都可以正常运行。

答案 1 :(得分:11)

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

我的猜测是阻止使用您的Office 365帐户进行电子邮件欺骗,否则您可以发送为sballmer@microsoft.com。

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

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

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

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

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

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>

答案 2 :(得分:9)

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

System.Net.Mail.SmtpStatusCode.MustIssueStartTlsFirst 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("alias@fulldomain.com", "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("alias@fulldomain.com"), // 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);
                }
            }

答案 3 :(得分:6)

你看到了这个吗? Sending email using Smtp.mail.microsoftonline.com

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

答案 4 :(得分:5)

这是一些可能正在搜索此主题以获得此问题的答案的旁注。 (在实施此解决方案之前,请务必阅读底部的注意事项。)我无法为我的MS Office 365订阅没有用户或域的客户端发送电子邮件。我尝试通过 Me@MyDomain.com 365帐户进行SMTP,但.NET邮件是从 Client@ClientDomain.com 发送的。这是为我弹出“5.7.1客户端没有权限”错误的时候。要解决此问题, MailMessage 类需要将发件人属性设置为我提供的SMTP凭据在O365中具有“发送为”权限的电子邮件地址。我选择使用我的主帐户电子邮件( Me@MyDomain.com ),如下面的代码所示。请记住,我可以使用任何电子邮件地址,我的O365帐户有权“发送”(即Support@MyDomain.com,no-reply @ MyDomain.com等)

using System;
using System.Net.Mail;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
         using (
            MailMessage message = new MailMessage
            {
               To = { new MailAddress("Recipient1@Recipient1Domain.com", "Recipient 1") },
               Sender = new MailAddress("Me@MyDomain.com", "Me"),
               From = new MailAddress("Client@ClientDomain.com", "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("Me@MyDomain.com", "Pa55w0rd"),
                  EnableSsl = true
               }
            )
            {
               try { smtp.Send(message); }
               catch (Exception excp)
               {
                  Console.Write(excp.Message);
                  Console.ReadKey();
               }
            }
         }
      }
   }
}

请注意,SmtpClient只是一次性的,可以使用.NET Framework 4中的使用块
.NET Framework 2到3.5的用户应该使用SmtpClient ......

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

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

Authentication-Results: spf=none (sender IP is )  
   smtp.mailfrom=Me@MyDomain.com;  
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 <Client@ClientDomain.com>  
Sender: Me <Me@MyDomain.com>  
To: Recipient 1 <Recipient1@Recipient1Domain.com>  

- 谨慎 -
请注意,某些邮件客户端可能会将发件人地址显示为注释。例如,Outlook将在阅读窗格的标题中显示这些行:

  

我&lt; Me@MyDomain.com>代表客户&lt; Client@ClientDomain.com>

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

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

答案 5 :(得分:4)

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

第一台服务器是smtp.office365.com(smtp客户端的属性主机),第二台服务器是STARTTLS / smtp.office365.com(属性TargetName of smtp client)。另一件事是在设置networkcredentials之前必须使用Usedefaultcredential = false。

    client.UseDefaultCredentials = False
    client.Credentials = New NetworkCredential("user@domain.com", "Password")
    client.Host = "smtp.office365.com"
    client.EnableSsl = true
    client.TargetName = "STARTTLS/smtp.office365.com"
    client.Port = 587

    client.Send(mail)

答案 6 :(得分:2)

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

最后从某个地方获得这条线作为最后的手段,就在之前。发送(消息)

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

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

答案 7 :(得分:1)

最后,作品!

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