Recently we have faced a situation to send a html formatted mail in our asp.net mvc application. We want to provide an option to users to open their html formatted mails in outlook because user can edit the mail and can send it to their outlook contacts.Pramod tell me an idea it was quite enough to solve our problem.we have take the html from our template view and send it through smtpClient. we have used pickupDirectory option of webmail, using this we can send mail in to a particular directory, it will save as a .eml file. A custom action result will do all this things and download it as an outlook file. now user can send it by opening it in outlook
Here is the custom action result
public class MailResult : ActionResult {
string _content;
string _viewName;
string _contentType = "message/rfc822";
dynamic _model;
string _fromMailAddress;
string _toMailAddress;
public MailResult(string AViewName,dynamic AModel,string AFromMail,string AToMail) {
_viewName = AViewName;
_model = AModel;
_fromMailAddress = AFromMail;
_toMailAddress=AToMail;
}
public override void ExecuteResult(ControllerContext context)
{ var view = ViewEngines.Engines.FindView(context, _viewName, null);
var ViewData = new ViewDataDictionary();
var TempData = new TempDataDictionary();
ViewData.Model = _model;
using (var writer = new StringWriter())
{
var ccontext = new ViewContext(context, view.View, ViewData, TempData, writer); ViewData.Model = _model;
view.View.Render(ccontext, writer);
writer.Flush();
_content = writer.ToString();
}
System.Net.Mail.MailMessage msg = new MailMessage();
msg.From = new MailAddress(_fromMailAddress);
msg.To.Add(new MailAddress(_toMailAddress));
msg.IsBodyHtml = true;
msg.Body = _content;
SmtpClient smtp = new SmtpClient();
smtp.PickupDirectoryLocation
= context.HttpContext.Request.ServerVariables["APPL_PHYSICAL_PATH"];
smtp.PickupDirectoryLocation = smtp.PickupDirectoryLocation + @"\Content\Mail\"; Guid newGuId = Guid.NewGuid();
string fname = smtp.PickupDirectoryLocation + newGuId + ".eml";
//Save is an Extension method, using this we can specify the guid in to that ie; for deleting msg.Save(fname);
context.HttpContext.Response.Clear();
context.HttpContext.Response.AddHeader("Content-Disposition",string.Format("attachmen t; filename={0}", "mail.eml"));
context.HttpContext.Response.Charset = "";
context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.HttpContext.Response.ContentType = _contentType
context.HttpContext.Response.TransmitFile(fname);
context.HttpContext.Response.End();
System.IO.File.Delete(fname);
}
}
Extension Method:
(extension method source: codeproject)
public static class MailMessageExt
{
public static void Save(this MailMessage Message, string FileName)
{
Assembly assembly = typeof(SmtpClient).Assembly;
Type _mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (FileStream _fileStream = new FileStream(FileName, FileMode.Create))
{
// Get reflection info for MailWriter contructor
ConstructorInfo _mailWriterContructor = _mailWriterType.GetConstructor( BindingFlags.Instance | BindingFlags.NonPublic,null,new Type[] { typeof(Stream) }, null);
// Construct MailWriter object with our FileStream
object _mailWriter = _mailWriterContructor.Invoke(new object[] { _fileStream }); // Get reflection info for Send() method on MailMessage
MethodInfo _sendMethod
= typeof(MailMessage).GetMethod("Send",BindingFlags.Instance | BindingFlags.NonPublic); // Call method passing in MailWriter
_sendMethod.Invoke(Message,BindingFlags.Instance | BindingFlags.NonPublic, null,new object[] { _mailWriter, true },null);
// Finally get reflection info for Close() method on our MailWriter
MethodInfo _closeMethod = _mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
// Call close method
_closeMethod.Invoke(_mailWriter,BindingFlags.Instance | BindingFlags.NonPublic, null,new object[] { },null);
}
}
}