Mail queues.

This commit is contained in:
Burak Kaan Köse
2025-10-30 17:15:05 +01:00
parent b0ac6e4e55
commit 2d81d07c0a
13 changed files with 579 additions and 472 deletions
@@ -1,17 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Gmail.v1.Data;
using MimeKit;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Calendar;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Misc;
using Wino.Services;
using Wino.Services.Extensions;
namespace Wino.Core.Extensions;
@@ -121,41 +118,6 @@ public static class GoogleIntegratorExtensions
return GetNormalizedLabelName(lastPart);
}
/// <summary>
/// Returns MailCopy out of native Gmail message and converted MimeMessage of that native messaage.
/// </summary>
/// <param name="gmailMessage">Gmail Message</param>
/// <param name="mimeMessage">MimeMessage representation of that native message.</param>
/// <returns>MailCopy object that is ready to be inserted to database.</returns>
public static MailCopy AsMailCopy(this Message gmailMessage, MimeMessage mimeMessage)
{
bool isUnread = gmailMessage.GetIsUnread();
bool isFocused = gmailMessage.GetIsFocused();
bool isFlagged = gmailMessage.GetIsFlagged();
bool isDraft = gmailMessage.GetIsDraft();
return new MailCopy()
{
CreationDate = mimeMessage.Date.UtcDateTime,
Subject = HttpUtility.HtmlDecode(mimeMessage.Subject),
FromName = MailkitClientExtensions.GetActualSenderName(mimeMessage),
FromAddress = MailkitClientExtensions.GetActualSenderAddress(mimeMessage),
PreviewText = HttpUtility.HtmlDecode(gmailMessage.Snippet),
ThreadId = gmailMessage.ThreadId,
Importance = (MailImportance)mimeMessage.Importance,
Id = gmailMessage.Id,
IsDraft = isDraft,
HasAttachments = mimeMessage.Attachments.Any(),
IsRead = !isUnread,
IsFlagged = isFlagged,
IsFocused = isFocused,
InReplyTo = mimeMessage.InReplyTo,
MessageId = mimeMessage.MessageId,
References = mimeMessage.References.GetReferences(),
FileId = Guid.NewGuid()
};
}
public static List<RemoteAccountAlias> GetRemoteAliases(this ListSendAsResponse response)
{
return response?.SendAs?.Select(a => new RemoteAccountAlias()
@@ -65,6 +65,11 @@ public interface IDefaultChangeProcessor
Task<bool> IsMailExistsInFolderAsync(string messageId, Guid folderId);
Task<List<string>> AreMailsExistsAsync(IEnumerable<string> mailCopyIds);
Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string synchronizationDeltaIdentifier);
Task ClearMailItemQueueAsync(Guid accountId);
Task AddMailItemQueueItemsAsync(IEnumerable<MailItemQueue> queueItems);
Task<int> GetMailItemQueueCountAsync(Guid accountId);
Task<List<MailItemQueue>> GetMailItemQueueAsync(Guid accountId, int take);
Task UpdateMailItemQueueAsync(IEnumerable<MailItemQueue> queueItems);
}
public interface IGmailChangeProcessor : IDefaultChangeProcessor
@@ -208,6 +213,21 @@ public class DefaultChangeProcessor(IDatabaseService databaseService,
public Task UpdateCalendarDeltaSynchronizationToken(Guid calendarId, string deltaToken)
=> CalendarService.UpdateCalendarDeltaSynchronizationToken(calendarId, deltaToken);
public Task ClearMailItemQueueAsync(Guid accountId)
=> MailService.ClearMailItemQueueAsync(accountId);
public Task AddMailItemQueueItemsAsync(IEnumerable<MailItemQueue> queueItems)
=> MailService.AddMailItemQueueItemsAsync(queueItems);
public Task<int> GetMailItemQueueCountAsync(Guid accountId)
=> MailService.GetMailItemQueueCountAsync(accountId);
public Task<List<MailItemQueue>> GetMailItemQueueAsync(Guid accountId, int take)
=> MailService.GetMailItemQueueAsync(accountId, take);
public Task UpdateMailItemQueueAsync(IEnumerable<MailItemQueue> queueItems)
=> MailService.UpdateMailItemQueueAsync(queueItems);
public async Task DeleteUserMailCacheAsync(Guid accountId)
{
await _mimeFileService.DeleteUserMimeCacheAsync(accountId).ConfigureAwait(false);
File diff suppressed because it is too large Load Diff
+16 -9
View File
@@ -41,22 +41,27 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
/// <summary>
/// How many items must be downloaded per folder when the folder is first synchronized.
/// Only metadata is downloaded during sync - MIME content is fetched on-demand when user reads mail.
/// </summary>
public abstract uint InitialMessageDownloadCountPerFolder { get; }
/// <summary>
/// Number of MIME messages to download during initial synchronization per folder.
/// For the first messages in each folder during initial sync, both metadata and MIME content will be downloaded.
/// Subsequent messages will only have metadata downloaded, with MIME content fetched on-demand.
/// DEPRECATED: MIME messages are no longer downloaded during synchronization.
/// MIME content is only downloaded when explicitly needed (e.g., when user reads a message).
/// This property is kept for backward compatibility but is no longer used.
/// </summary>
public virtual int InitialSyncMimeDownloadCount => 50;
[Obsolete("MIME messages are no longer downloaded during sync. Use DownloadMissingMimeMessageAsync instead.")]
public virtual int InitialSyncMimeDownloadCount => 0;
/// <summary>
/// Creates a new Wino Mail Item package out of native message type with full Mime.
/// Creates a new Wino Mail Item package out of native message type with metadata only.
/// NO MIME content is downloaded during synchronization - only headers and essential metadata.
/// MIME will be downloaded on-demand when user explicitly reads the message.
/// </summary>
/// <param name="message">Native message type for the synchronizer.</param>
/// <param name="assignedFolder">Folder to assign the mail to.</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Package that encapsulates downloaded Mime and additional information for adding new mail.</returns>
/// <returns>Package with MailCopy metadata. MimeMessage will be null during sync.</returns>
public abstract Task<List<NewMailItemPackage>> CreateNewMailPackagesAsync(TMessageType message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default);
/// <summary>
@@ -86,13 +91,15 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
/// <summary>
/// Creates a MailCopy object with minimal properties from the native message type.
/// This is used for queue-based sync to avoid downloading full MIME messages.
/// Only overridden by synchronizers that support the new queue-based sync.
/// This is used during synchronization to create mail entries WITHOUT downloading MIME content.
/// Only metadata (headers, labels, flags) is extracted from the native message format.
/// MIME content will be downloaded later on-demand when user reads the message.
/// Only overridden by synchronizers that support metadata-only synchronization.
/// </summary>
/// <param name="message">Native message type</param>
/// <param name="assignedFolder">Folder this message belongs to</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>MailCopy with minimal properties</returns>
/// <returns>MailCopy with minimal properties populated from metadata</returns>
protected virtual Task<MailCopy> CreateMinimalMailCopyAsync(TMessageType message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default) => Task.FromResult<MailCopy>(null);
/// <summary>