I have a webpage which I would like users to be able to send to a friend at the click of a button. I am currently using Chilkat's MailMan but I keep getting intermittent problems with it. It seems occassionaly on the first attempt to mail it throws a null pointer exception. Then if try the exact same page again it sends no problem.
Are there any other components out
there that will do what I am trying
to do?
Would it be easier to right my
own light weight component to do it?
Has anyone had the above problem that
can be solved easily and then I don't
have to worry about the above?
EDIT:
Maybe I should clear something up. I know how to send emails. That is not the problem. The Chilkat component I was using could take in a webpage and put it into an email and send it. The person that receives it then has an email with all the CSS included and the pictures and everything in the email.
This is actually not a trivial exercise.
What you want to do, is download the HTML (which is the easy part). You then have to parse it, and extract all of the css references, and image references, and either:
Embed them into the email, or
Convert all links to absolute links.
When you look at all the bad HTML out there, you find out this isn't trival. The reason why I know this, is I wrote this functionality into aspNetEmail (www.aspNetEmail.com), and had to account for all sorts of bad HTML.
Could you use the WebClient class to get the webpage that the user is requesting? You'd want to change any relative links to absolute links (e.g. from "/images/logo.gif" to "http://myapp.com/images/logo.gif"), then take the output and use that as the body of the MailMessage object
i.e.
public void MailToAFriend(string friendMailAddress, Uri uriToEmail) {
MailMessage message = new MailMessage();
message.From = "your_email_address#yourserver.com";
message.To = friendEmailAddress;
message.Subject = "Check out this awesome page!";
message.Body = GetPageContents(uriToEmail);
SmtpClient mailClient = new SmtpClient();
mailClient.Send(message);
}
private string GetPageContents(Uri uri) {
var webClient = new WebClient();
string dirtyHtml = webClient.DownloadString(uri);
string cleanedHtml = MakeReadyForEmailing(dirtyHtml);
return cleanedHtml;
}
private string MakeReadyForEmailing(string html) {
// some implementation to replace any significant relative link
// with absolute links, strip javascript, etc
}
There's lots of resources on Google to get you started on the regex to do the replacement.
1) .NET comes with a reasonably adequate class for sending mail, in System.Net.Mail.
2) If it happens only rarely and does not repeat, just put it in a try block and retry two more times before considering it a failure. While it may sound crude, it's a very effective solution.
Related
I'm working with C# on Windows servers for a web application stored on the IIS Server.
I would like to create an eml file from :
an html content (string)
some attachments that are loaded in memory
a string subject
string recipients
string sender
The main problem is that I am not allowed to store files on the host server (not even in a temporary directory or if I delete them after).
I saw many threads explaining how to create an eml file with the help of SmtpClient. But we always need to use a directory to save the file.
Do someone knows a way to do that ? Or to create a directory in memory (which seems undoable) ?
Thanks for everyone who will read me
[EDIT]
Using jstedfast's answer below and the Mime documentation, I could figure a way. Here is a POC in case someone needs it later.
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Joey", "joey#friends.com"));
message.To.Add(new MailboxAddress("Alice", "alice#wonderland.com"));
message.Subject = "How you doin?";
var builder = new BodyBuilder();
// Set the plain-text version of the message text
builder.TextBody = #"Hey Alice,
What are you up to this weekend? Monica is throwing one of her parties on
Saturday and I was hoping you could make it.
Will you be my +1?
-- Joey
";
// We may also want to attach a calendar event for Monica's party...
builder.Attachments.Add("test.pdf", attachmentByteArray);
// Now we just need to set the message body and we're done
message.Body = builder.ToMessageBody();
using (var memory = new MemoryStream())
{
message.WriteTo(memory);
}
Look into using MimeKit.
You can write the MimeMessage objects to any type of stream that you want, including a MemoryStream.
I am using IMAP4 client called: MailKit.
It works great, but I have a problem on getting body of message without downloading the attachments. I want to show the mail's body text and also what attachments there are,
but only if a user clicks on the attachment I want to actually download the attachment.
I've tried:
var message = inbox.GetMessage(uid, cancel.Token);
But this gets the entire message.
Also tried:
uids[0] = uid;
var ms = inbox.Fetch(uids, MessageSummaryItems.BodyStructure , cancel.Token);
var bp1 = inbox.GetBodyPart(uid, ms.First().Body, cancel.Token);
But again this downloads the attachment.
With your sample code, you are downloading the entire message because you are requesting the top-level body part of the message.
MIME is a tree structure of "body parts". What you want to do is to traverse the ms.First().Body to find the part(s) that you want, and then download them individually using the GetBodyPart() method.
Take a look at MailKit.BodyPartMultipart, MailKit.BodyPartMessage, MailKit.BodyPartBasic and MailKit.BodyPartText.
A BodyPartMultipart contains other body parts.
A BodyPartMessage parts contains a message (which will also contain a body part).
A BodyPartBasic is a basic leaf-node body part - usually an "attachment".
A BodyPartText is a text part (a subclass of BodyPartBasic) which can either be an attached text part or what you might consider to be the main text of the message.
To figure out if a BodyPartBasic is meant to be displayed inline or as an attachment, what you need to do is:
if (part.ContentDisposition != null && part.ContentDisposition.IsAttachment)
// it is an attachment
else
// it is meant to be shown to the user as part of the message
// (if it is an image, it is meant to be displayed with the text)
I should probably add a convenience property to BodyPartBasic called IsAttachment to make this a bit simpler (I'll try to add it today).
Hope that helps.
Update: I've just added the BodyPartBasic.IsAttachment convenience property in git master, so the next release of MailKit will have it.
This IMAP command will return just the text body.
a1 uid fetch <uid> (body.peek[text])
-Rick
This is working fine locally but when I sent it to another person in the company (same exchange server) using Outlook on a mac, it does not work correctly. Instead, the image is replaced with the text ATT00001 and the image becomes an attachment called ATT0001
It was tricky to get this working in the first place, here is the code I use:
var assembly = Assembly.GetExecutingAssembly();
var stream = assembly.GetManifestResourceStream("EmailManager.Kitten.jpg");
var inlineLogo = new LinkedResource(stream, "image/jpg");
inlineLogo.ContentId = "CompanyLogo";
body = body.Replace("{logourl}", string.Format("cid:{0}", inlineLogo.ContentId));
var view = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
view.LinkedResources.Add(inlineLogo);
mailMessage.Body = body;
mailMessage.Subject = "Check out the kitty logo";
mailMessage.AlternateViews.Add(view);
mailMessage.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient(....);
smtp.Send(mailMessage);
The body is just a string of stuff with an <img src='{logourl}' /> in it.
Any suggestions of what I might do to fix or debug this? Alternatively is there a way to link to an external image without outlook blocking it by default (eg. having it come from the same server or similar).
Edit: I've read something about macs wanting the attachments listing at the end of the e-mail, could this be it? Although there is no way I can see from the above how to specify this behaviour. Also I am not entirely sure it's the problem.
can be one of the possible solution
i have found answer .bin file comes when _EmailLogo1 and
_EmailLogo are empty so need to check if it's empty/NULL or not !! if not empty/NULL then it should be linked otherwise don't !!
dynamic htmlView = AlternateView.CreateAlternateViewFromString(_Body.ToString(), null, "text/html");
if (!string.IsNullOrEmpty(_EmailLogo1)) {
LinkedResource logo = new LinkedResource(_EmailLogo);
logo.ContentId = "logo2";
htmlView.LinkedResources.Add(logo);
}
if (!string.IsNullOrEmpty(_EmailLogo))
{
LinkedResource logo1 = new LinkedResource(_EmailLogo1);
logo1.ContentId = "logo1";
htmlView.LinkedResources.Add(logo1);
aMessage.AlternateViews.Add(htmlView);
}
Some email clients are smart enough to display correctly whereas others require you to be very specific with your AlternateView and LinkedResource. Have you tried with other email clients e.g. Windows Live Mail?
Try specifying the ContentType of your AlternateView:
view.ContentType = new ContentType("text/html");
I had the same issue where Outlook did the same, displayed the image as an unnamed attachment however Windows Live Mail worked perfectly.
Fast forward to when we moved our SMTP server to Mandrill and we hit the same issue for all email clients where emails displayed as unnamed attachments and it turned out we didn't specify one of our ContentType's and it defaulted to "application/octet-stream"
I know that this question is a bit old, but I have noticed that some issues occur when you use ' instead of " wrapping the source.
Try instead to write it like this <img src="{logourl}" />
Hope this helps someone.
Why when i send html email it looks like:
but initial page is:
Here is code:
MailMessage message = new MailMessage();
message.IsBodyHtml = true;
message.Subject = subject;
message.Body = body;
foreach (MailAddress recipient in recipients)
{
message.To.Add(recipient);
}
if (message.To.Count > 0)
{
SmtpClient smtp = new SmtpClient();
smtp.Send(message);
return true;
}
Html file contains css in head.
http://pastebin.com/r5V6X4Ld
I assume that the body variable only contains the HTML code, but not the CSS or the images, because both are separate files.
Basically, you need to attach the images to the mail and change the HTML code of the body to point to the correct location. See here for more info and sample code.
This might also be helpful: http://www.alistapart.com/articles/cssemail/
Problem:
Some clients rendered my email with no style whatsoever. I first attributed this to the stripping of styles, but I then discovered that the styles were clearly visible in the source code. I subsequently spent a good deal of time attempting to uncover the culprit, testing countless versions of the email. Alas, the problem was right under my nose: the styles weren’t being stripped — the dots (.) preceding their names were. Therefore, “.Feature {}” became “Feature {}”, resulting in a meaningless style definition.
Solution:
I used class selectors, which ensured that each style would begin with a letter instead of a dot. So “.Feature {}” would become “td.Feature {}” or “div.Feature {}” (depending on the application). A somewhat mundane fix, but effective and (again) compliant.
You have to refer your image with full path ie www.yourdomain/imagename.jpg etc and also have to give the class as inline styles
I have a requirement to send emails containing both text and Images.
So, I have .mhtml file that contains the content that needs to be emailed over.
I was using Chilkat for this, but in outlook 2007 it is showing the mhtml file as different attachments(html+images).
Can anyone suggest me some other component for sending mhtml emails.
FYI, I am using .Net 3.5
Also, I do not want to save the images on server before sending them.
Thank you!
I use plain old native MailMessage class. This previous answer can point you in right direction
EDIT: I built a similiar code some time ago, which captures an external HTML page, parse it's content, grab all external content (css, images, etc) and to send that through email, without saving anything on disk.
Here is an example using an image as an embedded resource.
MailMessage message = new MailMessage();
message.From = new MailAddress(fromEmailAddress);
message.To.Add(toEmailAddress);
message.Subject = "Test Email";
message.Body = "body text\nblah\nblah";
string html = "<body><h1>html email</h1><img src=\"cid:Pic1\" /><hr />" + message.Body.Replace(Environment.NewLine, "<br />") + "</body>";
AlternateView alternate = AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html);
message.AlternateViews.Add(alternate);
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream("SendEmailWithEmbeddedImage.myimage.gif")) {
LinkedResource picture = new LinkedResource(stream, MediaTypeNames.Image.Gif);
picture.ContentId = "pic1"; // a unique ID
alternate.LinkedResources.Add(picture);
SmtpClient s = new SmtpClient();
s.Host = emailHost;
s.Port = emailPort;
s.Credentials = new NetworkCredential(emailUser, emailPassword);
s.UseDefaultCredentials = false;
s.Send(message);
}
}
System.Net would be the one that you are looking for.<br/>
MailMessage is used to compose new mail.<br/>
SMTPClient is used to send mail.
NetworkCredentials would be used to attach username and password for making request to sending mail.
Coming to your question how to add images.
You need to set isHtml=true for MailMessage
Since you want to send mail relative paths in the html won't work like ../directory/imagename.formate
in such case you need to give completed path to the image location that's websiteUrl/directory/imagename.formate
To get complete Url dynamically you can use like this Request.Uri.GetLeftParth(URIPartial.Authority)+VitrtualToAbsolute.getAbsolute("~")
I'm not sure about last line since I have wrote directly over here. You just need to use it and have good luck ;-)
You need to explicitly set the MIME type to multipart/related. Change the MailMessage.Body to include the content of the MHTML file in it. Finally add a new item to the MailMessage.AlternateViews collection to define the correct MIME type. The following link from MSDN has a very good example how to set it up:
MailMessage.AlternateViews Property