using System.Net; using System.Net.Sockets; using System.Text; using e_suite.Service.Mail.Helper; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace eSuite.API.HealthChecks; /// /// Health check used to perform a basic check to see that the smtp server is available. /// public class SmtpHealthCheck { /// /// Returns Health check result for if the smtp server is up and available to connect too. /// /// /// /// public static HealthCheckResult Healthy(IConfiguration configuration, ISocketFactory socketFactory) { //failure to be able to send an email should result in degraded. var host = configuration.GetConfigValue("MAIL_SERVER", "Smtp:Server", "defaultmailserver"); var port = configuration.GetConfigValue("MAIL_PORT", "Smtp:Port", 25); //var fromAddress = configuration.GetConfigValue("MAIL_ADDRESS", "Smtp:FromAddress", "defaultfromaddress"); //var fromDisplayName = configuration.GetConfigValue("MAIL_NAME", "Smtp:FromDisplayName", "MailService"); //var username = configuration.GetConfigValue("MAIL_USERNAME", "Smtp:Username", string.Empty); //var password = configuration.GetConfigValue("MAIL_PASSWORD", "Smtp:Password", string.Empty); //var enableSsl = configuration.GetConfigValue("MAIL_ENABLE_SSL", "Smtp:EnableSSL", false); //client.Timeout = _configuration.GetConfigValue("MAIL_TIMEOUT", "Smtp:timeout", 30000); var isServerOk = TestConnection(host!, port, socketFactory); if (!isServerOk) return HealthCheckResult.Unhealthy("Unable to connect to SMTP Server"); return HealthCheckResult.Healthy(); } /// /// Performs the test to connect to the smtp server to see that the server is functional. /// /// /// /// /// public static bool TestConnection(string smtpServerAddress, int port, ISocketFactory socketFactory) { var hostEntry = Dns.GetHostEntry(smtpServerAddress); var endPoint = new IPEndPoint(hostEntry.AddressList[0], port); using (var tcpSocket = socketFactory.CreateSocket( endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { //try to connect and test the rsponse for code 220 = success tcpSocket.Connect(endPoint); if (!CheckResponse(tcpSocket, 220)) { return false; } // send HELO and test the response for code 250 = proper response SendData(tcpSocket, $"HELO {Dns.GetHostName()}\r\n"); if (!CheckResponse(tcpSocket, 250)) { return false; } // if we got here it's that we can connect to the smtp server return true; } } private static void SendData(ISocketFacade socket, string data) { var dataArray = Encoding.ASCII.GetBytes(data); socket.Send(dataArray, 0, dataArray.Length, SocketFlags.None); } private static bool CheckResponse(ISocketFacade socket, int expectedCode) { while (socket.Available == 0) { Thread.Sleep(100); } var responseArray = new byte[1024]; socket.Receive(responseArray, 0, socket.Available, SocketFlags.None); var responseData = Encoding.ASCII.GetString(responseArray); var responseCode = Convert.ToInt32(responseData.Substring(0, 3)); return responseCode == expectedCode; } }