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.
Related
We are trying to check if a recipient email id (domain of a given email id) has TLS implemented or not. If not implemented we cannot send the email. Is there any way in C# to check it? e.g. Following is a service where we can enter any email id and it will tell us if that email domain has TLS implemented or not. https://www.checktls.com/TestReceiver How to do this in C#? C# email client comes with the property smtpClient.EnableSsl = true; question is what will happen if at the recipient side the TLS is not implemented? Will it fail or it will go through? If it fails that's what we want. Our SMTP server has TLS implemented.
I tried STARTTLS command and EHLO from telnet. It gives 250 STARTTLS, which tells me that the destination server has TLS implemented. How to do it programmatically?
smtpClient.EnableSsl = true;
If you use a library like MailKit, you can do this:
bool supportsStartTls;
using (var client = new SmtpClient ()) {
client.Connect ("smtp.host.com", 587, SecureSocketOptions.None);
supportsStartTls = client.Capabilities.HasFlag (SmtpCapabilities.StartTls);
client.Disconnect (true);
}
If you want to use MailKit to send mail, you have full control over what happens if STARTTLS is not available.
For example, if you wanted it to fail if STARTTLS is not supported, then use SecureSocketOptions.StartTls as the third argument to the Connect method.
If you want MailKit to use STARTTLS when it is available but not fail if it isn't, then use SecureSocketOptions.StartTlsWhenAvailable instead.
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.
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'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.
This question already has answers here:
Email messages going to spam folder
(7 answers)
Closed 9 years ago.
I've got a C# application going that needs to send out an html email via smtp. The email gets sent just fine, but the default security setting on outlook (Low) classifies it as junk email.
It's not exactly a showstopper issue, but this is rather annoying, especially since the junk folder turns off html. I don't want to have to make everyone at my company do something special to receive these emails in a readable fashion, does anyone know what I could be doing that makes outlook think this is junk email?
Code that makes the email (basic stuff.) Config is an object that holds strings related to the configuration of this stuff, toList is a list of email addresses, body/subject are filled by other function calls.
Edit: To add, at the moment I'm just sending it out to myself. In the live version, we'll be looking at less than a hundred people being sent to in a worst-case.
Another Edit: It turned out to be happening much much more often for the longer emails I was generating the other day (~200-300 lines at the worst), and not the shorter emails I'm generating now. That's a reasonable enough filter criteria, I suppose.
SmtpClient smtp = new SmtpClient(config.SmtpServer);
NetworkCredential net = new NetworkCredential();
net.UserName = config.SmtpLogin;
net.Password = config.SmtpPass;
smtp.Credentials = net;
MailMessage msg = new MailMessage();
msg.IsBodyHtml = true;
msg.Priority = MailPriority.Normal;
msg.To.Add(String.Join(",", toList.ToArray()));
msg.From = new MailAddress(fromAddr, "Build Server");
msg.Body = "Blah html is here";
msg.Subject = "Build successful: #numberhere and stuff";
try
{
smtp.Send(msg);
}
catch (SmtpException)
{
//stuff
}
I think this is less of a programming issue and more of a configuration issue. The recipients need to add fromAddr to their “Safe Senders List”.
The thing is, if there were a way to configure an e-mail to bypass the junk mail filter then all the spammers will be doing it.
If it's a matter of crafting the perfect non-junk-looking e-mail then it may work sometimes and not others. And all the spammers will be doing it.
You're going to have to tell everyone to allow e-mails from that account. And you probably shouldn't start that e-mail with any unnecessary anatomical or medicinal references.
If your message To contains a large list it may be seen as spam. Try sending a unique email to each person instead of a mass email.
However:
If you're going to loop through your list and send an email for each user, you might want to consider creating a queue that will be processed that allows for failure and retry.
We had a similar issue in our system where after about 20,00 messages sent in quick succession (ie: within a foreach loop) the outgoing mail server rejected any further attempt to relay.
We instead added outgoing messages to a database table, and wrote a service that would process a specified number of emails at a time and then pause for a specified time before going again.
In addition this allowed us to capture failures, and then setup retry rules. After X attempts we mark the message as failed for good and report the issue. We found that this provided a much more reliable system of users getting their messages, plus they were no longer marked as spam.
If you are sending out several mails at a time send them in small batches so you're not flooding the server.
Check the text of the email for words and symbols likely to be considered spam by some filters.
You might also want to look into things such as SPF to reduce the chance that your mails will be marked as spam.
Add following line in your code while creating MailMessage
msg.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
Just a thought, try looping through your to list and send a separate email. Also, try experimenting with different wording and html structures.