Merge pull request #341 from bkaankose/hotfix/FixGmailDelete

Fixing Gmail SENT label deletes.
This commit is contained in:
Burak Kaan Köse
2024-08-30 00:03:53 +02:00
committed by GitHub
4 changed files with 38 additions and 13 deletions

View File

@@ -21,7 +21,6 @@ namespace Wino.Core.Integration.Processors
{ {
Task UpdateAccountAsync(MailAccount account); Task UpdateAccountAsync(MailAccount account);
Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string deltaSynchronizationIdentifier); Task<string> UpdateAccountDeltaSynchronizationIdentifierAsync(Guid accountId, string deltaSynchronizationIdentifier);
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId); Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead); Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead);
Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged); Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged);
@@ -53,6 +52,7 @@ namespace Wino.Core.Integration.Processors
public interface IGmailChangeProcessor : IDefaultChangeProcessor public interface IGmailChangeProcessor : IDefaultChangeProcessor
{ {
Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId); Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId);
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
} }
public interface IOutlookChangeProcessor : IDefaultChangeProcessor public interface IOutlookChangeProcessor : IDefaultChangeProcessor
@@ -135,8 +135,7 @@ namespace Wino.Core.Integration.Processors
public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId) public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId); => MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId);
public Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.CreateAssignmentAsync(accountId, mailCopyId, remoteFolderId);
public Task DeleteMailAsync(Guid accountId, string mailId) public Task DeleteMailAsync(Guid accountId, string mailId)
=> MailService.DeleteMailAsync(accountId, mailId); => MailService.DeleteMailAsync(accountId, mailId);

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Services; using Wino.Core.Services;
@@ -12,5 +13,8 @@ namespace Wino.Core.Integration.Processors
public Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId) public Task MapLocalDraftAsync(string mailCopyId, string newDraftId, string newThreadId)
=> MailService.MapLocalDraftAsync(mailCopyId, newDraftId, newThreadId); => MailService.MapLocalDraftAsync(mailCopyId, newDraftId, newThreadId);
public Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.CreateAssignmentAsync(accountId, mailCopyId, remoteFolderId);
} }
} }

View File

@@ -409,12 +409,11 @@ namespace Wino.Core.Services
foreach (var mailItem in allMails) foreach (var mailItem in allMails)
{ {
await DeleteMailInternalAsync(mailItem).ConfigureAwait(false); // Delete mime file as well.
// Delete mime file.
// Even though Gmail might have multiple copies for the same mail, we only have one MIME file for all. // Even though Gmail might have multiple copies for the same mail, we only have one MIME file for all.
// Their FileId is inserted same. // Their FileId is inserted same.
await _mimeFileService.DeleteMimeMessageAsync(accountId, mailItem.FileId);
await DeleteMailInternalAsync(mailItem, preserveMimeFile: false).ConfigureAwait(false);
} }
} }
@@ -457,7 +456,7 @@ namespace Wino.Core.Services
ReportUIChange(new MailUpdatedMessage(mailCopy)); ReportUIChange(new MailUpdatedMessage(mailCopy));
} }
private async Task DeleteMailInternalAsync(MailCopy mailCopy) private async Task DeleteMailInternalAsync(MailCopy mailCopy, bool preserveMimeFile)
{ {
if (mailCopy == null) if (mailCopy == null)
{ {
@@ -473,7 +472,7 @@ namespace Wino.Core.Services
// If there are no more copies exists of the same mail, delete the MIME file as well. // If there are no more copies exists of the same mail, delete the MIME file as well.
var isMailExists = await IsMailExistsAsync(mailCopy.Id).ConfigureAwait(false); var isMailExists = await IsMailExistsAsync(mailCopy.Id).ConfigureAwait(false);
if (!isMailExists) if (!isMailExists && !preserveMimeFile)
{ {
await _mimeFileService.DeleteMimeMessageAsync(mailCopy.AssignedAccount.Id, mailCopy.FileId).ConfigureAwait(false); await _mimeFileService.DeleteMimeMessageAsync(mailCopy.AssignedAccount.Id, mailCopy.FileId).ConfigureAwait(false);
} }
@@ -554,6 +553,19 @@ namespace Wino.Core.Services
return; return;
} }
if (mailCopy.AssignedFolder.SpecialFolderType == SpecialFolderType.Sent &&
localFolder.SpecialFolderType == SpecialFolderType.Deleted)
{
// Sent item is deleted.
// Gmail does not delete the sent items, but moves them to the deleted folder.
// API doesn't allow removing Sent label.
// Here we intercept this behavior, removing the Sent copy of the mail and adding the Deleted copy.
// This way item will only be visible in Trash folder as in Gmail Web UI.
// Don't delete MIME file since if exists.
await DeleteMailInternalAsync(mailCopy, preserveMimeFile: true).ConfigureAwait(false);
}
// Copy one of the mail copy and assign it to the new folder. // Copy one of the mail copy and assign it to the new folder.
// We don't need to create a new MIME pack. // We don't need to create a new MIME pack.
// Therefore FileId is not changed for the new MailCopy. // Therefore FileId is not changed for the new MailCopy.
@@ -585,7 +597,7 @@ namespace Wino.Core.Services
return; return;
} }
await DeleteMailInternalAsync(mailItem).ConfigureAwait(false); await DeleteMailInternalAsync(mailItem, preserveMimeFile: false).ConfigureAwait(false);
} }
public async Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package) public async Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package)

View File

@@ -595,13 +595,23 @@ namespace Wino.Core.Synchronizers
{ {
return CreateBatchedHttpBundleFromGroup(request, (items) => return CreateBatchedHttpBundleFromGroup(request, (items) =>
{ {
// Sent label can't be removed from mails for Gmail.
// They are automatically assigned by Gmail.
// When you delete sent mail from gmail web portal, it's moved to Trash
// but still has Sent label. It's just hidden from the user.
// Proper assignments will be done later on CreateAssignment call to mimic this behavior.
var batchModifyRequest = new BatchModifyMessagesRequest var batchModifyRequest = new BatchModifyMessagesRequest
{ {
Ids = items.Select(a => a.Item.Id.ToString()).ToList(), Ids = items.Select(a => a.Item.Id.ToString()).ToList(),
AddLabelIds = new[] { request.ToFolder.RemoteFolderId }, AddLabelIds = [request.ToFolder.RemoteFolderId]
RemoveLabelIds = new[] { request.FromFolder.RemoteFolderId }
}; };
// Only add remove label ids if the source folder is not sent folder.
if (request.FromFolder.SpecialFolderType != SpecialFolderType.Sent)
{
batchModifyRequest.RemoveLabelIds = [request.FromFolder.RemoteFolderId];
}
return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me"); return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
}); });
} }