public async IAsyncEnumerable <IMailMessage> GetMessagesAsync(EmailConfig.IncomingConfig cfg, MailQuery?query = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { if (!new[] { MailProtocol.Imap, MailProtocol.Pop3 }.Contains(cfg.Protocol)) { throw new InvalidOperationException($"Invalid email protocol: {cfg.Protocol}"); } var container = await Policy .Handle <SocketException>().Or <System.IO.IOException>().Or <SslHandshakeException>() .WaitAndRetryAsync(_retryConfig.Max, _ => _retryConfig.Delay, (exc, delay, attempt, _) => _log.LogError(exc, Message.ConnError, attempt, cfg, delay)) .ExecuteAsync(token => InitContainerAsync(_client, cfg, token), cancellationToken); if (container == null) { throw new InvalidOperationException("Message container must be initialized properly"); } var ids = await GetMessageIdsAsync(container, query?.Limit, cancellationToken); foreach (var id in ids) { var message = await TryOrNull(token => GetMessageAsync(container, id, token), cancellationToken, Message.ReceiveError, _retryConfig.Max, id, cfg.Username); if (message == null || (!query?.AutoDelete ?? false)) { continue; } _ = await TryOrNull(token => DeleteMessageAsync(container, id, token), cancellationToken, Message.DeleteError, _retryConfig.Max, id, cfg.Username); yield return(message.ToPort()); } await _client.DisconnectAsync(true, cancellationToken); }
protected override async Task <IMailFolder?> InitContainerAsync(IImapClient client, EmailConfig.IncomingConfig config, CancellationToken cancellationToken) { _ = await base.InitContainerAsync(client, config, cancellationToken); var mailbox = await client.GetFolderAsync(config.MailBox, cancellationToken); if (mailbox == null) { throw new InvalidOperationException( $"Email account {config.Username} doesn't have mailbox '{config.MailBox}'"); } _ = await mailbox.OpenAsync(FolderAccess.ReadWrite, cancellationToken); return(mailbox); }