Send already generated MHTML using CDOSYS through C#? - c#

I have a ready generated MHTML as a byte array (from Aspose.Words) and would like to send it as an email. I'm trying to do this through CDOSYS, though am open to other suggestions. For now though I have the following:
CDO.Message oMsg = new CDO.Message();
CDO.IConfiguration iConfg = oMsg.Configuration;
Fields oFields = iConfg.Fields;
// Set configuration.
Field oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendusing"];
oField.Value = CDO.CdoSendUsing.cdoSendUsingPort;
oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserver"];
oField.Value = SmtpClient.Host;
oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"];
oField.Value = SmtpClient.Port;
oFields.Update();
//oMsg.CreateMHTMLBody("http://www.microsoft.com", CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
// NEED MAGIC HERE :)
oMsg.Subject = warning.Subject; // string
oMsg.From = "system#example.com";
oMsg.To = warning.EmailAddress;
oMsg.Send();
In this snippet, the warning variable has a Body property which is a byte[]. Where it says "NEED MAGIC HERE" in the code above I want to use this byte[] to set the body of the CDO Message.
I have tried the following, which unsurprisingly doesn't work:
oMsg.HTMLBody = System.Text.Encoding.ASCII.GetString(warning.Body);
Anybody have any ideas how I can achieve what I want with CDOSYS or something else?

Please don't use CDO, it dates from an era when computers still used smoke signals to exchange emails. System.Net.Mail contains everything you need, MailMessage is your friend. Note its IsBodyHtml property.

It is possible via CDO.Message (it is necessary add to project references COM library "Microsoft CDO for Windows 2000 Library"):
protected bool SendEmail(string emailFrom, string emailTo, string subject, string MHTmessage)
{
string smtpAddress = "smtp.email.com";
try
{
CDO.Message oMessage = new CDO.Message();
// set message
ADODB.Stream oStream = new ADODB.Stream();
oStream.Charset = "ascii";
oStream.Open();
oStream.WriteText(MHTmessage);
oMessage.DataSource.OpenObject(oStream, "_Stream");
// set configuration
ADODB.Fields oFields = oMessage.Configuration.Fields;
oFields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value = CDO.CdoSendUsing.cdoSendUsingPort;
oFields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value = smtpAddress;
oFields.Update();
// set other values
oMessage.MimeFormatted = true;
oMessage.Subject = subject;
oMessage.Sender = emailFrom;
oMessage.To = emailTo;
oMessage.Send();
}
catch (Exception ex)
{
// something wrong
}
}

Related

How do you create a PDF after submitting a form and attach it to an automated email in ASP.NET MVC C#?

