Lurgle.Alerting v1.3.1 - Multiple mail hosts, DNS delivery, and fine grained TLS options!
I've recently been contributing some code to the Seq Email+ (Seq.App.HtmlEmail) repo to allow for enhanced capabilities, such as delivering email using DNS (by querying the MX record for domains) and using fallback mail hosts, along with adding To/CC/BCC and other options. These additions will, if merged, make for a more powerful Seq app.
In the meantime, I've circled back to add capabilities to Lurgle.Alerting, to allow my FluentEmail implementation to use multiple mailhosts and DNS delivery, and also have fine-grained control over TLS (when using MailKit), using what I've learned by my contributions to Email+.
The result is Lurgle.Alerting v1.3.1. This has a couple of breaking changes to the constructor if you use that to build your config, by virtue of adding the two new options.
These are predominantly config-based additions:
<add key="MailHost" value="mailhost1.domain.com,mailhost2.domain.com"/>
<add key="MailUseDns" value="true"/>
<add key="MailTlsOptions" value="Auto" />
or in the constructor:
Alerting.SetConfig(new AlertConfig(Alerting.Config, mailHost="mailhost1.domain.com,mailhost2.domain.com", mailUseDns: true, mailTlsOptions: TlsOptions.Auto));
Multiple mail hosts and DNS delivery
In short - the additions for MailHost mean that you can specify multiple hosts as a comma-delimited string. If delivery to one host fails, the next will be attempted, and so on. This means that you have inbuilt mail fallback capabilities.
If MailHost is empty and MailUseDns is true, Lurgle.Alerting will deliver using DNS, by looking up the MX records for each To, CC, and BCC email address. It will attempt to deliver using each MX record found for each domain.
If MailHost has entries and MailUseDns is true, then if all mail host deliveries fail, Lurgle.Alerting will then attempt delivery via DNS, for the ultimate in fallback capabilities!
I have moved Lurgle.Alerting from using FluentEmail.Core.Models.SendResponse
to a MailResult
class, which preserves the Successful, ErrorMessages, and MessageId properties. This should preserve compatibility in existing code, but now reflects the last delivery attempt. Lurgle now also provides MailResult.DeliveryType and MailResult.MailHost. These fields reflect the last delivery attempt's type and the mail server attempted.
public class MailResult
{
/// <summary>
/// Overall Success / Failure
/// </summary>
public bool Successful { get; set; }
/// <summary>
/// Last send's delivery type
/// </summary>
public DeliveryType DeliveryType { get; set; }
/// <summary>
/// Last send's mail host
/// </summary>
public string MailHost { get; set; }
/// <summary>
/// Last send's ErrorMessages for backward compatibility
/// </summary>
public IList<string> ErrorMessages { get; set; }
/// <summary>
/// Last send's MessageId for backward compatibility
/// </summary>
public string MessageId { get; set; }
/// <summary>
/// List of all attempts
/// </summary>
public List<DeliveryAttempt> DeliveryAttempts { get; set; }
}
You can explore all delivery attempts using the MailResult.DeliveryAttempts list, which contains the result of each delivery attempt!
The DeliveryType enum is as follows;
public enum DeliveryType
{
/// <summary>
/// Delivery via mailhost
/// </summary>
MailHost,
/// <summary>
/// Delivery via mailhost fallback
/// </summary>
MailFallback,
/// <summary>
/// Delivery via DNS
/// </summary>
Dns,
/// <summary>
/// Delivery via DNS fallback
/// </summary>
DnsFallback,
/// <summary>
/// Delivery via Mailhost DNS fallback
/// </summary>
HostDnsFallback,
/// <summary>
/// N/A
/// </summary>
None = -1
}
and the DeliveryAttempt class in MailResult.DeliveryAttempts is;
public class DeliveryAttempt
{
/// <summary>
/// Type of delivery
/// </summary>
public DeliveryType DeliveryType { get; set; }
/// <summary>
/// Host attempted
/// </summary>
public string MailHost { get; set; }
/// <summary>
/// Send response
/// </summary>
public SendResponse Result { get; set; }
}
Fine grained TLS with MailKit
MailTlsOptions offers finer grained control over that offered by the MailUseTls boolean's "on or off" functionality. It uses a TlsOptions enum which inherits the same values as MailKit's SecureSocketOptions enum. This allows TlsOptions to be referenced within code, without needing to import the MailKit.Security reference.
public enum TlsOptions
{
/// <summary>
/// None
/// </summary>
None = SecureSocketOptions.None,
/// <summary>
/// Auto
/// </summary>
Auto = SecureSocketOptions.Auto,
/// <summary>
/// Implicit TLS
/// </summary>
SslOnConnect = SecureSocketOptions.SslOnConnect,
/// <summary>
/// Explicit TLS
/// </summary>
StartTls = SecureSocketOptions.StartTls,
/// <summary>
/// Optional TLS
/// </summary>
StartTlsWhenAvailable = SecureSocketOptions.StartTlsWhenAvailable
}
This will only work with MailKit, and setting MailTlsOptions will override MailUseTls. Lurgle.Alerting will also ensure that the correct behaviour is used if you configure TCP port 465 for SMTP:
switch (MailTlsOptions)
{
case null when MailUseTls && MailPort == 465: //Implicit TLS
case TlsOptions.None when MailPort == 465:
case TlsOptions.Auto when MailPort == 465:
case TlsOptions.StartTlsWhenAvailable when MailPort == 465:
MailTlsOptions = TlsOptions.SslOnConnect;
break;
case null when MailUseTls:
MailTlsOptions = TlsOptions.StartTls; //Explicit TLS
break;
case null:
MailTlsOptions = TlsOptions.Auto;
break;
}
This enforces implicit TLS to be used in this scenario.
Lurgle the day away
Lurgle.Alerting is now even more powerful, and this builds on the effort to make common log, alert, and even date libraries using the Lurgle name. Download Lurgle.Alerting now, and check out the other Lurgles!
Comments