I'm using System.Net.Mail to send email, like so :
MailMessage message = new MailMessage();
message.From = new MailAddress("foo#foo.com");
message.To.Add(new MailAddress("foobar#foobar.com"));
message.Subject = "Hello";
message.Body = "This is a nice body..";
SmtpClient client = new SmtpClient();
client.Send(message);
How can i know if the E-mail was sent, can i put in a if sentence to check it out ?
What would it look like then ?
You might want to wrap your SMTP call into a try...catch block - that way you can easily catch any obvious SMTP related errors that might happen:
try
{
SmtpClient client = new SmtpClient();
client.Send(message);
}
catch(Exception exc)
{
// log the error, update your entry - whatever you need to do
}
This will handle the most obvious errors, like
SMTP server not found
SMTP server not responding
SMTP refusing you to send (e.g. because you didn't provide any or valid credentials)
Once the SMTP server has your message, it's out of your .NET hands.... you can't really do much (except check for the SMTP server's logs for errors).
If you want to check and see whether your SMTP mails actually are "sent out", you can also add these lines of code to your app's app.config (or web.config) and let .NET put your mails into a directory (as EML files):
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="C:\temp\mails"/>
</smtp>
</mailSettings>
</system.net>
Your mails will now be stored into the C:\temp\mails directory as EML files and you can have a look at them and check to see whether they are as they should be.
What marc_s says is correct about the use of try/catch.
It's worth noting clearly though that there are no delivery guarantees with SMTP, and trying to work out actual delivery numbers is a very inexact science.
There are a number of techniques that some software attempts to use, like image bugs and tracking links, however these are not fully reliable.
Many servers will silently fail a message with an unknown address or if there are transmission errors, to avoid giving spam providers too much information.
So once you've sent it, if there's no exception, you can only hope that it succeeded. One valuable technique though is to use a regular expression to validate the email address when the user enters it. This helps to avoid some common address problems before they affect mail delivery.
You can install and use the DevNullSmtp server - it does not send any email, but will log and display all messages and traffic.
I would consider using 3rd party services (smtp.com comes to mind) to handle messaging. These usually provide tracking api's that can be queried for successful delivery.
Related
I try to send emails with my dedicated office365 account but I have issues with subject encoding - all my special characters are replaced with "?".
Code I use is pretty simple and works fine with different test account at smtp-mail.outlook.com.
using (var mailMsg = new MailMessage(sender, recipient))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = "Hello world żółćąź";
mailMsg.Body = body;
using (var smtpClient = new SmtpClient())
{
smtpClient.Credentials = new NetworkCredential("email", "password");
smtpClient.EnableSsl = true;
smtpClient.Host = "smtp.office365.com";
smtpClient.Port = 587;
await smtpClient.SendMailAsync(mailMsg);
}
}
I tried to set all possible subject encoding with no luck. Also converting subject string to Base64String also don't work. Also tried to set Content-Type header charset... All of the resolutions I found didn't help me. Maybe this is some specific SmtpClient issue realated only with office365?
And also setting the body encoding did not help
mailMsg.BodyEncoding = Encoding.UTF8;
I had the same issue with my company's account. Here are my findings so far:
It looks like the Office365 e-mail servers enabled the SMTPUTF8 extension a few months ago which changes the behavior of the System.Net.Mail.SmtpClient class into sending different SMTP commands and a different DATA payload.
In my case the message would always arrive fine when sent to another Office365 account but for other accounts we received e-mail bounce notices from the remote SMTP server which accepted the relayed e-mail message from Office365. The error was something like "Invalid data received, expected 7-bit-safe characters". I could thus imagine that the remote SMTP server from the OP might silently replace all characters outside the low 7-bit range with a question mark.
Sending through GMail (which also has the SMTPUTF8 extension active) had no problems.
So far I haven't debugged the SmtpClient reference sources yet to see what gets sent to the Office365 server. The root cause could thus either be that SmtpClient sends a good message which Office365 "corrupts" before relaying and which GMail sends on without issue; or SmtpClient builds a bad message / SMTP session which Office365 silently accepts and forwards to remote SMTP servers but which GMail accepts and fixes on the fly before relaying.
Either way, I pulled in the MailKit and MimeKit libraries using NuGet and use those instead to send my e-mails. These offer SMTP protocol logging to troubleshoot issues and appear to solve the stated problem by properly sending the SMTPUTF8 and 8BITMIME flags as defined in RFC 6531. It does take extra work to read configuration from the usual Web.config or App.config location but the libraries do the job.
If you want to keep using SmtpClient then you should either contact Microsoft (it's their service and their .NET Runtime), or run your own private SMTP server without the SMTPUTF8 extension which relays to remote servers. In the latter case SmtpClient should properly encode all headers and payload (though it does mean that you might be unable to use the International value for the DeliveryFormat property when you want to send to people with an internationalized e-mail address).
Set the encoding of the mail message so one that supports the characters you use, since the default is us-ascii:
mailMsg.BodyEncoding = Encoding.UTF8;
We had the same Issue with Office365 SMTP Server, using vmime library. We solved it by disabling SMTPUTF8, thus always encoding non-ascii characters.
As stated above by JBert, the same protocol works with GMail SMTP servers.
I'm using MimeKit and MailKit together to send off e-mails through an SMTP server. Every now and then, though, I've got a server that throws back an error at me:
The SMTP server does not support the SMTPUTF8 extension
Obviously, I'd like to stop these errors from occurring. Is there a way in MimeKit to disable the SMTPUTF8 extension on either the SmtpClient, MimeMessage, or MimeEntity?
I fear I'm asking the wrong question, or asking for a solution in the wrong place. If anybody can add clarification to a possibly poorly worded question, please let me know.
Here's how I'm sending:
using (var client = new SmtpClient())
{
try
{
client.Connect("server", port);
// I've got reasons to remove this.
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Send(message);
client.Disconnect(true);
}
catch (Exception e)
{
// Pokemon Exception handling right here
// for the sake of showing what I'm doing.
}
}
One or more of the email addresses in your list of recipients (or the sender) has a unicode address (and I don't mean the "display name" contains unicode characters, I mean that the "x#y.com" part contains unicode characters that require the SMTP server to support the SMTPUTF8 extension in order to work).
For example, you might be trying to send to an email address such as 日本語#日本語.jp. Note that traditionally, only ASCII-based email addresses were allowed and SMTP servers that do not support the SMTPUTF8 extension cannot handle email addresses that are non-ASCII.
Below code is workin fine . However I need get Failure or Success Notification to Specific address (b#technospine.com). But I'm receiving Delivery Notification mail to FromMail address(A#technospine.com). Can you please help me to resolve this problem?
SmtpClient smtpClient = new SmtpClient();
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress("A#technospine.com", "BALA");
MailAddress adminAddress = new MailAddress("b#technospine.com");
smtpClient.Host = "Mail Server Name";
smtpClient.Port = 25;
smtpClient.UseDefaultCredentials = true;
message.From = fromAddress;
message.To.Add(_sendTo); //Recipent email
message.Subject = _subject;
message.Body = _details;
message.IsBodyHtml = true;
message.Headers.Add("Disposition-Notification-To", "b#technospine.com");
message.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess;
message.ReplyTo = adminAddress;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.Send(message);
The short answer is what you are asking cannot be done in the direct manner in which you are assuming.
This will only work in certain conditions. The easiest to describe would be if the SMTP server you are using to send the message, is the same server that hosts the domain of the recipient email messages (the server you refer to when setting your .HOST property of smtpClient). So, if you were only sending to recipients on your local SMTP mail server, then this might work pretty reliably. But that depends on the specific SMTP server software being used and potentially also on how it is configured.
To explain why this is, you must realize that only the last SMTP mail server receiving the message that actually hosts the desired email addresses, will be able to authoritatively answer the question, is this a valid email address. If the message has to pass through any other email servers on the way to getting at this final authoritative server, the message has to be handed off sequentially from one server to the next server in the chain until it reaches that final authoritative server. This means that there is not a guaranteed method for authenticating a specific address. Couple this with the fact that some domains are configured to act as a black hole and swallow illegitimately addressed mail, and you can see that there are many reasons why you cannot rely on that methodology.
So, many messages to external domains are going to have to hit at least one separate SMTP server and depending on how that server answers or forwards the mail, it will determine the results for any specific receiving domain. In fact, monitoring the FROM address for bounced messages is not foolproof either as my previous comment about some hosts putting some messages into a black hole if they do not appear to be valid.
If the recipient e-mail address is valid you don't get an immediate return value about the successful delivery of the message; see the signature:
public void Send(MailMessage message)
The SMTP server will notify the sender (or whoever you specify for the notification) almost immediately with an 'Undeliverable' notification whenever the recipient e-mail address is invalid/fake.
SMTP servers are required to periodically retry delivery. When the recipient e-mail address is a valid address but for some reason the SMTP server could not deliver the message, the SMTP server will return a failure message to the sender if it cannot deliver the message after a certain period of time.
RFC 2821 contains more details.
From section 2.1 Basic Structure
In other words, message transfer can occur in a single connection
between the original SMTP-sender and the final SMTP-recipient, or can
occur in a series of hops through intermediary systems. In either
case, a formal handoff of responsibility for the message occurs: the
protocol requires that a server accept responsibility for either
delivering a message or properly reporting the failure to do so.
See sections 4.5.4 and 4.5.5
From section 6.1 Reliable Delivery and Replies by Email
If there is a delivery failure after acceptance of a message, the
receiver-SMTP MUST formulate and mail a notification message. This
notification MUST be sent using a null ("<>") reverse path in the
envelope. The recipient of this notification MUST be the address from
the envelope return path (or the Return-Path: line).
According to MSDN the .Send will throw a SmtpFailedRecipientsException EDIT: if the MESSAGE can not be delivered to one or more of the recipients. You can find the information on which one in the Failed Recipient property in the exception.
Thus if you try and catch that exception and validate the address you're looking for in the Exception, that might help.
I am trying to send 4 emails using my isp. (NOT JUNK MAIL, i send it to my address)
I send them one by one from a loop (as I build them). every message is 50kb-80kb
MailMessage mailmessage = new MailMessage();
mailmessage.To.Add(to);
mailmessage.From = new MailAddress(from, "From");
mailmessage.IsBodyHtml = true;
mailmessage.Priority = MailPriority.Normal;
mailmessage.Subject = subject;
mailmessage.Body = body;
SmtpClient smtpclient = new SmtpClient(server, 25); //use this PORT!
smtpclient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpclient.Credentials = new NetworkCredential(user, pass);
smtpclient.Send(mailmessage);
On last message I get this error:
Service not available, closing
transmission channel. The server
response was: Connection not accepted
at this time
UPDATE:
some times after this error , I can't send any email (using this server) even from other applications like outlook express, I get error:
An unknown error has occurred.
Account: 'MailServerAddress', Server:
'MailServerAddress'', Protocol: SMTP,
Server Response: '421 Connection not
accepted at this time', Port: 25,
Secure(SSL): No, Server Error: 421,
Error Number: 0x800CCC67
after about a minute, I can send again.
Always make sure your sender address is also a valid mailbox so bounce messages actually get back to you, many ISPs prohibit use of other (unregistered) sender addresses entirely. As pointed out in the comments by others, there is typically also rate limiting by the ISP so you'll have to fine-tune your sending code to the ISPs expectations, which can be tedious.
In general, sending emails is both art and science for some reason. If you're trying to use this for a production system, I can only suggest you use some service such as SendGrid or Mailgun. Even if your mail server accepts the messages, it might hit a limit on another ISPs mail server because most ISPs have certain limits and email routing is quite complicated. Also you might hit spam filters quickly. With my ISP, automated messages always to go spam in googlemail for whatever reason.
For development, Mailgun offers a two hundred emails per day for free which should be enough in the beginning. Also, SMTP is a very slow protocol so using their HTTP interface will save you some server time.
I had not exactly, but very similar issue here:
SMTP send email failure by SmtpClinet (SmarterEmail server)
The problem was that my local ISP was closing 25 port.
Have you tested some other ports, like 587?
I have written some simple code, to send en auto generated email, using the System.mail.Net namespace.
It works like a charm, but there is one little problem.
The mail does not get send, untill my whole application is terminated.
Does any of you have a workaround for this?
Here is the code I use (c#):
try
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("myEmail#mail.com");
mail.To.Add("targetEmail#mail.com");
mail.Subject = "Test test";
mail.Body = "blah blah";
mail.Attachments.Add(new Attachment("c:\\file.txt"));
SmtpClient smtp = new SmtpClient("myserver.mail.com");
smtp.Send(mail);
}
catch (SmtpFailedRecipientsException ex)
{
Console.WriteLine(ex);
}
As I said, everything works, but the mail is not send, untill I terminate the application.
Is there any way to force it to send the mail now?
The reason it is a problem, is both that I want the mail to be sent instantly without the user needing to reboot the application, but also because I want to delete the attachment after the mail has been sent, and when the mail isn't sent, the file is therefore marked as "in use" and can therefore not be deleted.
Best regards
/S
I've had the same problem, and using the workaround posted at http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/6ce868ba-220f-4ff1-b755-ad9eb2e2b13d/ seems to work:
For anyone interested, I've found a solution or at least a work around to the delay.
The ServicePoint member contains a member called MaxIdleTime. Setting this value to 0 seems to have the same affect as Timeout.Infinite (which I assume is also 0). Setting it to 1 caused my email to be sent out immediately.
See this link:
http://msdn2.microsoft.com/en-us/library/system.net.servicepoint.maxidletime.aspx
Example code:
SmtpClient smtp = new SmtpClient();
// setup the mail message
smtp.ServicePoint.MaxIdleTime = 1;
smtp.Send(myMailMessage);
Calling
smtp.Send(mail);
Sends the email to your smtp server immediately. If you're not seeing the email being sent as soon as that line executes, then I would check to see if your smtp server is functioning properly.
Here's more information on the SmtpClient.
I wonder if your application has a lock on the attachment which is preventing the mail component from doing its work until your application starts shutting down. Can you verify that all locks are cleared prior to sending the mail?
You might start with a new small app that only sends an email. Once that it working properly, add a hard coded attachment. Verify it's still working. If everything is good, add your code for how you are handling attachments. If it breaks, tweak your code. Rinse and repeat. ;)
I have seen this problem before. I had to turn off Norton Antivirus outgoing email scan to get emails to go right away.
HTH