I am having the hardest time figuring out how to create a pdf and attach it to an automated email. I thought it wouldn't be that hard but have quickly found out that it is much more complex than I imagined. Anyways, what I am doing is I have an order form, and when the customer fills out an order and submits it, I want it to generate a PDF for that order and attach it to an automated confirmation email. I am currently using Rotativa to generate the pdf and if I just ran the action result for generating it, it works perfectly fine which looks something like this:
public ActionResult ProcessOrder(int? id)
{
string orderNum = "FulfillmentOrder" + orderDetail.OrderID + ".pdf";
var pdf = new ActionAsPdf("OrderReportPDF", new { id = orderDetail.OrderID }) { FileName = orderNum };
return pdf;
}
When I added the function to send an automated email after the order form was submitted, that works perfectly fine with just the email by itself. But I can't seem to figure out how to generate the pdf and attach it to the email. The report view that gets the data from the order form is called "OrderReportPDF". My order form is called "Checkout", but the action result I use for this is called "Process Order". I've taken out the code in this function that is for the order form as it is not applicable. The section of my code for sending the email after the form is submitted is:
public ActionResult ProcessOrder(int? id)
{
//Send a confirmation email
var msgTitle = "Order Confirmation #" + orderDetail.OrderID;
var recipient = JohnDoe;
var fileAttach = //This is where I can't figure out how to attach//
var fileList = new string[] { fileAttach };
var errorMessage = "";
var OrderConfirmation = "Your order has been placed and is pending review." +
" Attached is a copy of your order.";
try
{
// Initialize WebMail helper
WebMail.SmtpServer = "abc.net";
WebMail.SmtpPort = 555;
WebMail.UserName = recipient;
WebMail.Password = "12345";
WebMail.From = "orders#samplecode.com";
// Send email
WebMail.Send(to: "orders#samplecode.com",
subject: msgTitle,
body: OrderConfirmation,
filesToAttach: fileList
);
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
//5. Remove item cart session
Session.Remove(strCart);
return View("OrderSuccess");
}
I have been able to find very few articles on this issue using Rotativa and the ones I have found don't work for what I'm doing. Maybe Rotativa won't work for this, I'm hoping it does because I've designed my pdf report it generates from it, and not sure if doing it another way will screw up my formatting of it or not. As you can see at the bottom of the code, I return the view to an "OrderSuccess" page. When I try to implement the first code into the second code, it won't let me "return pdf" to execute the ActionAsPdf that generates the pdf when I do the "return View("OrderSuccess")". It only lets me do one or the other. If anybody knows how I can accomplish this, I need some help. I appreciate any suggestions or feedback. I'm pretty new to this so please be patient with me if I don't understand something.
Here is the updated code that fixed my problem and created the pdf, then attached it to an automated email once the order form was submitted:
public ActionResult ProcessOrder(int? id)
{
//1. Generate pdf file of order placed
string orderNum = "FulfillmentOrder" + orderDetail.OrderID + ".pdf";
var actionResult = new Rotativa.ActionAsPdf("OrderReportPDF", new { id = orderDetail.OrderID }) { FileName = orderNum };
var PdfAsBytes = actionResult.BuildFile(this.ControllerContext);
//2. Send confirmation email
var msgTitle = "Order Confirmation #" + orderDetail.OrderID;
var OrderConfirmation = "Your order has been placed and is pending review.<br />" +
" Attached is a copy of your order." +
using (MailMessage mail = new MailMessage())
{
mail.From = new MailAddress("orders#samplecode.com");
mail.To.Add("orders#samplecode.com");
mail.Subject = msgTitle;
mail.Body = OrderConfirmation;
mail.IsBodyHtml = true;
//STREAM THE CONVERTED BYTES AS ATTACHMENT HERE
mail.Attachments.Add(new Attachment(new MemoryStream(PdfAsBytes), orderNum));
using (SmtpClient smtp = new SmtpClient("abc.net", 555))
{
smtp.Credentials = new NetworkCredential("orders#samplecode.com", "password!");
smtp.EnableSsl = true;
smtp.Send(mail);
}
}
//3. Remove item cart session
Session.Remove(strCart);
return View("OrderSuccess");
}
Thank you again to the people that helped and got me pointed in the right direction! Also, a quick shout out to #Drewskis who posted this answer in convert Rotativa.ViewAsPdf to System.Mail.Attachment where I was able to use it to solve my issue!

Converting to doc file in ASP.NET Core app and attaching doc file to email

I am trying to convert some data I get from my database in my ASP.NET application. So far I came across a very straight forward framework to do that called DocX.
https://www.nuget.org/packages/DocX/
So according to its API I decided that the best way to implement my task would be to first make a documents and save it to server. Then import it from server as stream and attach it to email. But I a doubtfull.
So I go:
var doc = DocX.Create("test.doc");
string f = "sdcdscdsc";
doc.InsertParagraph(f);
doc.Save();
Two things happen here:
1) First I get an exception FileNotFoundException: Could not load file or assembly 'System.IO.Packaging
2) Somehow... when I tried another framework for doing this DocumentCore (https://www.nuget.org/packages/sautinsoft.document/), I guess that installed a missing file and the Save() method started working and saving the file but the files where blank.
Honestly I would really appreciate on best practices to do this task. If anyone has come across similar task please share the methodology used.
The second part is a bit easier. I got the email part sorted but still got no idea how to attach the file. So far the code looks like this:
private static void SendMail()
{
var mailMessage = new MailMessage("xxxxxx#gmail.com", "xxxxxx#gmail.com");
mailMessage.Subject = "Tester ";
mailMessage.Body = "This is the message";
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.Credentials = new System.Net.NetworkCredential()
{
UserName = "xxxxxxxx#gmail.com",
Password = "xxxxxxxxx"
};
client.EnableSsl = true;
client.Send(mailMessage);
}
Overall it in bits and pieces and I would really appreciate some sharing of experience. Thank you very much.
Part 1 - create doc with content
Had to use DocXCore for ASP.NET Core app.
private void CreateDocument()
{
try
{
var doc = DocX.Create("mytest.docx");
doc.InsertParagraph("Hello my new message");
doc.Save();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
Part 2 - sending email
private void SendMail()
{
var mailMessage = new MailMessage("xxxxx#gmail.com", "yzolxxxxxotarev#gmail.com");
mailMessage.Subject = "Tester ASP.NET Boat Inspector";
mailMessage.Body = "This is the message";
var contentPath = _env.ContentRootPath+#"\mytest.docx";
Attachment data = new Attachment(contentPath, MediaTypeNames.Application.Octet);
mailMessage.Attachments.Add(data);
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.Credentials = new System.Net.NetworkCredential()
{
UserName = "xxxxx#gmail.com",
Password = "xxxxx"
};
client.EnableSsl = true;
client.Send(mailMessage);
}
Works well.

SSIS script task issue

Using SSDT for Visual Studio 2013 am sending e-mail notifications via ssis script using SmtpClient class.
public void Main()
{
SmtpClient v_EmailClient;
string v_From = Dts.Variables["User::vFrom"].Value.ToString();
string v_To = Dts.Variables["User::vTo"].Value.ToString();
string v_EnvNameToSubject = Dts.Variables["User::vEnvNameToSubject"].Value.ToString();
MailMessage v_EmailMessage = new MailMessage(v_From, v_To);
v_EmailMessage.IsBodyHtml = true;
v_EmailMessage.Subject = v_EnvNameToSubject + "SSIS email notification";
//Concatenation of variable with the standard message does not work
v_EmailMessage.Body = "Message text";
v_EmailClient = new SmtpClient("SmtpServer");
v_EmailClient.UseDefaultCredentials = true;
v_EmailClient.Send(v_EmailMessage);
Dts.TaskResult = (int)ScriptResults.Success;
}
When I try to concatenate the variable v_EnvNameToSubject with the standard subject text does not work. I tried to use try catch block to find out the actual error message and that did not help either.
First, check your variables names (and cases) vFrom , vTo , vEnvNameToSubject because they are case sensitive.
Second, Try concatenating these strings another way (Using String.Concat() Function or using a stringbuilder):
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendLine(v_EnvNameToSubject);
sb.AppendLine("SSIS email notification");
v_EmailMessage.Subject = sb.ToString();
Or
v_EmailMessage.Subject = String.Concat(v_EnvNameToSubject,"SSIS email notification")
Third, Check your variables scope and that they are added to the script task ReadOnly Variables

Replace not working as expected, razor engine inserting unwanted periods

I have a class that uses the razor engine to generate html templates and there seems to be an issue where some links (anchors or images) have an additional period inserted into the address, usually at the www. part making the link unusable.
There doesn't appear to be any rhyme or reason as to when or where it does this, sometimes it works fine, other times several of the links have this issue.
So when I return the template as string to then send as an email I call replace like below:
var fixedTemplate = template.Replace("www..", "www.");
But this isn't working. I've never ran into this issue before. The strings are quite large, could this cause problems with the replace function?
How can I
a) Fix the razor engine so that these random periods are no longer added in links
Or
b) Find out why the replace function isn't replacing all of the occurrences.
A sample of the code called in my class below for completeness.
// nt = class associated with template
using (TemplateService templateService = new TemplateService())
{
string html = templateService.Parse(File.ReadAllText(nt.TemplateFilePath), nt, null, null);
var pm = new PreMailer.Net.PreMailer(html);
//inline css styles with premailer
Emailer.SendTestEmail(pm.MoveCssInline().Html, emailAddress, "Test Email: " + campaign.Title);
pm = null;
}
And the emailer code where replace is called
public static void SendTestEmail(string template, string emailAddress, string subject)
{
var updatedTemplate = template.Replace("www..", "www.");
var email = new MailMessage
{
Body = updatedTemplate,
Subject = subject,
IsBodyHtml = true,
From = new MailAddress("noreply#mydomain.com")
};
email.To.Add(emailAddress);
using (var smtpClient = new SmtpClient())
{
smtpClient.PickupDirectoryLocation = "M:\\Pickup";
smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
smtpClient.Send(email);
}
}

Problem with FaxComExLib

I can successfully fax messages using FAXCOMLib. Now I try to use FAXCOMEXLib, but I have problems with that:/
This is the code (from MSDN VB example):
try
{
FaxServer objFaxServer = new FaxServer();
FaxDocument objFaxDocument = new FaxDocument();
object JobID;
objFaxServer.Connect(Environment.MachineName);
objFaxDocument.Body = "test.bmp";
objFaxDocument.DocumentName = "Test name";
objFaxDocument.Recipients.Add("xxxxxxx", "Name");
objFaxDocument.AttachFaxToReceipt = true;
objFaxDocument.CoverPageType = FAXCOMEXLib.FAX_COVERPAGE_TYPE_ENUM.fcptSERVER;
objFaxDocument.CoverPage = "generic";
objFaxDocument.Note = "Here is the info you requested";
objFaxDocument.ReceiptAddress = "someone#example.com";
objFaxDocument.ReceiptType = FAXCOMEXLib.FAX_RECEIPT_TYPE_ENUM.frtMAIL;
objFaxDocument.ScheduleType = FAXCOMEXLib.FAX_SCHEDULE_TYPE_ENUM.fstNOW;
objFaxDocument.Subject = "Today's fax";
objFaxDocument.Sender.Title = "Mr.";
objFaxDocument.Sender.Name = "Bob";
objFaxDocument.Sender.City = "Cleveland Heights";
objFaxDocument.Sender.State = "Ohio";
objFaxDocument.Sender.Company = "Microsoft";
objFaxDocument.Sender.Country = "USA";
objFaxDocument.Sender.Email = "someone#microsoft.com";
objFaxDocument.Sender.FaxNumber = "12165555554";
objFaxDocument.Sender.HomePhone = "12165555555";
objFaxDocument.Sender.OfficeLocation = "Downtown";
objFaxDocument.Sender.OfficePhone = "12165555553";
objFaxDocument.Sender.StreetAddress = "123 Main Street";
objFaxDocument.Sender.TSID = "Office fax machine";
objFaxDocument.Sender.ZipCode = "44118";
objFaxDocument.Sender.BillingCode = "23A54";
objFaxDocument.Sender.Department = "Accts Payable";
JobID = objFaxDocument.ConnectedSubmit(objFaxServer);
MessageBox.Show(("The Job ID is :" + JobID.ToString()),"Finished");
objFaxServer.Disconnect();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString() + ". " + ex.ToString(), "Exception");
}
The exception is thrown on that line: FaxServer objFaxServer = new FaxServer();
Unable to cast COM object of type 'System.__ComObject' to interface type 'FAXCOMEXLib.FaxServer'.
When I do: FaxServer objFaxServer = new FaxServerClass();
I can't even compile that line.. It shows: Interop type 'FAXCOMEXLib.FaxServerClass' cannot be embedded. Use the applicable interface instead.
So, I was stopped on that line :/
BTW. Basically, I want to implement a class that will send faxes and watch the status of sent messages. I would be very very pleased, if somebody send a whole ready to use class.
Please help me,
When I do: FaxServer objFaxServer = new FaxServerClass(); I can't even
compile that line
Weird thing about COM objects is that interfaces sometimes act as though they have constructors:
FaxServer objFaxServer = new FaxServer();
That is the correct line. I have it on mine and it works. There may be something wrong with the interop.
Do the following steps to overcome this issue:
Select FAXCOMEXLib from refrences in Solution Explorer.
Open Properties
Set "Enable Interop Type" to False.

Categories