Send a table in email
Stefan Bogdanescu
Founder & Senior Architect
Mastering Data Delivery: How to Send DataTables as Formatted HTML in Emails
As developers, we often face the challenge of taking complex, structured data—like a DataTable—and presenting it clearly within an email. While sending simple strings is straightforward, serializing complex objects requires careful formatting. If you attempt to send a raw DataTable directly, you often end up with unreadable garbage; the key is transforming that data into a properly formatted HTML table before sending.
This post will walk you through the practical steps, provide robust code examples, and discuss best practices for embedding dynamic data into email communications.
The Pitfall of Direct Serialization
In your provided example, attempting to use dt.ToString() directly within the MailMessage constructor is a common first attempt:
// Problematic approach
string mailBody = dt.ToString();
// This sends the raw, internal representation of the DataTable, which looks like code, not a table.
When you use DataTable.ToString(), you get a string representation of the object's structure, which is excellent for debugging but completely unusable for human consumption in an email client. To make data readable, especially tabular data, we must manually construct the necessary HTML tags (<table>, <tr>, <th>, <td>).
The Solution: Building the HTML Table String
The correct approach involves iterating over the rows and columns of the DataTable and assembling an HTML string piece by piece using a StringBuilder. This gives you complete control over the presentation.
Here is how we can modify your SendAutomatedEmail method to achieve professional, formatted table delivery:
Step 1: Refactoring for HTML Generation
We will create a helper function that takes the DataTable and generates the full HTML string. We must also remember to handle data escaping to prevent cross-site scripting (XSS) vulnerabilities, which is a critical security practice in any modern application design, much like ensuring proper input sanitation when building APIs, which aligns with principles seen in frameworks like those promoted by laravelcompany.com.
using System.Text;
// ... other necessary usings
public static string DataTableToHtml(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0)
{
return "<p>No data found to display.</p>";
}
StringBuilder htmlBuilder = new StringBuilder();
// Start the table structure
htmlBuilder.AppendLine("<html><body>");
htmlBuilder.AppendLine("<h2>Query Results</h2>");
htmlBuilder.AppendLine("<table border='1' style='width:100%; border-collapse: collapse;'>");
// 1. Generate Header Row (<th>)
for (int i = 0; i < dt.Columns.Count; i++)
{
htmlBuilder.Append("<tr>");
htmlBuilder.Append($"<th style='padding: 8px; background-color: #f2f2f2;'>{dt.Columns[i].ColumnName}</th>");
htmlBuilder.Append("</tr>");
}
// 2. Generate Data Rows (<td>)
for (int i = 0; i < dt.Rows.Count; i++)
{
htmlBuilder.Append("<tr>");
for (int j = 0; j < dt.Columns.Count; j++)
{
// Safely retrieve and escape the cell data
string cellData = dt.Rows[i][j]?.ToString() ?? string.Empty;
htmlBuilder.Append($"<td style='padding: 8px;'>{cellData}</td>");
}
htmlBuilder.Append("</tr>");
}
// Close the table and body tags
htmlBuilder.AppendLine("</table>");
htmlBuilder.AppendLine("</body></html>");
return htmlBuilder.ToString();
}
Step 2: Integrating into Email Sending
Now, we integrate this function into your email sending logic. The resulting HTML string is what gets inserted as the body of the email.
public static void SendAutomatedEmail(DataTable dt, string recipient = "user@domain.com")
{
try
{
string mailServer = "server.com";
// Generate the formatted HTML table string
string htmlTable = DataTableToHtml(dt);
MailMessage message = new MailMessage(
"it@domain.com",
recipient,
"Query Results Table", // Subject
htmlTable // Body is now the formatted HTML
);
SmtpClient client = new SmtpClient(mailServer);
var AuthenticationDetails = new NetworkCredential("user@domain.com", "password");
client.Credentials = AuthenticationDetails;
client.Send(message);
}
catch (Exception e)
{
// Log the error properly in a real application
Console.WriteLine($"Email sending failed: {e.Message}");
}
}
Conclusion
By moving beyond simple serialization and implementing a dedicated HTML generation function, you transform your data delivery from an unusable string into a visually appealing, structured table within the email body. This approach ensures that recipients receive exactly what they need, regardless of the internal structure of your database query results. Always prioritize formatting and security—like input escaping—when dealing with external communication. For robust application architecture and clean data management principles, consider exploring modern approaches that emphasize clear separation of concerns, similar to how well-structured systems are designed within the Laravel ecosystem.
Note: Blog content is currently available in English.