draft header

This commit is contained in:
Burak Kaan Köse
2025-11-01 01:04:04 +01:00
parent 4d0d2ff099
commit 2a67a1e961
2 changed files with 54 additions and 19 deletions
@@ -323,10 +323,24 @@ public static class OutlookIntegratorExtensions
var headers = new List<InternetMessageHeader>(); var headers = new List<InternetMessageHeader>();
// PRIORITY: Always include WinoLocalDraftHeader first if it exists
// This is critical for draft mapping functionality
var winoDraftHeader = mime.Headers.FirstOrDefault(h => h.Field == Domain.Constants.WinoLocalDraftHeader);
int includedHeaderCount = 0; int includedHeaderCount = 0;
if (winoDraftHeader != null)
{
var headerValue = winoDraftHeader.Value.Length >= 995 ? winoDraftHeader.Value.Substring(0, 995) : winoDraftHeader.Value;
headers.Add(new InternetMessageHeader() { Name = winoDraftHeader.Field, Value = headerValue });
includedHeaderCount++;
}
// Include other headers up to the limit (excluding the already added WinoLocalDraftHeader)
foreach (var header in mime.Headers) foreach (var header in mime.Headers)
{ {
if (header.Field == Domain.Constants.WinoLocalDraftHeader)
continue; // Already processed above
if (!headersToIgnore.Contains(header.Field)) if (!headersToIgnore.Contains(header.Field))
{ {
var headerName = headersToModify.Contains(header.Field) ? $"X-{header.Field}" : header.Field; var headerName = headersToModify.Contains(header.Field) ? $"X-{header.Field}" : header.Field;
+40 -19
View File
@@ -98,6 +98,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
"Subject", "Subject",
"ParentFolderId", "ParentFolderId",
"InternetMessageId", "InternetMessageId",
"InternetMessageHeaders",
]; ];
private readonly SemaphoreSlim _handleItemRetrievalSemaphore = new(1); private readonly SemaphoreSlim _handleItemRetrievalSemaphore = new(1);
@@ -575,7 +576,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
if (message != null) if (message != null)
{ {
// Create MailCopy from metadata only // Create MailCopy from metadata only
var mailCopy = CreateMailCopyFromMessage(message, folder); var mailCopy = await CreateMailCopyFromMessageAsync(message, folder).ConfigureAwait(false);
if (mailCopy != null) if (mailCopy != null)
{ {
@@ -666,7 +667,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
/// Creates a MailCopy from an Outlook Message with metadata only (centralized method). /// Creates a MailCopy from an Outlook Message with metadata only (centralized method).
/// This replaces the scattered CreateMinimalMailCopyAsync and AsMailCopy calls. /// This replaces the scattered CreateMinimalMailCopyAsync and AsMailCopy calls.
/// </summary> /// </summary>
private MailCopy CreateMailCopyFromMessage(Message message, MailItemFolder assignedFolder) private async Task<MailCopy> CreateMailCopyFromMessageAsync(Message message, MailItemFolder assignedFolder)
{ {
if (message == null) return null; if (message == null) return null;
@@ -675,6 +676,37 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
mailCopy.UniqueId = Guid.NewGuid(); mailCopy.UniqueId = Guid.NewGuid();
mailCopy.FileId = Guid.NewGuid(); mailCopy.FileId = Guid.NewGuid();
// Check for draft mapping if this is a draft with WinoLocalDraftHeader
if (message.IsDraft.GetValueOrDefault() && message.InternetMessageHeaders != null)
{
var winoDraftHeader = message.InternetMessageHeaders
.FirstOrDefault(h => string.Equals(h.Name, Domain.Constants.WinoLocalDraftHeader, StringComparison.OrdinalIgnoreCase));
if (winoDraftHeader != null && Guid.TryParse(winoDraftHeader.Value, out Guid localDraftCopyUniqueId))
{
// This message belongs to existing local draft copy.
// We don't need to create a new mail copy for this message, just update the existing one.
bool isMappingSuccessful = await _outlookChangeProcessor.MapLocalDraftAsync(
Account.Id,
localDraftCopyUniqueId,
mailCopy.Id,
mailCopy.DraftId,
mailCopy.ThreadId);
if (isMappingSuccessful)
{
_logger.Debug("Successfully mapped remote draft {RemoteId} to local draft {LocalId}",
mailCopy.Id, localDraftCopyUniqueId);
return null; // Don't create new mail copy, existing one was updated
}
// Local copy doesn't exist. Continue execution to insert mail copy.
_logger.Debug("Local draft copy {LocalId} not found, creating new mail copy for {RemoteId}",
localDraftCopyUniqueId, mailCopy.Id);
}
}
return mailCopy; return mailCopy;
} }
@@ -687,10 +719,10 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
await QueueMailIdsForFolderAsync(folder, cancellationToken).ConfigureAwait(false); await QueueMailIdsForFolderAsync(folder, cancellationToken).ConfigureAwait(false);
} }
protected override Task<MailCopy> CreateMinimalMailCopyAsync(Message message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default) protected override async Task<MailCopy> CreateMinimalMailCopyAsync(Message message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default)
{ {
// Use centralized method // Use centralized method
return Task.FromResult(CreateMailCopyFromMessage(message, assignedFolder)); return await CreateMailCopyFromMessageAsync(message, assignedFolder).ConfigureAwait(false);
} }
private async Task<Message> GetMessageByIdAsync(string messageId, CancellationToken cancellationToken = default) private async Task<Message> GetMessageByIdAsync(string messageId, CancellationToken cancellationToken = default)
@@ -1760,23 +1792,12 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
public override async Task<List<NewMailItemPackage>> CreateNewMailPackagesAsync(Message message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default) public override async Task<List<NewMailItemPackage>> CreateNewMailPackagesAsync(Message message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default)
{ {
// Download MIME message for specific scenarios (e.g., search results, draft handling) // Download MIME message for specific scenarios (e.g., search results, draft handling)
// During normal sync, this method should not be called - use CreateMailCopyFromMessage instead // During normal sync, this method should not be called - use CreateMailCopyFromMessageAsync instead
var mimeMessage = await DownloadMimeMessageAsync(message.Id, cancellationToken).ConfigureAwait(false); var mimeMessage = await DownloadMimeMessageAsync(message.Id, cancellationToken).ConfigureAwait(false);
var mailCopy = CreateMailCopyFromMessage(message, assignedFolder); var mailCopy = await CreateMailCopyFromMessageAsync(message, assignedFolder).ConfigureAwait(false);
if (message.IsDraft.GetValueOrDefault() // If draft mapping was successful, mailCopy will be null
&& mimeMessage.Headers.Contains(Domain.Constants.WinoLocalDraftHeader) if (mailCopy == null) return null;
&& Guid.TryParse(mimeMessage.Headers[Domain.Constants.WinoLocalDraftHeader], out Guid localDraftCopyUniqueId))
{
// This message belongs to existing local draft copy.
// We don't need to create a new mail copy for this message, just update the existing one.
bool isMappingSuccessful = await _outlookChangeProcessor.MapLocalDraftAsync(Account.Id, localDraftCopyUniqueId, mailCopy.Id, mailCopy.DraftId, mailCopy.ThreadId);
if (isMappingSuccessful) return null;
// Local copy doesn't exists. Continue execution to insert mail copy.
}
// Outlook messages can only be assigned to 1 folder at a time. // Outlook messages can only be assigned to 1 folder at a time.
// Therefore we don't need to create multiple copies of the same message for different folders. // Therefore we don't need to create multiple copies of the same message for different folders.