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);
        }
Beispiel #2
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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++;
                }
            }
        }