Added Smtp reconnect on connection loss
This commit is contained in:
parent
8563391584
commit
1193d76838
|
@ -4,7 +4,7 @@ public interface IEmailService : IAsyncDisposable {
|
|||
ValueTask ConnectAsync(CancellationToken cancellation);
|
||||
ValueTask DisconnectAsync(CancellationToken cancellation);
|
||||
|
||||
ValueTask SendEmailAsync(IEmail email);
|
||||
ValueTask SendEmailAsync(IEmail email, CancellationToken cancellation = default);
|
||||
}
|
||||
|
||||
public sealed class NoOpEmailService : IEmailService {
|
||||
|
@ -12,5 +12,5 @@ public sealed class NoOpEmailService : IEmailService {
|
|||
|
||||
public ValueTask ConnectAsync(CancellationToken cancellation) => ValueTask.CompletedTask;
|
||||
public ValueTask DisconnectAsync(CancellationToken cancellation) => ValueTask.CompletedTask;
|
||||
public ValueTask SendEmailAsync(IEmail email) => ValueTask.CompletedTask;
|
||||
public ValueTask SendEmailAsync(IEmail email, CancellationToken cancellation = default) => ValueTask.CompletedTask;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using MailKit.Net.Smtp;
|
||||
using MailKit;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
|
@ -43,7 +44,7 @@ public class SmtpEmailService(ILogger<SmtpEmailService> logger, IOptions<EmailCo
|
|||
Client = null;
|
||||
}
|
||||
|
||||
public async ValueTask SendEmailAsync(IEmail email) {
|
||||
public async ValueTask SendEmailAsync(IEmail email, CancellationToken cancellation = default) {
|
||||
if (Client is null) throw new ApplicationException("Not connected.");
|
||||
|
||||
var message = new MimeMessage {
|
||||
|
@ -66,10 +67,13 @@ public class SmtpEmailService(ILogger<SmtpEmailService> logger, IOptions<EmailCo
|
|||
int retryCount = 0;
|
||||
while (retryCount < 3) {
|
||||
try {
|
||||
await Client.SendAsync(message);
|
||||
await Client.SendAsync(message, cancellation);
|
||||
Logger.LogInformation("Successfully send mail to {email} (subject: {subject}).",
|
||||
email.ReceiverEmail, email.Subject);
|
||||
return;
|
||||
} catch (ServiceNotConnectedException ex) {
|
||||
Logger.LogWarning(ex, "Not connected, attempting reconnect.");
|
||||
if (!await TryReconnect(cancellation)) throw;
|
||||
} catch (Exception ex) {
|
||||
retryCount++;
|
||||
Logger.LogWarning(ex, "Error sending E-Mail to {email}. Try: {RetryCount}.",
|
||||
|
@ -80,4 +84,27 @@ public class SmtpEmailService(ILogger<SmtpEmailService> logger, IOptions<EmailCo
|
|||
// throw new EmailNotSendException();
|
||||
Logger.LogError("Giving up");
|
||||
}
|
||||
|
||||
private async ValueTask<bool> TryReconnect(CancellationToken cancellation) {
|
||||
int reconnectCount = 0;
|
||||
while (true) {
|
||||
try {
|
||||
await DisconnectAsync(cancellation);
|
||||
await ConnectAsync(cancellation);
|
||||
return true;
|
||||
} catch (Exception ex1) {
|
||||
reconnectCount++;
|
||||
// 2^11 = 2048 seconds ~= 34 minutes
|
||||
if (reconnectCount <= 11) {
|
||||
// 2 4 6 8 16 32 64... seconds
|
||||
int waitTime = (int)Math.Pow(2, reconnectCount);
|
||||
Logger.LogError(ex1, "Reconnect failed, Try: {ReconnectTry}. Will wait {ReconnectWaitTime} Seconds for next attempt.", reconnectCount, waitTime);
|
||||
await Task.Delay(TimeSpan.FromSeconds(waitTime), cancellation);
|
||||
} else {
|
||||
Logger.LogCritical(ex1, "Reconnect retry count exceeded, giving up.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue