/// <summary> /// Publish requested mail content to the stream. /// </summary> /// <param name="cancel"></param> /// <param name="uid"></param> /// <returns></returns> private async Task PublishRequestedByUidMailContent(CancellationToken cancel, string uid) { try { using (IMailStorage <MailContentEntity> storage = _mailContentStorageFactory()) { // 1. Check if content already exists in the database. if (storage.Exists(x => x.Uid == uid)) { var mailContentEntity = storage.FindOne(x => x.Uid == uid); if (mailContentEntity == null || !mailContentEntity.IsComplete) { // 2. If content is not yet downloaded of any reason, download it and publish afterwards. await RunDownloadContentAsyncLoop(cancel, new List <string>() { uid }); } else { _mailContentStream.OnNext(new MailContent(mailContentEntity)); } } } } catch (Exception e) { Logger.Error(e, "PublishRequestedByUidMailContent"); } }
/// <summary> /// Download MailContent for given uids. /// </summary> /// <param name="cancel"></param> /// <param name="uids"></param> /// <returns></returns> private async Task RunDownloadContentAsyncLoop(CancellationToken cancel, List <string> uids) { if (uids == null || uids.Count == 0) { return; } // Create mail client. IMailClient client = (new TrivialMailDllFactory()).Build(_serverType); try { await Task.Factory.StartNew(() => { client.Connect(_serverEncryption, _host); client.Login(_user, _password); // If is not connected or encrypted (if req) then will break and try to reconnect. if (client.IsConnected && (_serverEncryption == MailServerEncryption.Unencrypted || client.IsEncrypted)) { using (IMailStorage <MailContentEntity> storage = _mailContentStorageFactory()) { foreach (var uid in uids) { if (string.IsNullOrWhiteSpace(uid)) { continue; } if (cancel.IsCancellationRequested) { break; } var downloadRequired = true; MailContentEntity mailContentEntity = null; if (storage.Exists(x => x.Uid == uid)) { mailContentEntity = storage.FindOne(x => x.Uid == uid); if (mailContentEntity != null && mailContentEntity.IsComplete) { downloadRequired = false; } } if (downloadRequired) { // 1. Insert empty MailContent with only uid set to prevent other concurrent method to download same content. mailContentEntity = new MailContentEntity() { Uid = uid, IsComplete = false }; storage.Insert(new List <MailContentEntity>() { mailContentEntity }); // 2. Download complete email. var message = client.GetMessageByUid(uid); // Note: MailDll documentation states that message can be null. if (message != null) { IMail email = new MailBuilder().CreateFromEml(message); if (email != null) { // 3. Update database with downloaded email content. mailContentEntity = new MailContentEntity() { Uid = uid, Date = email?.Date == null ? DateTime.MinValue : email.Date.Value, Html = email.Html, MessageId = email.MessageID, Text = email.Text, CustomHeader = email?.Document.Root.Headers["x-spam"], IsComplete = true }; storage.Update(new List <MailContentEntity>() { mailContentEntity }); // Publish MailContent. _mailContentStream.OnNext(new MailContent(mailContentEntity)); } } } } } } }, cancel, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } catch (Exception e) { Logger.Error(e, $"RunDownloadContentAsync"); } finally { client?.Close(); } }