public async Task LookupWithFallback_FailedAll() { var mockMailReference = new MockMailReference( "mock-1", "*****@*****.**", new[] { "*****@*****.**" }.ToImmutableList(), true, "Some text", _queue); _queue.References.Add(mockMailReference); _dns.AddMx("example.com", "first.example.com", 10); _dns.AddIp("first.example.com", IPAddress.Parse("10.0.0.1")); Task executeTask = Task.Run( () => _transfer.SendMailsToDomain("example.com", new[] { mockMailReference }, CancellationToken.None)); MockTcpConnectionProvider.MockTcpClient client = await GetClientFor(IPAddress.Parse("10.0.0.1")); await WriteToAsync( client.HalfStream, @"554 Failed 554 Failed "); await executeTask; Assert.Equal(1, _queue.References.Count); Assert.Equal(0, _queue.DeletedReferences.Count); SmtpFailureData failure = _failures.GetFailure("mock-1", false); Assert.NotNull(failure); Assert.Equal(1, failure.Retries); Assert.InRange(failure.FirstFailure, DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1), DateTime.UtcNow); }
public SmtpFailureData ShouldAttemptRedelivery(IMailReference mail) { SmtpFailureData failure = _failures.GetFailure(mail.Id, true); if (failure.Retries + 1 >= s_retryDelays.Length) { return(null); } return(failure); }
public void ShouldAttemptRetryAfterSingleFailure() { Assert.NotNull( _transfer.ShouldAttemptRedelivery( new MockMailReference( "mock-1", "*****@*****.**", new[] { "*****@*****.**" }.ToImmutableList(), true, _queue))); SmtpFailureData failure = _failures.GetFailure("mock-1", false); Assert.NotNull(failure); Assert.InRange(failure.FirstFailure, DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1), DateTime.UtcNow); }
public SmtpFailureData GetFailure(string mailId, bool createIfMissing) { if (!CurrentFailures.TryGetValue(mailId, out SmtpFailureData failure)) { if (createIfMissing) { failure = new SmtpFailureData(mailId) { FirstFailure = DateTimeOffset.UtcNow, Retries = 0 }; CurrentFailures.Add(mailId, failure); } } return(failure); }
public SmtpFailureData GetFailure(string mailId, bool createIfMissing) { if (!_failures.Value.TryGetValue(mailId, out SmtpFailureData failure)) { if (!createIfMissing) { return(null); } failure = new SmtpFailureData(mailId) { FirstFailure = DateTimeOffset.UtcNow, Retries = 0 }; _failures.Value.Add(mailId, failure); } return(failure); }
public bool IsReadyToSend(IMailReference mail) { SmtpFailureData failure = _failures.GetFailure(mail.Id, false); if (failure == null) { return(true); } TimeSpan currentLag = DateTimeOffset.UtcNow - failure.FirstFailure; if (currentLag < CalculateNextRetryInterval(failure.Retries)) { return(false); } return(true); }
private async Task HandleFailedMailsAsync(IReadOnlyList <IMailReference> unsent) { foreach (IMailReference mail in unsent) { SmtpFailureData retryData = ShouldAttemptRedelivery(mail); if (retryData == null) { // We're giving up, forget about it _failures.RemoveFailure(mail.Id); await HandleRejectedMailAsync(mail); await _queue.DeleteAsync(mail); } else { retryData.Retries++; } } }