Email Timeout

DataKnight11

Member
Joined
Apr 18, 2024
Messages
18
Location
Portugal
Programming Experience
Beginner
I'm working on a solution that involves sending a single email with notifications. However, I'm running into an issue where the function is timing out after 10 minutes, even though the email only contains a single row of data. Can anyone offer some guidance on how to optimize this process or suggest alternative approaches to avoid the timeout?

NotificationEmail class:
public class NotificationEmail : IDisposable
    {
        private readonly IConfiguration _config;
        private readonly SmtpClient _smtpClient;

        public NotificationEmail(IConfiguration config)
        {
            _config = config ?? throw new ArgumentNullException(nameof(config));

            var smtpHost = _config.GetValue<string>("Host") ?? "smtp-mail.outlook.com";
            var smtpPort = _config.GetValue<int>("Port");
            var smtpUser = _config.GetValue<string>("UserEmail");
            var smtpPass = _config.GetValue<string>("PasswordEmail");

            if (string.IsNullOrWhiteSpace(smtpUser) || string.IsNullOrWhiteSpace(smtpPass))
            {
                throw new InvalidOperationException("SMTP configuration is missing or invalid.");
            }

            _smtpClient = new SmtpClient(smtpHost)
            {
                Port = smtpPort,
                Credentials = new NetworkCredential(smtpUser, smtpPass),
                EnableSsl = true,
                Timeout = 10000
            };
        }

        public string GetHtmlTable(string title, DataTable table)
        {
            try
            {
                string messageBody = "<font>" + title + " </font><br><br>";

                if (table.Rows.Count == 0)
                    return messageBody;

                string htmlTableStart = "<table style=\"border-collapse:collapse; text-align:center;\" >";
                string htmlTableEnd = "</table>";
                string htmlHeaderRowStart = "<tr style =\"background-color:#6FA1D2; color:#ffffff;\">";
                string htmlHeaderRowEnd = "</tr>";
                string htmlTrStart = "<tr style =\"color:#555555;\">";
                string htmlTrEnd = "</tr>";
                string htmlTdStart = "<td style=\" border-color:#5c87b2; border-style:solid; border-width:thin; padding: 5px;\">";
                string htmlTdEnd = "</td>";

                messageBody += htmlTableStart;
                messageBody += htmlHeaderRowStart;

                foreach (DataColumn column in table.Columns)
                    messageBody += htmlTdStart + WebUtility.HtmlEncode(column.ColumnName) + htmlTdEnd;

                messageBody += htmlHeaderRowEnd;

                foreach (DataRow row in table.Rows)
                {
                    messageBody += htmlTrStart;
                    foreach (var item in row.ItemArray)
                    {
                        messageBody += htmlTdStart;
                        messageBody += WebUtility.HtmlEncode(item?.ToString() ?? string.Empty);
                        messageBody += htmlTdEnd;
                    }
                    messageBody += htmlTrEnd;
                }

                messageBody += htmlTableEnd;

                return messageBody;
            }
            catch (Exception e)
            {
                return null;
            }
        }

        public async Task SendEmailAsync(string subject, string body, string toEmail, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrWhiteSpace(toEmail))
            {
                throw new ArgumentException("Recipient email address is invalid.");
            }

            try
            {
                var fromEmail = _config.GetValue<string>("UserEmail");

                using (var mailMessage = new MailMessage(fromEmail, toEmail))
                {
                    mailMessage.Subject = subject;
                    mailMessage.Body = body;
                    mailMessage.IsBodyHtml = true;

                    Console.WriteLine("Sending email...");
                    await _smtpClient.SendMailAsync(mailMessage, cancellationToken);
                    Console.WriteLine("Email sent successfully.");
                }
            }
            catch (SmtpException ex)
            {
                Console.WriteLine($"SMTP Exception: {ex.Message}");
                throw new InvalidOperationException("An error occurred while sending the email. Please check your SMTP settings.", ex);
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Email sending was canceled.");
                throw;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"General Exception: {ex.Message}");
                throw new InvalidOperationException("An unexpected error occurred while sending the email.", ex);
            }
        }

        public void Dispose()
        {
            _smtpClient?.Dispose();
        }
    }
 
Read the documentation. MailKit is recommended instead of using the SmtpClient class.

 
Not related to your timeout issue, but you asked for optimizations:

Doing string concatenation is slow and used a lot of memory. Use a StringBuilder. In your case, since you are building a HTML string, consider using the HtmlTextWriter or XmlWriter classes which might make your code more readable, and uses the StringBuilder under the covers.
 
Last edited:
More optimizations:

Instead of setting the style for each HTML element ala Office, use a style sheet embedded in your HTML. Something like:
HTML:
<html>
<style type="text/css">
td
{
    border-color: #5c87b2;
    ...
}
</style>

Also note that there <thead> and th elements that can be utilized to distinguish headers from rows.
 
Last edited:
As for the timeout itself, you'll need to figure out what kind of handshaking or authentication is needed by the SMTP provider you are trying to use. As previously mentioned, SmtpClient should be considered obsolete because it doesn't support some of the more modern protocols. It's likely timing out because the SMTP provider is waiting for some particular bit of information or response from your the sender.

Also check to see if ports are blocked on the sending machine or on your corporate firewall. The timeout could be as simple as the initial connection to the SMTP provider cannot be established.

Also check to see if your antivirus might be blocking your application from making the outbound connection. Some antivirus nad data loss prevention tools detect suspicious behavior or behavior that looks like data exfiltration and automatically block it.

Notice that none of the above are actually directly C# related issues, and only the first one is only indirectly related because most people using the .NET Framework library are using C#, but anybody else using F#, VB.NET, or PowerShell would equally be affected by the SmtpClient being obsoleted.
 
I implemented the suggestions you provided, but in the end, your last comment was the correct one. The problem was that my VPN was preventing the connection from being established, which caused a timeout. Thank you once again for your help.
 

Latest posts

Back
Top Bottom