Aspose.email for Dot Net BulkSend mailmerge barcode and failure list

Our company bought Aspose.email for .NET a couple of months ago and I was wondering if you could provide me the following:


1. an example on how to include a different Bar-code for each mail merge email utilizing email templates and bulk-send. We are planning on sending less than 1 million emails each with a different Bar-code and additional custom data. Both the Bar-code number and custom data will be stored in a database table-row or view-row

2. An example on how to catch all the failures without stopping the email dispatch process until it is done attempting to send all the emails.

3. An example on how to step one by one (if so desired) to view the merged results (messages with specific details already composed, including bar-code) and so test/approve them before actually dispatching the emails.

Note that we will be utilizing the company Microsoft Exchange server/services, etc. so hopefully the examples will be tailored to this environment


Thank you


Hi Luis,

Thank you for writing to Aspose support team.

I have analyzed the requirement and observed that there is no direct method to embed bar code images into MailMessage using template engine. However a workaround is given here for your reference.

lucho1981:

  1. an example on how to include a different Bar-code for each mail merge email utilizing email templates and bulk-send. We are planning on sending less than 1 million emails each with a different Bar-code and additional custom data. Both the Bar-code number and custom data will be stored in a database table-row or view-row

Comments:

Please give a try to the following sample code by using your own DataTable and let us know the feedback:

static private void Email_668794()

{

//Create an instance of DataTable

//Fill a DataTable as data source

DataTable dt = new DataTable();

dt.Columns.Add(“Receipt”, typeof(string));

dt.Columns.Add(“FirstName”, typeof(string));

dt.Columns.Add(“PlainText”, typeof(string));

dt.Columns.Add(“Barcode”, typeof(byte[]));

//Create an instance of DataRow

DataRow dr;

dr = dt.NewRow();

dr[“Receipt”] = “newcustomeronnet@gmail.com>”;

dr[“FirstName”] = “a”;

dr[“PlainText”] = “bc”;

byte[] imageByte1 = {1,2,3,4,5,6,7,8,9,10};//dummy barcode bytes

dr[“Barcode”] = imageByte1;

dt.Rows.Add(dr);

dr = dt.NewRow();

dr[“Receipt”] = “email@domain.com”;

dr[“FirstName”] = “Guangzhou”;

dr[“PlainText”] = “Team”;

byte[] imageByte2 = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };//dummy barcode bytes

dr[“Barcode”] = imageByte2;

dt.Rows.Add(dr);

dr = dt.NewRow();

dr[“Receipt”] = “email.address@domain.com>”;

dr[“FirstName”] = “Kyle”;

dr[“PlainText”] = “Huang”;

byte[] imageByte3 = { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };//dummy barcode bytes

dr[“Barcode”] = imageByte3;

dt.Rows.Add(dr);

MailMessageCollection messages = new MailMessageCollection();

foreach (DataRow dataRow in dt.Rows)

{

MailMessage mail = new MailMessage();//You may load some template mail here like MailMessage mail = new MailMessage(“teamplate.msg”);

//Set the content

mail.Subject = "Hello " + dr[“FirstName”];

//Set the addresses

mail.From = new MailAddress(“sender@receiver”);

mail.To.Add(dataRow[“Receipt”].ToString());

//Create the plain text part

//It is viewable by those clients that don’t support HTML

AlternateView plainView =AlternateView.CreateAlternateViewFromString(dr[“PlainText”].ToString(), null,“text/plain”);

//Create the HTML part.

//To embed images, we need to use the prefix ‘cid’ in the img src value.

//The cid value will map to the Content-Id of a Linked resource.

//Thus will map to a LinkedResource with a ContentId of //‘companylogo’.

AlternateView htmlView = AlternateView.CreateAlternateViewFromString(“Here is an embedded image.”, null, “text/html”);

//create the LinkedResource (embedded image)

Stream stream = new MemoryStream((byte[])dr[“Barcode”]);

LinkedResource logo = new LinkedResource(stream, MediaTypeNames.Image.Png);

logo.ContentId = “companylogo”;

//Add the LinkedResource to the appropriate view

mail.LinkedResources.Add(logo);

mail.AlternateViews.Add(plainView);

mail.AlternateViews.Add(htmlView);

messages.Add(mail);

}

try

{

SmtpClient client = new SmtpClient(“smtp.gmail.com”, 587, “testuser”,“password”);

client.SecurityOptions = SecurityOptions.SSLExplicit;

SmtpClient client = GetSmtpClient();

//Send messages in bulk

client.BulkSend(messages);

}

