Sending mail using SmtpClient in .net
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 :
- 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
- Use the oss lib MailKit.
- Elaboration : Because you will face its deficiencies sooner rather than later. Read here or read around the internet.
- 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.
Manish Gupta
Updated on July 09, 2022Comments
-
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 about 14 yearsThe 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 about 14 yearsWhat is Authentication Mode of your application ? Please provide more details around your problem scenario..
-
Manish Gupta about 14 yearsIn asp.net authentication mode is set to forms.
-
Alex Wiese almost 10 yearsThis doesn't make sense as both code snippets are almost identical. The only difference is the instantiation of the
NetworkCredential
class happens inside theusing
block in the second snippet. Maybe this has an unintended side effect? -
user3524983 almost 10 yearsYour 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 almost 10 yearsAnd I finally got the credentials working from web.config. Whew! What a day.
-
user3524983 almost 10 yearsWhat 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 almost 8 yearsYour 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 almost 8 yearsIndeed. If you want to
catch (Exception ex)
and thenthrow
it, just usethrow;
instead ofthrow ex;
and the stack trace will be maintained. This is only useful, however, f you are doing other things before rethrow
ing the exception, such as logging it. In this case, though, simply omitting thecatch
clause altogether would have had the same effect. -
Chris Snowden over 4 yearsThanks for this solution. I've updated the answer with example code showing why the order is important.