I want to send a password email to a user, however the customer wants an image embedded (inline) in the email.
I created an email, saved the data to a txt file, during my code I read in the template but when I send it the line endings are broken and therefore the MIME data is broken. I just get =3D
What am I doing wrong?
string FILENAME = Server.MapPath("~/GuestUserTemplate.txt");
StreamReader objStreamReader = File.OpenText(FILENAME);
string sEmailTemplate = "";
string input = null;
while ((input = objStreamReader.ReadLine()) != null)
{
sEmailTemplate = sEmailTemplate + input;
}
objStreamReader.Close();
/* send an email */
MailMessage msg = new MailMessage();
msg.IsBodyHtml = true;
msg.To.Add(new MailAddress(sToEmail));
msg.From = new MailAddress(sFromEmail);
msg.Subject = sEmailSubject;
msg.Body = sEmailTemplate;
//try
{
client.Send(msg);
}
//catch (Exception excm)
{
}
Just done a bit more detective work. The email I am sending out has this in the header:
MIME-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Where as an email which has inline images has:
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type: multipart/related;
boundary="----_=_NextPart_001_01C9C98D.6552117E";
type="multipart/alternative"
It seems that I need to set the Content type to multipart but I am not sure how...
I'm not quite sure what kind of text you are loading (and appending to what?) but I would recommend you create a real template, e.g. your email text with placeholders that will be replaced with user's name, etc.
Use <img src="cid:logo.png" /> - for the inline image in the HTML body of the message (in your template).
You will then need to add the corresponding image to the LinkedResources collection of the MailMessage and set its ContentID header to "logo.png" or whatever you call it. After that go and send your mail (multipart content type will be set automatically for you based on the structure of the mail message).
P.S.: use SendAsync() or write the mail to the local pickup queue of your own smtp server, otherwise you tie up your ASP.NET worker thread. Connecting to remote smtp servers/web services etc. takes a considerable amount of time (compared to the request execution time) and the worker thread is sitting there waiting and unable to service other incoming requests.
You should use System.Net.Mail. Create a MailMessage, then add an attachment and send with SmtpClient.
Check your text file - it may be missing the expected line ending (Cr + Lf).
Change the while loop from:
while ((input = objStreamReader.ReadLine()) != null)
{
sEmailTemplate = sEmailTemplate + input;
}
To:
sEmailTemplate = sEmailTemplate + objStreamReader.ReadToEnd();
The bottom line is that you can't do this with System.Net.Mail.
Here is the problem you are running into.
Encodings.
Your orignal mail was saved with the quoted-printable encoding (hence the "=3D"s you are seeing) When you re-read this into the message, these will get double encoded. Encodings are using for protecting the message during SMTP transport.
Boundaries.
When a message is created, boundaries are used in the headers to tell the mail client the boundaries of different parts of the message. You are trying to take boundaries of one message, and merge them into a new message. Since System.Net.Mail doesn't give you enough control over the internal boundaries, you can't do this.
If you want to send an embedded image using System.Net.Mail, you will need to create the message using a Linked Resource. Here is a link with more:
http://systemnetmail.com/faq/4.4.aspx
Related
I have a complex email template that contains many div, section and other HTML elements. The HTML template has reference to CSS(uploaded to server). I am using the below code to send HTML email via MailKit :
var message = new MimeMessage();
var bodyBuilder = new BodyBuilder();
bodyBuilder.HtmlBody = File.ReadAllText(pathToHtmlFIle);
message.Body = bodyBuilder.ToMessageBody();
client.Send(message);
But the client only receives everything in plain-text, no colors, no formatting. Is this the expected result ?
I think you need to use either inline CSS or CSS embedded in the head section. Since most webmail clients block links to external stylesheets, it is rare to see this method employed in an email.
After struggling a lot with this topic, I finally figure out the error was the double quotes inside the html...Use notepad++ to replace (quick launched with ctrl+f) all " for '. Holy remedy, after only receiving plain/text I finally received the text/html.
PD: Do not use bootstrap nor try to link an external source 'cause mail clients block external css providers. Use strictly style attributes for all tags.
Read multiple posts about .net mail delivery notifications and tested multiple things:
Trying to send mail via SMTP. No mails arrives and no exception error
https://msdn.microsoft.com/en-us/library/system.net.mail.smtpfailedrecipientsexception.aspx
How to check MailMessage was delivered in .NET?
https://www.emailarchitect.net/easendmail/sdk/html/o_deliverynotificationoptions.htm
http://forums.asp.net/p/1189023/2038523.aspx
Though I'm still stuck. What I want to accomplish is the following: I only want to know if the email-address which the mail is send to is valid, and not valid as in a valid format but valid as in: does the email address exist.
Sometimes a user will send an email to an address but by accident types 1 letter wrong, the mail is valid since it contains a domain and # but the mail address doesn't exist. The sender will think it has been send correctly since they didn't receive any notification.
I want to make sure the sender gets the undelivered notification.
When using code to send mails through Outlook for example you automatically get a undelivered message if the mail address doesn't exists, however with SMTP (I am) not so lucky. I tried it with this bit of code:
using (var msg = new MailMessage())
using (var client = new SmtpClient("spamfilter.mySpamFilter.com", 587))
{
msg.IsBodyHtml = true;
msg.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
msg.From = new MailAddress(FromAddress);
msg.To.Add(TO);
msg.Body = Body;
msg.Subject = Subject;
//Send mail
try
{
client.Send(msg);
}
catch (SmtpFailedRecipientsException ex)
{
throw ex;
}
}
For the To address I created an address that is 100% invalid. Though, the exception is never reached.
Can the spamfilter be the problem? For example, when I check the spamfilter I can see the messages have the refused send status for the invalid email addresses but the action status is allowed (so no spam). So it looks like the spamfilter never returns the exception back to the code.
Or is it just not possible what I want to achieve?
Spamfilter:
I dont think that you will get an error here because the To Method takes either an string or an MailAdress which will also takes an string as input.
So every Adress will be accepted here.
Have you tried to place some not allowd characters like ' " % or something like this?
I guess you will get an exception here.
Everything else will be forwared to the smtp and the he will take care of the delivery and not your C# Code.
Regards
Andre
I am having an issue testing alternate views while sending HTML E-Mails. I am creating sending the mail message as plain text, but I include an HTML alternate view. I have tried using several e-mail clients, but I have been unable to see the plain text version. My main concern is that someone who does use a plain text only client won't see it correctly. See below for code:
MailMessage message = new MailMessage();
message.To.Add("email");
message.From = new MailAddress("fromaddress");
message.Subject = "subject"
//Plain text version of e-mail
message.Body = _formattedPlainText;
message.IsBodyHtml = false;
AlternateView htmlView = CreateHTMLView();
message.AlternateViews.Add(htmlView);
//message.AlternateViews.Add(plainTextView);
smtp.Send(message);
private AlternateView CreateHTMLView()
{
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(_formattedHTML, null, System.Net.Mime.MediaTypeNames.Text.Html);
//Code for adding embedded images...
return htmlView;
}
Is there reason to believe the plain text version isn't being received or are there any clients you know that definitely can only receive plain text e-mails?
Thanks in advance
UPDATE:
You can force plain text in GMAIL by pressing the options arrow and selecting the option "Message Text Garbled?"
Is there reason to believe the plain text version isn't being received
or are there any clients you know that definitely can only receive
plain text e-mails?
No, and PINE.
You could use the mail command in any *nix OS to read email. It will only display email in text format.
UPDATE
A guy here, claims that GMAIL ONLY displays emails in plain text if given the option. I find that an awkward default choice from Google if that's still the case.
Through some experimentation I have had best results this way:
Set up two alternate views, one HTML and one plain text.
Then, leave the MailMessage.Body alone (default/undefined) and
leave the MailMessage.IsBodyHtml at default. My code segment:
myMessage.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(HtmlMessage, new System.Net.Mime.ContentType("text/html")));
myMessage.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(TextMessage, new System.Net.Mime.ContentType("text/plain")));
// myMessage.Body = HtmlMessage;
// myMessage.IsBodyHtml = true;
myClient.UseDefaultCredentials = false;
NetworkCredential credentials = new NetworkCredential("xxxx","xxxxx");
myClient.Credentials = credentials;
myClient.DeliveryMethod = SmtpDeliveryMethod.Network;
I have tested this with messages sent to Windows Outlook clients and to Mac users, and it seems to work just fine. The email client software chooses the view. I still need to test how this works for clients such as webmail apps. Your mileage may vary.
Bob
I'm trying to add a List-Unsubscribe header to my e-mail that is being sent. So far I hadn't any luck trying to do so.
What I have got so far:
var mailMessage = new MailMessage
{
Subject = newsletter.Subject,
Body = newsLetterHTML,
IsBodyHtml = true,
Sender = new MailAddress(senderAddress)
};
mailMessage.To.Add(subscriber.Email);
mailMessage.ReplyToList.Add(senderAddress);
mailMessage.Headers.Add("List-Unsubscribe", unSubscribeUrl);
The unSubscribeUrl is something like 'www.example.com/unlist?id=8822772727'.
When I sent the e-mail everything works fine except for the list-unsubscribe option. Which is not shown in any mail client.
Any assistance would be welcome!
UPDATE
This is the whole code I use for sending the email:
var mailMessage = new MailMessage
{
Subject = newsLetter.Subject,
Body = newsLetterHTML,
IsBodyHtml = true,
Sender = new MailAddress(senderAddress)
};
mailMessage.To.Add(subscriber.Email);
mailMessage.ReplyToList.Add(senderAddress);
mailMessage.Headers.Add("List-Unsubscribe", String.Format("<{0}>", "http://www.foo.com/unlist?id=8888"));
mailMessage.HeadersEncoding = Encoding.Default;
var smtpClient = new SmtpClient();
smtpClient.Send(mailMessage);
UPDATE 2
After a little research I got the header into the mailMessage. When I sent an email I can see the following headers:
List-Unsubscribe: <http://demo.localhost/home/hobbymap-gerard/afmelden-voor-nieuwsbrief?id=c786aeb0-554d-4670-94d8-82d6f25a050b>
MIME-Version: 1.0
From: info#test.nl
To: test#gmail.com
Reply-To: info#test.nl
Date: 8 Feb 2011 09:50:22 +0100
Subject: Test met plaatje
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
But when I open the email in any client I can't see the unsubscribe button in the client? Am I doing something else wrong?
Most email clients only support mailto-links.
Try this, it should work always:
mailMessage.Headers.Add("List-Unsubscribe", "<mailto:list#host.com?subject=unsubscribe>");
The RFC specifies it is possible to use http-links also.
But i've found that if you include http-links, the email clients no longer shows the unsubscribe link. I think it's because of the possibility that people only have access to the mail protocol.
So this does not always work:
mailMessage.Headers.Add("List-Unsubscribe", "<http://www.host.com/list.cgi?cmd=unsub&lst=list>, <mailto:list-request#host.com?subject=unsubscribe>";
According to the List-Unsubscribe website, the URL should be wrapped with angle brackets, e.g. <https://www.example.com/unlist?id=8822772727>.
You can try something like:
mailMessage.Headers.Add("List-Unsubscribe", String.Format(
CultureInfo.InvariantCulture, "<https://{0}>", unSubscribeUrl));
To ensure you are not flagged as spam make sure to have an SSL Certified domain.
In addition to other answers, there is also RFC-8058 that requires another header to enable HTTPS link unsubscribe functionality:
List-Unsubscribe:<https://example.com/unsubscribe.html?opaque=123456789>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
List-Unsubscribe-Post header should have a value List-Unsubscribe=One-Click. This is to prevent accidental unsubscribe by anti-spam software and allow an extra step of displaying a web page with an unsubscribe button.
Some email client will not process List-Unsubscribe links without List-Unsubscribe-Post header.
I am dispatching emails at clients, notifying them for specific content deliveries and I have a problem with the containing ftp uri in mail body. I am constructing the ftp uri alongside with ftp credentials in the following format, but the credentials part is stripped away (the section user:pass#):
ftp://user:pass#server/relativepath/filename
The code is something like that:
mailTemplate += String.Format("File FTP URI: {1}<br>",
new Uri(ftpBaseLink, filename), filename);
and the email is dispatched with the following matter:
MailMessage message = new MailMessage(
mailSettings.Smtp.From,
mailTo,
subject,
mailMessage) { IsBodyHtml = true };
SmtpClient client = new SmtpClient();
client.Send(message);
Is there any clue how can I override this "normalization"?
I think that there was a general "tightening" of security a while back because of the way URLs containing user:pass were being mis-used to fool people into thinking they were clicking on a link to http://www.mybank.com when the link itself was http://www.mybank.com:blah#www.adodgysite.com/fake_bank_site. Users are wiser now, but it may be that its this "lockdown" that is affecting you.
My suggestion would be to concatenate the URI yourself, without using Uri
off the top, i'd look into what 'new Uri(ftpBaseLink, filename)' becomes as a string.