catch (Aspose.Email.Mail.MailException ex)

{

System.Diagnostics.Debug.WriteLine(ex.ToString());

}

catch (SmtpException ex)

{

System.Diagnostics.Debug.WriteLine(ex.ToString());

}

}

lucho1981:

  1. An example on how to catch all the failures without stopping the email dispatch process until it is done attempting to send all the emails.

Comments:

You may please log the Smtp client activity as given here.

lucho1981:

  1. An example on how to step one by one (if so desired) to view the merged results (messages with specific details already composed, including bar-code) and so test/approve them before actually dispatching the emails.

Comments:

As mentioned in the first example you may please save/observe all the messages being prepared before sending through BulkSend.

Please feel free to write us back if you have any other query in this regard.

Thanks for your reply Muhammad, following up a bit on my questions:


On 1. Bar-codes? We will give a try to your solution, but I thought we were having is on utilizing something like
TemplateEngine.RegisterRoutine"GetBarcode", new TemplateRoutine(GetBarCode);

this way we could generate the image on the fly, but could you provide us an example utilizing our idea? in particular how do we pass the row data to the Routine?, how do we return the generated bar-code (I image as an object I imagine), but how do we include it in the message so it displays properly? What is your opinion on this idea? in comparison to your work around suggestion?

On 2. Failures? We need to Capture failures for further processing in code after a full dispatch is completed. It seems that your solution logs the failures but we would like to add them real time (in code) to a list so that we can, for example, opt-out customers, etc.
So for this we were thinking on utilizing SmtpClientBulkSendAgent instead of BulkSend, it seems that we can hook more events that way and also retrieve more information about the process that way. But what is the recommended approach: SmtpClientBulkSendAgent.Start(…) or SmtpClient.BulkSend(…)

On 3. Reviewing messages before dispatching them? You mentioned that we can save/observe all messages being prepared before sending through BulkSend, but we still don’t know how? could you provide an example? We were thinking on utilizing TemplateEngine.Merge(…) is that what you are talking about? Probably not because your are mentioning BulkSend and not TemplateEngine. So it will be great if you elaborate a bit more on this one or provide an example? Thanks

Additionally we will appreciate your recommendation on a couple of aspects:

4. New. What is your estimate on performance for sending less than 1 million emails utilizing Microsoft Exchange, etc? How long would it take more or less if the email is small with links and bar-code image, but no attachments? Should we partition the task into smaller groups? This last part leads to the next question

5. New. Do you have an example where asynchronous processes are properly handled, and example utilizing SmtpClientBulkSendAgent.WaitForIdle() for example if there is need to partition things into smaller tasks?


Hi,


We are analyzing he requirement and it may take little time to provide comments on these requirements. Please spare us little time to complete the analysis and provide our feedback

Hello Muhammad.


It seems that I am going a bit in circles and would appreciate if you give me some assistance with the the following requirement. The answer I have gotten so far seem to provide pieces of what we need but not a complete solution.

I need to mass mail 1 million emails (same template, but different dynamic data) to 1 million users (different email address each)

Different data includes different images, a bar code number (generated Image), a couple of links, different body line items like salutation, and some other details. So the overall question is that I need a complete solution at least the the conceptual or better yet the logical level utilizing Aspose functionality that is to:

1. Utilize a single message-template
2. utilizing a reader that reads the dynamic-data one a a time (and not all of them placed into a datatable)
3. A simple way to merge the message-template with the dynamic-data generating a rendered message that can then be:
3.1. Returned for previewing and aproval or
3.2 Dispatched if so desired so that the recipients gets their email.
Notice that 3.1 and 3.2 are an or condition that means two separate paths and times, the reviewing is one path and time, the dispatching is another path and time

Q1. It seems that you are saying that I can not utilize the template engine because that way we can not include bar-code images. So how do I merge the dynamic-data with the message template if not utilizing the template engine. What Aspose functionality do I utilize to merge if I can not utilize the template engine because of the bar-codes?

Q.2 If I have to replace the message-template keys-data with my own code to search for the keys and replaces them with the dynamic-data row, and then generate the MailMessage and then I will have to Add the MailMessage to the MalMessageCollection. Could the MailMEssageColleciton hold 1 million items completely rendered at the same time? what is the memory foot print for such case? in other words what is the size of the MAilMessage Object MailMessage Collection object if the content I place in them is just what I mentioned above (no attachments)

