Domanda

I wrote the below program to send HTML Email to the demo users in this table:

enter image description here

I want to send only one email and lists all of the information for each customer. Currently, if a customer has 10 books past due, then the customer will get 10 emails based on the table structure, because each book loan is a separate record.

For example:

Dear Jim Carey: The following book(s) are due:

  1. How to Fix Cars
  2. James Bond Returns

Is there a way that I can send only one email for each customer but list each item in the email. For example list all the books due?

Fox example: Sending an email using the above table, Jim Carey will get 2 emails, instead of 1. I would like to send just one but list both the books due.

class Program
{
static DataSet dtProfile = Database.AcquireData();
static DataTable table = dtProfile.Tables[0];

static string CustFName;
static string CustLName;
static string CheckoutDate;
static string DueDate;
static string BookName;

public static void SendEmail()
{
    foreach (DataRow row in table.Rows)
    {
     CustFName = row["CustFName"].ToString();
     CustLName = row["CustLName"].ToString();
     CheckoutDate = row["CheckoutDate"].ToString();
     DueDate = row["DueDate"].ToString();
     BookName = row["BookName"].ToString();          
     string body = PopulateBody(CustFName, CustLName, CheckoutDate, DueDate, BookName);<br />
     SendHtmlFormattedEmail("Email", "Subject", body);
    }
}

public static string PopulateBody(string custFName, string custLName,
    string checkoutDate, string dueDate, string bookName)
{
    string body = string.Empty;

    using (StreamReader reader = 
        new StreamReader(Path.GetFullPath(@"Z:\folder\email.html")))
    {
        body = reader.ReadToEnd();
    }
    body = body.Replace("{#First Name#}", custFName);
    body = body.Replace("{#Last Name#}",  custLName);
    body = body.Replace("{#Checkout Date#}", checkoutDate);
    body = body.Replace("{#Due Date#}",  dueDate);
    body = body.Replace("{#Book Name#}", bookName);

    return body;
}

public static void SendHtmlFormattedEmail(string recepientEmail, string subject, string body)
{
    using (MailMessage mailMessage = new MailMessage())
    {
      mailMessage.From = new MailAddress(ConfigurationManager.AppSettings["UserName"]);
      mailMessage.Subject = subject;
      mailMessage.Body = body;
      mailMessage.IsBodyHtml = true;
      mailMessage.To.Add(new MailAddress(recepientEmail));
      SmtpClient smtp = new SmtpClient();
      smtp.Host = ConfigurationManager.AppSettings["Host"];
      smtp.EnableSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableSsl"]);
      System.Net.NetworkCredential NetworkCred = new System.Net.NetworkCredential();
      NetworkCred.UserName = ConfigurationManager.AppSettings["UserName"];
      NetworkCred.Password = ConfigurationManager.AppSettings["Password"];
      smtp.UseDefaultCredentials = true;
      smtp.Credentials = NetworkCred;
      smtp.Port = int.Parse(ConfigurationManager.AppSettings["Port"]);
      smtp.Send(mailMessage);
    }
}

static void Main(string[] args)
{
    SendEmail();
}

}
È stato utile?

Soluzione

Create a collection of email data for each email address. Then iterate over the individual addresses and send out the emails.

class Program
{
    static DataSet dtProfile = null; //Database.AcquireData();
    static DataTable table = dtProfile.Tables[0];

    public static void SendEmail()
    {
        // Create the dictionary to hold the email data for each individual email. This allows us 
        // to group all of the books due for an individual together.  We will use the email address
        // as the key for the dictionary instead of CustomerID in case the user has given us two
        // different email addresses.
        Dictionary<string, List<DataRow>> emailList = new Dictionary<string, List<DataRow>>();

        // Iterate over the dataset and populate the dictionary
        foreach (DataRow row in table.Rows)
        {
            // grab the email address, will be the key for the dictionary
            string email = row["Email"].ToString();

            // if we haven't processed a row for this email yet, initialize the entry for it
            if (!emailList.ContainsKey(email))
            {
                emailList.Add(email, new List<DataRow>());
            }

            // add the datarow for the overdue book for the email
            emailList[email].Add(row);
        }

        // Now, craft and send an email for each unique email address in the list
        foreach (string email in emailList.Keys)
        {
            // create a string builder to build up the body of the email
            StringBuilder body = new StringBuilder();
            body.Append("<html>");
            body.Append("<body>");

            // assume the first/last name will be the same for each row, so just get the
            // name information from the first row to build the opening line of the email
            DataRow firstRow = emailList[email][0];
            body.AppendFormat("<p>Dear {0} {1}:  The following book(s) are due:</p>", firstRow["FName"].ToString(), firstRow["LName"].ToString());
            body.Append("<ol>");

            // now just add a line item for each book
            foreach (DataRow row in emailList[email])
            {
                body.AppendFormat("<li>{0}</li>", row["BookName"].ToString()); 
            }

            // close up your html tags
            body.Append("</ol>");
            body.Append("</body>");
            body.Append("</html>");

            // finally, send the email
            SendHtmlFormattedEmail(email, "Overdue Books", body.ToString());
        }
    }

    public static void SendHtmlFormattedEmail(string recepientEmail, string subject, string body)
    {
        using (MailMessage mailMessage = new MailMessage())
        {
            mailMessage.From = new MailAddress(ConfigurationManager.AppSettings["UserName"]);
            mailMessage.Subject = subject;
            mailMessage.Body = body;
            mailMessage.IsBodyHtml = true;
            mailMessage.To.Add(new MailAddress(recepientEmail));
            SmtpClient smtp = new SmtpClient();
            smtp.Host = ConfigurationManager.AppSettings["Host"];
            smtp.EnableSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableSsl"]);
            System.Net.NetworkCredential NetworkCred = new System.Net.NetworkCredential();
            NetworkCred.UserName = ConfigurationManager.AppSettings["UserName"];
            NetworkCred.Password = ConfigurationManager.AppSettings["Password"];
            smtp.UseDefaultCredentials = true;
            smtp.Credentials = NetworkCred;
            smtp.Port = int.Parse(ConfigurationManager.AppSettings["Port"]);
            smtp.Send(mailMessage);
        }
    }

    static void Main(string[] args)
    {
        SendEmail();
    }

}

Altri suggerimenti

Use Jason Young's example, but slightly modified to separate the emails for each different customer.

string lastCustId = "none";
foreach (DataRow row in table.Rows)
{
    if (!lastCustId.Equals("none") && !row["CustId"].ToString().Equals(lastCustId))
    {
        // Different customer's record, fire off the email to previous one
        SendHtmlFormattedEmail("Email", "Subject", body.ToString());
        lastCustId = row["CustId"].ToString();
    }
    // Build email for current customer
    CustFName = row["CustFName"].ToString();
    CustLName = row["CustLName"].ToString();
    CheckoutDate = row["CheckoutDate"].ToString();
    DueDate = row["DueDate"].ToString();
    BookName = row["BookName"].ToString();          
    body.AppendLine(PopulateBody(CustFName, CustLName, CheckoutDate, DueDate, BookName, template));
    // not sure what your template looks like, but this would be whatever
    // markup or text you would want separating your book details
    body.AppendLine("<br>");        
}
// Finally send email to the last customer in above loop
SendHtmlFormattedEmail("Email", "Subject", body.ToString());
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top