private async Task DeliverMessageAsync(Message message)
{
var accountRepository = _container.GetInstance <IAccountRepository>();
var messageRepository = _container.GetInstance <IMessageRepository>();
var folderRepository = _container.GetInstance <IFolderRepository>();
var dnsClient = _container.GetInstance <IDnsClient>();
message.NumberOfDeliveryAttempts++;
bool isLastAttempt = message.NumberOfDeliveryAttempts >= 3;
var deliveryResults = new List <DeliveryResult>();
try
{
var remainingRecipients = new List <Recipient>(message.Recipients);
var localDelivery = new LocalDelivery(accountRepository, messageRepository, folderRepository, _log);
deliveryResults.AddRange(await localDelivery.DeliverAsync(message, remainingRecipients.Where(recipient => recipient.AccountId != 0).ToList()));
var externalDelivery = new ExternalDelivery(messageRepository, dnsClient, _log);
deliveryResults.AddRange(await externalDelivery.DeliverAsync(message, remainingRecipients.Where(recipient => recipient.AccountId == 0).ToList()));
var failedRecipients =
deliveryResults.Where(result => result.ReplyCodeSeverity == ReplyCodeSeverity.PermanentNegative ||
(isLastAttempt && result.ReplyCodeSeverity == ReplyCodeSeverity.TransientNegative));
await SubmitBounceMessageAsync(message, failedRecipients);
var deliveryCompleted =
deliveryResults.Any(result => result.ReplyCodeSeverity == ReplyCodeSeverity.TransientNegative);
if (isLastAttempt || !deliveryCompleted)
{
await messageRepository.DeleteAsync(message);
}
}
catch (Exception ex)
{
var logEvent = new LogEvent()
{
EventType = LogEventType.Application,
LogLevel = LogLevel.Error,
Protocol = "SMTPD",
};
if (isLastAttempt)
{
logEvent.Message = "Failed delivering message due to an error. Giving up.";
}
else
{
logEvent.Message = "Failed delivering message due to an error. Will retry later.";
}
_log.LogException(logEvent, ex);
if (isLastAttempt)
{
await messageRepository.DeleteAsync(message);
}
else
{
await messageRepository.UpdateAsync(message);
}
}
}