Refactored impa synchronization.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using SQLite;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
@@ -63,6 +64,26 @@ public class DatabaseService : IDatabaseService
|
||||
Connection.CreateTableAsync<Reminder>(),
|
||||
Connection.CreateTableAsync<MailInvitationCalendarMapping>()
|
||||
);
|
||||
|
||||
await EnsureSchemaUpgradesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task EnsureSchemaUpgradesAsync()
|
||||
{
|
||||
var folderColumns = await Connection.GetTableInfoAsync(nameof(MailItemFolder)).ConfigureAwait(false);
|
||||
|
||||
if (!folderColumns.Any(c => c.Name == nameof(MailItemFolder.HighestKnownUid)))
|
||||
{
|
||||
await Connection
|
||||
.ExecuteAsync($"ALTER TABLE {nameof(MailItemFolder)} ADD COLUMN {nameof(MailItemFolder.HighestKnownUid)} INTEGER NOT NULL DEFAULT 0")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!folderColumns.Any(c => c.Name == nameof(MailItemFolder.LastUidReconcileUtc)))
|
||||
{
|
||||
await Connection
|
||||
.ExecuteAsync($"ALTER TABLE {nameof(MailItemFolder)} ADD COLUMN {nameof(MailItemFolder.LastUidReconcileUtc)} TEXT NULL")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,44 +93,47 @@ public static class MailkitClientExtensions
|
||||
return HtmlAgilityPackExtensions.GetPreviewText(message.HtmlBody);
|
||||
}
|
||||
|
||||
public static MailCopy GetMailDetails(this IMessageSummary messageSummary, MailItemFolder folder, MimeMessage mime)
|
||||
public static MailCopy GetMailDetails(this IMessageSummary messageSummary, MailItemFolder folder, MimeMessage mime = null)
|
||||
{
|
||||
// MessageSummary will only have UniqueId, Flags, ThreadId.
|
||||
// Other properties are extracted directly from the MimeMessage.
|
||||
// IMAP UIDs are unique only within a folder.
|
||||
// MailCopy.Id maps to {FolderId}_{UID} for deterministic folder-local identity.
|
||||
|
||||
// IMAP doesn't have unique id for mails.
|
||||
// All mails are mapped to specific folders with incremental Id.
|
||||
// Uid 1 may belong to different messages in different folders, but can never be
|
||||
// same for different messages in same folders.
|
||||
// Here we create arbitrary Id that maps the Id of the message with Folder UniqueId.
|
||||
// When folder becomes invalid, we'll clear out these MailCopies as well.
|
||||
var envelope = messageSummary.Envelope;
|
||||
|
||||
var messageUid = CreateUid(folder.Id, messageSummary.UniqueId.Id);
|
||||
var previewText = mime.GetPreviewText();
|
||||
var subject = mime?.Subject ?? envelope?.Subject ?? string.Empty;
|
||||
var previewText = mime != null ? mime.GetPreviewText() : GetPreviewText(messageSummary, subject);
|
||||
|
||||
// Use InternalDate (server received date) if available, otherwise fall back to Date header (sent date)
|
||||
var creationDate = messageSummary.InternalDate?.UtcDateTime ?? mime.Date.UtcDateTime;
|
||||
// Prefer InternalDate (server received time). Fall back to envelope date and finally UTC now.
|
||||
var creationDate = messageSummary.InternalDate?.UtcDateTime
|
||||
?? envelope?.Date?.UtcDateTime
|
||||
?? DateTime.UtcNow;
|
||||
|
||||
// Detect calendar invitation based on MIME content type
|
||||
var itemType = GetMailItemTypeFromMime(mime);
|
||||
var messageId = mime?.GetMessageId() ?? envelope?.MessageId ?? string.Empty;
|
||||
var fromName = mime != null ? GetActualSenderName(mime) : GetEnvelopeSenderName(envelope);
|
||||
var fromAddress = mime != null ? GetActualSenderAddress(mime) : GetEnvelopeSenderAddress(envelope);
|
||||
var references = mime?.References?.GetReferences() ?? messageSummary.References?.GetReferences();
|
||||
var inReplyTo = mime != null ? mime.GetInReplyTo() : envelope?.InReplyTo ?? string.Empty;
|
||||
var hasAttachments = mime != null ? mime.Attachments.Any() : false;
|
||||
var itemType = mime != null ? GetMailItemTypeFromMime(mime) : MailItemType.Mail;
|
||||
|
||||
var copy = new MailCopy()
|
||||
{
|
||||
Id = messageUid,
|
||||
CreationDate = creationDate,
|
||||
ThreadId = messageSummary.GetThreadId(),
|
||||
MessageId = mime.GetMessageId(),
|
||||
Subject = mime.Subject,
|
||||
MessageId = messageId,
|
||||
Subject = subject,
|
||||
IsRead = messageSummary.Flags.GetIsRead(),
|
||||
IsFlagged = messageSummary.Flags.GetIsFlagged(),
|
||||
PreviewText = previewText,
|
||||
FromAddress = GetActualSenderAddress(mime),
|
||||
FromName = GetActualSenderName(mime),
|
||||
FromAddress = fromAddress,
|
||||
FromName = fromName,
|
||||
IsFocused = false,
|
||||
Importance = mime.GetImportance(),
|
||||
References = mime.References?.GetReferences(),
|
||||
InReplyTo = mime.GetInReplyTo(),
|
||||
HasAttachments = mime.Attachments.Any(),
|
||||
Importance = mime != null ? mime.GetImportance() : MailImportance.Normal,
|
||||
References = references,
|
||||
InReplyTo = inReplyTo,
|
||||
HasAttachments = hasAttachments,
|
||||
FileId = Guid.NewGuid(),
|
||||
ItemType = itemType
|
||||
};
|
||||
@@ -138,6 +141,29 @@ public static class MailkitClientExtensions
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static string GetPreviewText(IMessageSummary messageSummary, string subjectFallback)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(messageSummary.PreviewText))
|
||||
return messageSummary.PreviewText;
|
||||
|
||||
return subjectFallback ?? string.Empty;
|
||||
}
|
||||
|
||||
private static string GetEnvelopeSenderName(Envelope envelope)
|
||||
{
|
||||
var mailbox = envelope?.From?.Mailboxes?.FirstOrDefault() ?? envelope?.Sender?.Mailboxes?.FirstOrDefault();
|
||||
if (mailbox == null)
|
||||
return Translator.UnknownSender;
|
||||
|
||||
return string.IsNullOrWhiteSpace(mailbox.Name) ? mailbox.Address : mailbox.Name;
|
||||
}
|
||||
|
||||
private static string GetEnvelopeSenderAddress(Envelope envelope)
|
||||
{
|
||||
var mailbox = envelope?.From?.Mailboxes?.FirstOrDefault() ?? envelope?.Sender?.Mailboxes?.FirstOrDefault();
|
||||
return mailbox?.Address ?? Translator.UnknownSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines MailItemType based on MIME message content type.
|
||||
/// Calendar invitations have text/calendar content type with METHOD parameter.
|
||||
|
||||
@@ -490,6 +490,9 @@ public class FolderService : BaseDatabaseService, IFolderService
|
||||
await Connection.UpdateAsync(folder, typeof(MailItemFolder)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task UpdateFolderHighestModeSeqAsync(Guid folderId, long highestModeSeq)
|
||||
=> Connection.ExecuteAsync("UPDATE MailItemFolder SET HighestModeSeq = ? WHERE Id = ?", highestModeSeq, folderId);
|
||||
|
||||
private async Task DeleteFolderAsync(MailItemFolder folder)
|
||||
{
|
||||
if (folder == null)
|
||||
|
||||
Reference in New Issue
Block a user