22

I am unable to send the mail using smtp client. here is the code:

SmtpClient client=new SmtpClient("Host");
client.Credentials=new NetworkCredential("username", "password");
MailMessage mailMessage = new MailMessage();
mailMessage.from="sender@gmail.com";
mailMessage.To.Add("recipient@gmail.com");
mailMessage.body="body";
mailMessage.subject="subject";
client.Send(mailMessage);

The problem is that when I use this code in ASP.NET application, I do not receive any mails. When in asp.net I change the from mail address to username given in NetworkCredential, I receive mails.

But in C# windows application, I can get emails, even if sender's email address is not valid.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Manish Gupta
  • 449
  • 2
  • 6
  • 16
  • This could be related to configuration on the server vs. your dev machine. – Nate Mar 18 '10 at 14:42
  • You seem to be using a gmail address in the from field. Have you made sure that all settings are set according to instructions from them? – Tomas Aschan Mar 18 '10 at 14:50

5 Answers5

20

I figured out that setting the SmtpClient Credentials property before setting the <html><span class="diff-delete">UseDefaultCredentials = false</span></html>. UseDefaultCredentials = false causes the credentials to be ignored.

Fails:

SmtpClient smtp = new SmtpClient;
smtp.Credentials = new NetworkCredential("user","pass");
smtp.UseDefaultCredentials = false;

Works:

SmtpClient smtp = new SmtpClient;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("user","pass");

Go figure.

** UPDATE **

The reason the order is important here is that the setter on the UseDefaultCredentials property actually sets the Credentials to null via the decompiled code:

/// <summary>Gets or sets a <see cref="T:System.Boolean" /> value that controls whether the <see cref="P:System.Net.CredentialCache.DefaultCredentials" /> are sent with requests.</summary>
/// <returns>
/// <see langword="true" /> if the default credentials are used; otherwise <see langword="false" />. The default value is <see langword="false" />.</returns>
/// <exception cref="T:System.InvalidOperationException">You cannot change the value of this property when an e-mail is being sent.</exception>
public bool UseDefaultCredentials
{
  get
  {
    return this.transport.Credentials is SystemNetworkCredential;
  }
  set
  {
    if (this.InCall)
      throw new InvalidOperationException(SR.GetString("SmtpInvalidOperationDuringSend"));
    this.transport.Credentials = value ? (ICredentialsByHost) CredentialCache.DefaultNetworkCredentials : (ICredentialsByHost) null;
  }
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
user3524983
  • 419
  • 4
  • 7
  • This doesn't make sense as both code snippets are almost identical. The only difference is the instantiation of the `NetworkCredential` class happens inside the `using` block in the second snippet. Maybe this has an unintended side effect? – Alex Wiese Jul 28 '14 at 00:44
  • Your are correct. And the unintended effect is that setting Credentials BEFORE you set UseDefaultCredentials = false is what makes this happen. I'll edit the post. – user3524983 Jul 28 '14 at 01:02
  • And I finally got the credentials working from web.config. Whew! What a day. – user3524983 Jul 28 '14 at 01:10
  • 2
    What I did not realize was that setting Host and Port act like a LOOKUP into the web.config smtp/network entries. And once it finds a match it will pull the user and password out and use them. Hope this helps somebody else. – user3524983 Jul 28 '14 at 01:18
  • Thanks for this solution. I've updated the answer with example code showing why the order is important. – Chris Snowden Sep 12 '19 at 14:22
7

The short answer : Do not use .net the internal SMTP client class - use MailKit.

The long answer :

  1. It is marked as obsolete in MS docs

[System.Obsolete("SmtpClient and its network of types are poorly designed, we strongly recommend you use https://github.com/jstedfast/MailKit and https://github.com/jstedfast/MimeKit instead")] public class SmtpClient : IDisposable

  1. Use the oss lib MailKit.
  2. Elaboration : Because you will face its deficiencies sooner rather than later. Read here or read around the internet.
  3. Here is an example for sending plain messages and multipart messages.

I intentionally did not copy-paste the examples from the docs here because the documentation may change over time and it is better to read .

Ognyan Dimitrov
  • 6,026
  • 1
  • 48
  • 70
1

It means your mail server does not allow Mail-Relay. Your mail server only allows you to send mail from authenticated email-id as username. Generally this is done to prevent mails being sent as different identities other than the authenticated one.

SteveC
  • 15,808
  • 23
  • 102
  • 173
this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
  • 1
    The mail server is same in both windows as well as ASP.NET application. And also the same code is working fine in other page of ASP.NET application. Its not working in the login page of ASP.NET application. What can be the problem? – Manish Gupta Mar 19 '10 at 04:39
  • What is Authentication Mode of your application ? Please provide more details around your problem scenario.. – this. __curious_geek Mar 19 '10 at 05:56
  • In asp.net authentication mode is set to forms. – Manish Gupta Mar 19 '10 at 08:49
0

Try this :

MailMessage mail = new MailMessage("emailfrom","emailto");

mail.From = new MailAddress("emailfrom");
mail.Subject = txtsbjct.Text;
string Body = txtmsg.Text;
mail.Body = Body;

mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com"; //Or Your SMTP Server Address
smtp.Credentials = new System.Net.NetworkCredential("youremail", "yourpassword");

smtp.EnableSsl = true;
smtp.Send(mail);
txtemail.Text = "";
txtmsg.Text = "";
txtsbjct.Text = "";
Label1.Text = "your email has been send";
mail = null;
smtp = null;
AgentFire
  • 8,944
  • 8
  • 43
  • 90
-4
void sendEmail(string strFrom
                        , string strTo
                        , string strSubject
                        , string strBody)
   {

       MailMessage objMailMessage = new MailMessage();
       System.Net.NetworkCredential objSMTPUserInfo =
           new System.Net.NetworkCredential();
       SmtpClient objSmtpClient = new SmtpClient();

       try
       {
           objMailMessage.From = new MailAddress(strFrom);
           objMailMessage.To.Add(new MailAddress(strTo));
           objMailMessage.Subject = strSubject;
           objMailMessage.Body = strBody;

           objSmtpClient = new SmtpClient("172.0.0.1"); /// Server IP
           objSMTPUserInfo = new System.Net.NetworkCredential
           ("User name", "Password","Domain");
           objSmtpClient.Credentials = objSMTPUserInfo;
           objSmtpClient.UseDefaultCredentials = false;
           objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;

           objSmtpClient.Send(objMailMessage);
       }
       catch (Exception ex)
       { throw ex; }

       finally
       {
           objMailMessage = null;
           objSMTPUserInfo = null;
           objSmtpClient = null;
       }
   }
usmanali
  • 2,028
  • 2
  • 27
  • 38
Ashish
  • 7
  • 5
    Your error handling is actually a very bad practice, because you are losing the stack trace (cf http://stackoverflow.com/a/730255/474763) ... in addition, in this case, omitting the catch clause would have been the way to go – tsimbalar Jun 30 '16 at 13:59
  • 3
    Indeed. If you want to `catch (Exception ex)` and then `throw` it, just use `throw;` instead of `throw ex;` and the stack trace will be maintained. This is only useful, however, f you are doing other things before re`throw`ing the exception, such as logging it. In this case, though, simply omitting the `catch` clause altogether would have had the same effect. – Owen Blacker Aug 05 '16 at 11:16