Q3. I believe this requirements are nothing out of the ordinary. No small data-table examples will work, or some sort of asynchronous methods barely mentioned in different places. Is there a good example that shows a more mature case of sending 1 million emails with the above requirements? If I have to do the template merging myself, If I have to do something like the Parallel.ForEach(…) myself. And if I am utilizing Aspose just to send the emails that I created with all this work. then the Aspose functionality has very little usability right? I really hope you can provide me some sort of answer that is complete and consistent throughout

And I thank you very much in advance





Hi,

We are analyzing the issues and preparing the sample code which may fulfill your requirements. Please spare us little time to complete the task and provide assistance accordingly.

Hi,

We have thoroughly investigated the issue again and following are the observations:

lucho1981:
Different data includes different images, a bar code number (generated Image), a couple of links, different body line items like salutation, and some other details.

Comments:

Here the requirement is to add different images in the emails. We can embed an image (including Bar code image) using Linked Resource as given in this article. On the other hand TemplateEngine helps us by replacing the string data only in data row by the hash tags in the template email. As there is no option to get the images binary data using TemplateEngine, hence this method cannot be used to insert images at run-time. That is why a sample code was provided which helps us to add images in the mails before sending them through BulkSend. The ultimate target was to prepare a collection of mail messages, which can be passed to BulkSend, thus we used a scheme which does not use TemplateEngine and uses Linked Resource to insert images.

lucho1981:
1. Utilize a single message-template
2. utilizing a reader that reads the dynamic-data one a a time (and not all of them placed into a datatable)
3. A simple way to merge the message-template with the dynamic-data generating a rendered message that can then be:
3.1. Returned for previewing and aproval or
3.2 Dispatched if so desired so that the recipients gets their email.
Notice that 3.1 and 3.2 are an or condition that means two separate paths and times, the reviewing is one path and time, the dispatching is another path and time

Comments:

You may use a template file rather than creating a new message in the above mentioned sample code. Reading dynamic data from database or any other source can be implemented using any language construct as Aspose does not support reading data from database or other sources. Merging the data in mail message requires a scheme which can embed image as well and same is accomplished in the above sample code. In 3.1 you mentioned that it should return mail for preview and approval. As Aspose.Email does not provide any viewing component, therefore you may implement your own scheme to view the message either by saving it on disc and then viewing it using some mail client like Outlook or Thunderbird etc. Second option to view the messages can be using Interop, which may not require saving messages on disc, but just open message in Outlook automatically to view it.

lucho1981:
Q1. It seems that you are saying that I can not utilize the template engine because that way we can not include bar-code images. So how do I merge the dynamic-data with the message template if not utilizing the template engine. What Aspose functionality do I utilize to merge if I can not utilize the template engine because of the bar-codes?

Comments:

You are right, that Template Engine cannot be utilized to embed images and that is why the sample code was provided where dynamic data from data row of a data table was used to create mail messages. There is no other option available similar to TemplateEngine for embedding images in the mails.

lucho1981:
Q.2 If I have to replace the message-template keys-data with my own code to search for the keys and replaces them with the dynamic-data row, and then generate the MailMessage and then I will have to Add the MailMessage to the MalMessageCollection. Could the MailMEssageColleciton hold 1 million items completely rendered at the same time? what is the memory foot print for such case? in other words what is the size of the MAilMessage Object MailMessage Collection object if the content I place in them is just what I mentioned above (no attachments)

Comments:

I have checked that 1 million mails can be added in MailMessageCollection and it does not take much more space. I tried a sample message (which takes 20 KB space on disc) and saved its 1 million copies in MailMessageCollection. It took about 294 MB space calculated by taking snapshot before and after adding the messages using following sample code:
long workingSetStart = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;

//Create and add messages here
long workingSetEnd = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;

//Get the difference of both the WorkingSet.
lucho1981:
Q3. I believe this requirements are nothing out of the ordinary. No small data-table examples will work, or some sort of asynchronous methods barely mentioned in different places. Is there a good example that shows a more mature case of sending 1 million emails with the above requirements? If I have to do the template merging myself, If I have to do something like the Parallel.ForEach(..) myself. And if I am utilizing Aspose just to send the emails that I created with all this work. then the Aspose functionality has very little usability right? I really hope you can provide me some sort of answer that is complete and consistent throughout

Comments:

BulkSend() is the option to send bulk of mails using Aspose.Email. Creating bulk of messages and viewing them for approval, may please be implemented using different multi-threading schemes and viewing techniques like Interop. Aspose.Email does not provide these features yet.