70

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("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);
Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
Adam Stewart
  • 1,983
  • 1
  • 18
  • 25
  • yes you get a timeout - this apparently is the default failure – Adam Stewart Jun 06 '11 at 10:10
  • 1
    so im starting to wonder if this is even possible using C# and the limitations the System.Net.Mail namespace has over SSL settings. It seems like Exchange has it's webservices exposed on Office 365 and a lot of articles talk about leveraging this to work with mailboxes etc. However i dont really want to expose the entire mailbox to my LOB application. The 'S' in SMTP stands for 'SIMPLE' - i just cant believe that Microsoft's install of Microsoft's mail server cant work with Microsoft's programming language. Please someone tell me im missing something here! – Adam Stewart Jun 22 '11 at 11:07
  • I wish I had a server to try it on. So, its timing out, Heres a question. As your test mail there is pure text, does it work if you dont say the body is HTML? – BugFinder Jun 22 '11 at 11:39
  • i changed the above code to have mail.IsBodyHtml = false; but i still get the timeout. i appreciate the suggestion - at this point in time im willing to try anything to get this working! – Adam Stewart Jun 24 '11 at 10:33
  • At this point I would point a finger at MS and say that exchange isnt playing fair. Does the mail get sent and its somehow expecting you to have closed the connection?if you lined up a couple of messages such as 1 to yourself, does that work - has the exchange person been able to see any log files showing such as connection, it maybe its a relay issue, in that you arent permitted, but it takes the connection and hangs on to it (my anti spam can do that)..? – BugFinder Jun 24 '11 at 12:23
  • 1
    Just thougt I would point out this answer to a similar question. For the code sample to work, you need to move the `UseDefaultCredentials = false` line before setting the `Credentials`. http://stackoverflow.com/a/14021685/20047 – jeroenh Jan 25 '14 at 15:58
  • This worked for my issue http://stackoverflow.com/questions/21045026/sent-outlook-draft-from-other-computer?answertab=votes#tab-top – Eugen Sep 26 '14 at 06:40

10 Answers10

72

Fixed a few typos in the working code above:

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

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

Joakim Johansson
  • 3,196
  • 1
  • 27
  • 43
Sanjeev
  • 729
  • 5
  • 2
  • what version of Office 365 are you running on. I haven't looked at this code for a while, but we are getting ready to port from small business plan P1 to enterprise plan E1 and i'm wondering if my initial problems were caused by our being on the P1 plan. – Adam Stewart Aug 07 '13 at 16:10
  • 37
    This code unfortunately is no longer valid with Office 365. Error message that comes up is 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 [HE1PR05CA0133.eurprd05.prod.outlook.com] – Simon Price Jan 30 '18 at 00:02
  • Yes, Simon Price is right, even on port 25 it doesn't work. – Dieter Jun 19 '20 at 20:44
  • 1
    we an organization enabled the MFA on accounts, then how we can configure the same? – Sunil Soni Jul 17 '20 at 03:47
  • This is really great! Thanks!. – Mike Malter Jul 29 '20 at 16:39
34

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("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);
                }
            }
Jirapong
  • 24,074
  • 10
  • 54
  • 72
  • This looks very promising, but I'm getting an error like: *System.Net.Mail.SmtpException: Failure sending mail. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions 52.97.133.146:587* ... Any idea? – Dieter Jun 21 '20 at 21:50
  • I also wonder where you can find that "full email address for authentication". Can you elaborate please? – Dieter Jun 25 '20 at 17:54
  • 1
    `"full email address for authentication"` is the email account which is used for sending out emails. E.g., my company's email is my-name@my-company.com. I create another email to send out emails such as noreply@my-company.com. I will fill the credentials of noreply account there. – Lam Le Dec 16 '21 at 09:20
  • What about when two factor authentication enabled ? – Gayan Feb 04 '22 at 17:22
  • If you have 2FA enabled, It is interactive mode which may not able to work by this script. – Jirapong Mar 24 '22 at 06:46
  • I love you! Thanks so much, this works! – Paul Feb 17 '23 at 07:48
15

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 sballmer@microsoft.com.

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>
The Dude
  • 281
  • 2
  • 6
  • 1
    I'm assuming `hunter2password` isn't your password? – rhughes May 20 '14 at 06:31
  • 11
    Heh, yeah, that's that old reference to the irc meme. My password is ***************. Src: http://ars.userfriendly.org/cartoons/?id=19990814 – The Dude May 20 '14 at 17:40
  • 1
    The MailMessage.From doesn't have to be the main account email if you add the MailMessage.Sender property with an O365 authorized "Send As" email address. See my post in this thread for details: http://stackoverflow.com/a/33613150/2464869 – ShaneLS Nov 09 '15 at 17:16
  • @jklemmack Thank you, I was wondering what bash.org's name was nowadays. --- What do you mean the name hasn't changed!? :) – The Dude Sep 17 '18 at 17:23
10

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("user@domain.com", "Password")
    client.Host = "smtp.office365.com"
    client.EnableSsl = true
    client.TargetName = "STARTTLS/smtp.office365.com"
    client.Port = 587

    client.Send(mail)
9

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

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

Community
  • 1
  • 1
Phil Sayers
  • 193
  • 1
  • 7
6

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 Me@MyDomain.com 365 account but the .NET mail message was addressed from Client@ClientDomain.com. 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 (Me@MyDomain.com) 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. Support@MyDomain.com, no-reply@MyDomain.com, etc.)

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

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("Me@MyDomain.com", "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 )  
   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>  

-- 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 <Me@MyDomain.com> on behalf of Client <Client@ClientDomain.com>

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?

ShaneLS
  • 466
  • 6
  • 14
5

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.

Joe Frank
  • 761
  • 7
  • 6
0

I got mine working with:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
456q
  • 107
  • 11
0

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

Juan
  • 2,156
  • 18
  • 26
-3

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();
nickhar
  • 19,981
  • 12
  • 60
  • 73
Yeong
  • 19
  • 1
  • -1; setting `UseDefaultCredentials = false;` after setting `Credentials = xxyy` reset your credentials to `null`. So you dont send any credentials at all. (and yes, i know i am necromanting this answer after 9 years...) See https://stackoverflow.com/questions/6656039/sending-email-using-smtp-mail-microsoftonline-com/7009204#7009204 – Jan 'splite' K. May 06 '21 at 15:08
  • Quite clearly this is contradictory to advice. UseDefaulCredentials = false should be BEFORE setting Credentials https://stackoverflow.com/questions/2470645/sending-mail-using-smtpclient-in-net – KiwiSunGoddess Nov 22 '21 at 20:10