Sending mail using SmtpClient in .net

107,459

Solution 1

I figured out that setting the SmtpClient Credentials property before setting the ' UseDefaultCredentials = false ' 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;
  }
}

Solution 2

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 .

Solution 3

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.

Share:
107,459
Manish Gupta
Author by

Manish Gupta

Updated on July 09, 2022

Comments

  • Manish Gupta
    Manish Gupta almost 2 years

    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="[email protected]";
    mailMessage.To.Add("[email protected]");
    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.

  • Manish Gupta
    Manish Gupta about 14 years
    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?
  • this. __curious_geek
    this. __curious_geek about 14 years
    What is Authentication Mode of your application ? Please provide more details around your problem scenario..
  • Manish Gupta
    Manish Gupta about 14 years
    In asp.net authentication mode is set to forms.
  • Alex Wiese
    Alex Wiese almost 10 years
    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?
  • user3524983
    user3524983 almost 10 years
    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
    user3524983 almost 10 years
    And I finally got the credentials working from web.config. Whew! What a day.
  • user3524983
    user3524983 almost 10 years
    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.
  • tsimbalar
    tsimbalar almost 8 years
    Your error handling is actually a very bad practice, because you are losing the stack trace (cf stackoverflow.com/a/730255/474763) ... in addition, in this case, omitting the catch clause would have been the way to go
  • Owen Blacker
    Owen Blacker almost 8 years
    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 rethrowing the exception, such as logging it. In this case, though, simply omitting the catch clause altogether would have had the same effect.
  • Chris Snowden
    Chris Snowden over 4 years
    Thanks for this solution. I've updated the answer with example code showing why the order is important.