Using email template to compose and send emails

This is a simple prototype to compose and send HTML emails using a sample template.

Here is the template;

String emailTemplate = @"
<html lang=""en"">
    <head>    
        <meta content=""text/html; charset=utf-8"" http-equiv=""Content-Type"">
        <title>
            {0}
        </title>
        <style type=""text/css"">
            HTML{background-color: #e8e8e8;}
            .document-table{font-size: 12px; padding: 3px; border-collapse: collapse; border-spacing: 0;}
            .document-table .description{color: #505050;}
            .document-table td{border: 1px solid #D1D1D1; background-color: #F3F3F3; padding: 0 10px;}
            .document-table th{border: 1px solid #424242; color: #FFFFFF;text-align: left; padding: 0 10px;}
            .green{background-color: #6B9852;}
            .wrapper { margin-bottom: 20px;}
        </style>
    </head>
    <body>
        <div class=""wrapper"">
            Team,
        </div>
        <div class=""wrapper"">
            SampleDb data pull job {1} last night. The job is configured to run on {2} basis.
        </div>
        <div class=""wrapper"">
            SampleDb database is scanned between {3} for new documents. Following new document have been found and their data is copied over to the target database.
        </div>
        <div class=""wrapper"">
            <table class=""document-table"">
                <thead>
                    <tr>
                        <th class=""green"">AccountNumber</th>
                        <th class=""green"">FYQ</th>
                        <th class=""green"">DateAdded</th>
                        <th class=""green"">RowStatus</th>
                    </tr>
                </thead>
                <tbody>
                    {4}
                </tbody>
            </table>
        </div>
        <div class=""wrapper"">
            <h5><br /><br />This inbox is unattended. please do not reply to this email. This is an auto-generated message.</h5>
        </div>
    </body>
</html>
";

We can use dynamic and ExpandoObject to create data. Alternatively you can grab data from database;

var list = new List<dynamic>();
dynamic row = new ExpandoObject();
row.AccountNumber = "XYZ-100";
row.FYQ = "Q1 FY 1999";
row.DateAdded = "1999-07-28 19:38:00.000";
row.RowStatus = "processed";
list.Add(row);

We need to fill template placeholders;

StringBuilder sb = new StringBuilder();           
list.ForEach(x =>
{
   sb.Append("<tr>");
   sb.Append($"<td class='description'>{x.AwardNumber}</td>");
   sb.Append($"<td>{x.FYQ}</td>");
   sb.Append($"<td>{x.DateAdded}</td>");
   sb.Append($"<td>{x.RowStatus}</td>");
   sb.Append("</tr>");
});

replace all placeholders in HTML template;

string emailBody =
    emailTemplate.Replace("{0}", "A demo email body title")
    .Replace("{1}", "succeeded")
    .Replace("{2}", "yearly")
    .Replace("{3}", "01/01/1999 23.59.59 - 11/2/2021 02:00:00 AM")
    .Replace("{4}", sb.ToString());
               

Compose and send email out;

MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("FromAdam@mail.com", "Sample Data Pull");
mailMessage.To.Add("ToJoe@mail.com");
mailMessage.Body = emailTemplate;
mailMessage.Subject = "Test email";
mailMessage.IsBodyHtml = true;
mailMessage.SubjectEncoding = Encoding.UTF8;
mailMessage.BodyEncoding = Encoding.UTF8;

//send email
using (var client = new SmtpClient("smtp-host-address"))
{
   //if true, user/pwd required, false network credentials will be used
   client.UseDefaultCredentials = true;
   if (client.UseDefaultCredentials)
   {
   client.Credentials = new NetworkCredential("FromAdmam@mail.com", "AdamSecretPassword");
   }
   client.EnableSsl = true;
   client.DeliveryMethod = SmtpDeliveryMethod.Network;
   client.Timeout = 3000;      //3 seconds
   client.Send(mailMessage);
}

Run your program and check your inbox. You will see HTML email with CSS style applied. The HTML table element is replace with our created data.

Have fun!

Dataset is empty, no tables in Dataset

This is how we can test if dataset is empty;

if(ds != null)
if(ds.Tables.Count > 0 )
if(ds.Tables[0].Rows.Count > 0)

We can loop through all tables in a method like this;

bool IsEmpty(DataSet dataSet)
{
    foreach(DataTable table in dataSet.Tables)
        if (table.Rows.Count != 0) return false;

    return true;
}

Since a DataTable could contain deleted rows RowState = Deleted, depending on what you want to achive, it could be a good idea to check the DefaultView instead (which does not contain deleted rows).

bool IsEmpty(DataSet dataSet)
{
    return !dataSet.Tables.Cast<DataTable>().Any(x => x.DefaultView.Count > 0);
}

Resource

https://stackoverflow.com/questions/2976473/how-to-test-if-a-dataset-is-empty

Dynamic type and Expando Object class

The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Instead, these operations are resolved at run time. The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).

Here is an example;

var list = new List<dynamic>();
dynamic row = new ExpandoObject();
row.AccountNumber = "XYZ-331";
row.FYQ = "Q3 FY 2021";
row.DateAdded = "2021-07-28 19:38:00.000";
row.RowStatus = "processed";
list.Add(row);

Here is the output;

list.ForEach(x =>
{
   Console.WriteLine($"AccountNumber = { x.AccountNumber} \nFYQ =  {x.FYQ}\nDateAdded = {x.DateAdded}\nRowStatus = {row.RowStatus}");
});

Resources

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types

https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?view=net-5.0

https://www.codegrepper.com/code-examples/csharp/add+static+data+to+list+in+c%23

Appending two string builders

The most performant way of appending two string builders in .NET Framework 4, use this;

frontStringBuilder.Append(backStringBuilder);

For .NET Framework 2.0/3.5, use this;

frontStringBuilder.Append(backStringBuilder.ToString(0, backStringBuilder.Length));

This wouldn’t hurt performance in .NET FW 4.0.

Resources

https://stackoverflow.com/questions/6454392/how-to-append-two-stringbuilders

C# expression trees

We want to treat lambda expressions as expression trees and look inside them instead of executing them. For example, LINQ to SQL gets the expression and converts it to the equivalent SQL statement and submits it to server (rather than executing the lambda).

With Lambda expressions we can write less code, and the code will be more readable.

A lambda expression uses the lambda operator => which means goes to.

arguments => expession

The expression reads: arguments goes to expression.

Let’s start with a common example;

using System;

namespace Lambdas
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(Square(5));
            Console.ReadLine();
        }

        static int Square(int num)
        {
            return num * num;
        }
    }
}

we declare a method called Square of type int with one input parameter of type int. It multiplies the number and returns the result.

In the Main() method we call our Square method with an int as a parameter.

We can convert this function into a Lambda expression. This is what it would look like:

num => num * num;

This expression would read: num goes to calculation (num * num).

This expression is short and easily readable once we get used to it. The catch though, is that a Lambda expression must be assigned to a delegate.

Resources

https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct

https://tyrrrz.me/blog/expression-trees

https://thesharperdev.com/an-introduction-to-c-expression-trees/