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;
}
}