I am working on a website I didn't write so I don't know it inside out. The default setting for SMTP mail encoding is being set to ASCII (somewhere) but I want it to be UTF-8. It seems this should be in a config file but I can't find where it is specified. I'm aware that I can manually set it in the code but I want the change to be site wide. The emails are in html. Everywhere else on the site except for email seem to be correctly set to UTF-8.
Currently, my email headers have this setting for encoding:
Content-Type: text/html; charset=us-ascii
And it should be:
Content-Type: text/html; charset=UTF-8
or something to that effect.
Here is some sample code that is used. I don't think it is that informative. The email values are being produced in another class. This is the part that sends the email.
using System.Net.Mail;
....
MailMessage msg = new MailMessage();
msg.IsBodyHtml = true;
msg.From = new MailAddress(shopEmail, (Globals.Settings.Shop.MailName));
// This just pulls these values from another class
msg.Subject = editEmailTemplates.EmailSubject;
msg.Body = editEmailTemplates.EmailBody;
SmtpClient mailClient = new SmtpClient();
try
{
mailClient.Send(msg);
}
catch(SmtpException)
{
}
Related
I am sending an email via C# SMTP. It's a HTML email which separates lines by tags, e.g. :
Dear Test,A password request has been initiated for your
account. Please click this link....
This renders fine in an Outlook inbox, but in Gmail it seemingly ignores the tags:
Gmail
Outlook
Why isn't Gmail rendering the HTML? It's the same result via the web browser as the Android email client.
When I view the source of the Gmail email and download the .eml file from Gmail the email contains the br tags.
I tried replacing the br tags with line breaks, but when I do that the opposite happens - it doesn't render the line breaks in Outlook but it does render them in Gmail.
What's actually going on here and how can I satisfy all email clients?
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Here is my C# for generating the emails:
var mailMessage = new MailMessage
{
Subject = subject,
BodyEncoding = Encoding.UTF8,
From = new MailAddress(EmailFrom),
IsBodyHtml = true
};
var htmlView = AlternateView.CreateAlternateViewFromString(body.ReplaceLineBreaksWithHtmlLineBreak(), new ContentType("text/html"));
htmlView.ContentType.CharSet = Encoding.UTF8.WebName;
mailMessage.AlternateViews.Add(htmlView);
var plainView = AlternateView.CreateAlternateViewFromString(body.StripHtml(), new ContentType("text/plain"));
plainView.ContentType.CharSet = Encoding.UTF8.WebName;
mailMessage.AlternateViews.Add(plainView);
For the HTML email, I replace line breaks in my template string with br tags. For the plain text view, any HTML is stripped out.
UPDATE:
It turns out on my plaintext view I was accidentally stripping out the line breaks. This solves the problem but another question I have is why does Gmail seemingly only render the plaintext version of the email?
I'm sending an Hebrew email to two places, one is Gmail and the other is Outlook.
The problem:
Gmail is working fine every time (they detect the Encoding automatically) but Outlook display the body in gibberish, I can fix it if I change the display encoding from Hebrew(Windows) to Unicode(UTF-8) (when opening the message display in Outlook).
worth mention that the headers and the subject are fine.
The Question: How can I "tell" Outlook or any other program to view the mail with Unicode(UTF-8) encoding ? without the need to do it manually.
I try to set the encoding, char-set and what not but I can get it to work.
Code related:
public static void SendEmail(MailMessage msg )
{
ContentType mimeType = new System.Net.Mime.ContentType("text/html");
msg.AlternateViews.Add(System.Net.Mail.AlternateView.CreateAlternateViewFromString(msg.Body, mimeType));
SmtpClient smtp = new SmtpClient
{
Host = "mailgw.netvision.net.il",
Port = 25,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(uName,uPass)
};
smtp.Send(msg);
}
Here is a couple examples how I tried to play with the Encoding:
msg.BodyEncoding = Encoding.ASCII;
msg.BodyEncoding = Encoding.UTF8;
msg.BodyTransferEncoding = TransferEncoding.SevenBit;
At the end what make it work is the configuration of the alternative view, like this:
AlternateView view = System.Net.Mail.AlternateView.CreateAlternateViewFromString(msg.Body, Encoding.UTF8, "text/html");
msg.AlternateViews.Add(view);
As you can see I've set the MIME (as I did before) but I also set the Encoding to UTF-8, what solve the problem.
Firstly, it would be a good idea to HTML encode all Unicode characters in the HTML body itself - https://en.wikipedia.org/wiki/Character_encodings_in_HTML.
Secondly, please port the complete MIME source of the message that you create.
When receiving e-mails sent with System.Net.Mail.MailMessage some recipients seem to have encoding issues with the e-mail. For example charachter ä is displayed as ä. I have set encoding properties:
System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
...
msg.BodyEncoding = System.Text.Encoding.UTF8;
msg.SubjectEncoding = System.Text.Encoding.UTF8;
What else can I do?
Update:
If I use the Body property the e-mail is displayed correctly, but when I use the AlternateViews property the e-mail is displayed incorrectly.
Complete code:
SmtpClient smtpClient = new SmtpClient("some.host.com");
MailMessage msg = new MailMessage();
msg.To.Add("someone#host.com");
msg.From = new MailAddress("name#host.com", "Name Name");
msg.Subject = "Test";
//Displays as ä
//msg.Body = "ä";
// Displays as ä
AlternateView htmlView = AlternateView.CreateAlternateViewFromString("ä", new ContentType(MediaTypeNames.Text.Html));
msg.AlternateViews.Add(htmlView);
smtpClient.Send(msg);
When sending to Gmail the e-mail is displayed correctly, but when sending to an Exchange server the e-mail is displayed incorrectly. I have tested in .NET 3.5 and 4.5.
Try adding the content type to the Alternative View:
AlternateView htmlView = AlternateView.CreateAlternateViewFromString("ä", new ContentType(MediaTypeNames.Text.Html));
htmlView.ContentType.CharSet = Encoding.UTF8.WebName;
I don't think the BodyEncoding and SubjectEncoding affects reading of messages in any way - it applies to when you send messages and sets the text encoding for the messages and headers when messages are sent.
SmtpClient will read the content-type and charset encoding from messages sent and decode the content of the message and subject according to the encoding it finds in the headers.
If your message is not getting decoded, it seems that the messages are possibly not encoded correctly (or potentially double encoded UTF-8 encoded string getting encoded again by a message encoder), the request headers on the message don't properly match the actual encoding of the message or a charset format that isn't supported in .NET is used.
The only way to know though is to look at the actual raw request trace of a message that fails to see what's actually getting sent.
You might want to set up System.NET tracing for email messages (see http://codepaste.net/j52ktp) or else monitor the TCP/IP stream with something like Wireshark to see what's actually going over the wire and what the headers are instructing the client to do with the data.
FWIW, there's no reason if a message is properly UTF-8 encoded for SmtpClient to not read these messages correctly.
I'm trying to convert some Python code for use in a .Net website. The code retrieves a message stored in RFC822 format and sends the message to an SMTP server again using:
mail from: blah blah
rcpt to: blah blah
data
<send the text from the RFC822 file here>
.
So no parsing of the RFC822 file is required (fortunately!). In Python this is simply:
smtp = smtplib.SMTP(_SMTPSERVER)
smtp.sendmail(_FROMADDR, recipient, msg)
where the file has been read into the variable msg. Is there an easy way to do this in C#?
The built in C# SMTP objects don't offer a way to do this, or at least I haven't found a way. They seem to be based on the principle of building up a MailMessage by providing the addresses, subject and body separately. SmtpClient has a Send(string, string, string, string) method, but again this requires a separate subject and body so I guess it constructs the RFC822 formatted message for you.
If necessary I can write my own class to send the mail. It's such a simple requirement that it wouldn't take long. However if there is a way using the standard libraries they're probably less buggy than my code.
I would recommend using MimeKit to parse the message file and then use MailKit to send via SMTP. MailKit is based on MimeKit, so they work well together and MailKit's SmtpClient is superior to System.Net.Mail's implementation.
Parsing a message is as simple as this:
var message = MimeMessage.Load (fileName);
Sending the message is as simple as these few lines:
using (var client = new SmtpClient ()) {
client.Connect ("smtp.gmail.com", 465, true);
client.Authenticate ("username", "password");
client.Send (message);
client.Disconnect (true);
}
You're right, the inbuilt stuff doesn't offer a solution for this.
My advice would be to simply write a bit of code that uses TcpClient and StreamReader / StreamWriter to interact with the SMTP server. It shouldn't need more than 50 lines of code.
This is easy to do, you need only to install MailKit and MimeKit from nuget.
Pay attention because if you don't need authentication, setting "useSsl" to false is not enough, it doesn't work. You need to set MailKit.Security.SecureSocketOptions.None
var message = MimeMessage.Load("pathToEml");
using (var client = new MailKit.Net.Smtp.SmtpClient())
{
client.Connect("smtp.yourserver.yourdomain", 25, MailKit.Security.SecureSocketOptions.None); //set last param to true for authentication
//client.Authenticate("username", "password");
client.Send(message);
client.Disconnect(true);
}
It appears that .NET's SmtpClient is creating emails with an extra dot in host names if the dot was to appear at the beginning of a MIME encoded line (e.g. test.com sometimes shows up as test..com). Example code:
[TestMethod]
public void TestEmailIssue()
{
var mail = new System.Net.Mail.MailMessage();
var smtpClient = new System.Net.Mail.SmtpClient();
mail.To.Add("Test#test.com");
mail.Subject = "Test";
mail.From = new System.Net.Mail.MailAddress("test#test.com");
mail.Body = "Hello this is a short test of the issue:"
+" <a href='https://test.com/'>https://test.com/</a>: ";
smtpClient.PickupDirectoryLocation = "C:\\temp\\";
smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.SpecifiedPickupDirectory;
smtpClient.Send(mail);
}
This creates an .eml file that looks like this:
X-Sender: test#test.com
X-Receiver: Test#test.com
MIME-Version: 1.0
From: test#test.com
To: Test#test.com
Date: 6 Jul 2011 15:55:28 -0400
Subject: Test
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Hello this is a short test of the issue: https://test=
..com/'>https://test.com/:=20
When sending the file, or opening in Outlook (or any other program), the double dots show up (i.e. test..com). Note that if I remove the extra space (in "is a"), that test.com shows correctly since the dot no longer appears at the beginning of the line.
This causes a problem when trying to send website addresses, and we get calls from clients saying this they cannot click our links.
Has anyone else experienced this? How can we resolve this issue other than writing our own encoding?
This is actually per RFC 2821 (4.5.2 Transparency)
Before sending a line of mail text, the SMTP client checks the first character of the line. If it is a period, one additional period is inserted at the beginning of the line.
.Net is just storing the file in "ready to transmit" mode which means that it doesn't have to monkey with the email before sending, instead it can transmit it as is. Unfortunately this format isn't 100% the same as Outlook Express's EML format apparently. You should be able to set the encoding to UTF-8 (or something similar) and that will kick in Base-64 encoding for you.
mail.BodyEncoding = System.Text.Encoding.UTF8;
In .Net 2.0
X-Sender: test#test.com
X-Receiver: Test#test.com
MIME-Version: 1.0
From: test#test.com
To: Test#test.com
Date: 6 Jul 2011 21:29:04 +0100
Subject: Test
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Hello this is a short test of the issue: <a href=3D'https://test.com/'>https://test.com/</a>:=
It looks like it is wrapping the text at a certain character length per line. I vaguely remember there was an issue in .Net 2.0 where by default it doesn't do this which can cause problems with spam filters.
In fact increasing the size of the message gives the following in .Net 4.0:
X-Sender: test#test.com
X-Receiver: Test#test.com
MIME-Version: 1.0
From: test#test.com
To: Test#test.com
Date: 6 Jul 2011 21:34:21 +0100
Subject: Test
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Hello this is a short test of the sssssssssssssssssissue: <a hre=
f=3D'https://test.com/'>https://test.com/</a>:=20
Seems like a bug.
A workaround might be to change the BodyEncoding to something other than ASCII.
Looking at .NET 4 source code, maybe what you are experiencing has something to do with MailWriter.WriteAndFold method. Also in MailWriter class there is
static int writerDefaultLineLength = 76
variable, meaning character count per line. Maybe because you removed one extra space character, it started working.