Improve alias capability model and Outlook alias sync
This commit is contained in:
@@ -250,7 +250,9 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
IsRootAlias = true,
|
||||
IsVerified = true,
|
||||
ReplyToAddress = address,
|
||||
Id = Guid.NewGuid()
|
||||
Id = Guid.NewGuid(),
|
||||
Source = AliasSource.Manual,
|
||||
SendCapability = AliasSendCapability.Confirmed
|
||||
};
|
||||
|
||||
await Connection.InsertAsync(rootAlias, typeof(MailAccountAlias)).ConfigureAwait(false);
|
||||
@@ -261,7 +263,7 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
public async Task<List<MailAccountAlias>> GetAccountAliasesAsync(Guid accountId)
|
||||
{
|
||||
return await Connection.QueryAsync<MailAccountAlias>(
|
||||
"SELECT * FROM MailAccountAlias WHERE AccountId = ? ORDER BY IsRootAlias DESC",
|
||||
"SELECT * FROM MailAccountAlias WHERE AccountId = ? ORDER BY IsRootAlias DESC, IsPrimary DESC, AliasAddress ASC",
|
||||
accountId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -491,11 +493,16 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
public async Task UpdateRemoteAliasInformationAsync(MailAccount account, List<RemoteAccountAlias> remoteAccountAliases)
|
||||
{
|
||||
var localAliases = await GetAccountAliasesAsync(account.Id).ConfigureAwait(false);
|
||||
var rootAlias = localAliases.Find(a => a.IsRootAlias);
|
||||
var normalizedRemoteAliases = remoteAccountAliases ?? [];
|
||||
|
||||
foreach (var remoteAlias in remoteAccountAliases)
|
||||
foreach (var remoteAlias in normalizedRemoteAliases)
|
||||
{
|
||||
var existingAlias = localAliases.Find(a => a.AccountId == account.Id && a.AliasAddress == remoteAlias.AliasAddress);
|
||||
if (string.IsNullOrWhiteSpace(remoteAlias?.AliasAddress))
|
||||
continue;
|
||||
|
||||
var existingAlias = localAliases.Find(a =>
|
||||
a.AccountId == account.Id &&
|
||||
a.AliasAddress.Equals(remoteAlias.AliasAddress, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (existingAlias == null)
|
||||
{
|
||||
@@ -509,7 +516,9 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
ReplyToAddress = remoteAlias.ReplyToAddress,
|
||||
Id = Guid.NewGuid(),
|
||||
IsRootAlias = remoteAlias.IsRootAlias,
|
||||
AliasSenderName = remoteAlias.AliasSenderName
|
||||
AliasSenderName = remoteAlias.AliasSenderName,
|
||||
Source = remoteAlias.Source,
|
||||
SendCapability = remoteAlias.SendCapability
|
||||
};
|
||||
|
||||
await Connection.InsertAsync(newAlias, typeof(MailAccountAlias));
|
||||
@@ -522,6 +531,8 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
existingAlias.IsVerified = remoteAlias.IsVerified;
|
||||
existingAlias.ReplyToAddress = remoteAlias.ReplyToAddress;
|
||||
existingAlias.AliasSenderName = remoteAlias.AliasSenderName;
|
||||
existingAlias.Source = remoteAlias.Source;
|
||||
existingAlias.SendCapability = remoteAlias.SendCapability;
|
||||
|
||||
await Connection.UpdateAsync(existingAlias, typeof(MailAccountAlias));
|
||||
}
|
||||
@@ -553,6 +564,21 @@ public class AccountService : BaseDatabaseService, IAccountService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateAliasSendCapabilityAsync(Guid accountId, string aliasAddress, AliasSendCapability capability)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(aliasAddress))
|
||||
return;
|
||||
|
||||
var aliases = await GetAccountAliasesAsync(accountId).ConfigureAwait(false);
|
||||
var alias = aliases.FirstOrDefault(a => a.AliasAddress.Equals(aliasAddress, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (alias == null)
|
||||
return;
|
||||
|
||||
alias.SendCapability = capability;
|
||||
await Connection.UpdateAsync(alias, typeof(MailAccountAlias)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task DeleteAccountAliasAsync(Guid aliasId)
|
||||
{
|
||||
// Create query to delete alias.
|
||||
|
||||
@@ -56,7 +56,8 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
public async Task<(MailCopy draftMailCopy, string draftBase64MimeMessage)> CreateDraftAsync(Guid accountId, DraftCreationOptions draftCreationOptions)
|
||||
{
|
||||
var composerAccount = await _accountService.GetAccountAsync(accountId).ConfigureAwait(false);
|
||||
var createdDraftMimeMessage = await CreateDraftMimeAsync(composerAccount, draftCreationOptions);
|
||||
var selectedAlias = await ResolveDraftAliasAsync(composerAccount, draftCreationOptions).ConfigureAwait(false);
|
||||
var createdDraftMimeMessage = await CreateDraftMimeAsync(composerAccount, draftCreationOptions, selectedAlias).ConfigureAwait(false);
|
||||
|
||||
var draftFolder = await _folderService.GetSpecialFolderByAccountIdAsync(composerAccount.Id, SpecialFolderType.Draft);
|
||||
|
||||
@@ -74,8 +75,8 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
UniqueId = Guid.Parse(mimeUniqueId),
|
||||
Id = Guid.NewGuid().ToString(), // This will be replaced after network call with the remote draft id.
|
||||
CreationDate = DateTime.UtcNow,
|
||||
FromAddress = primaryAlias?.AliasAddress ?? composerAccount.Address,
|
||||
FromName = composerAccount.SenderName,
|
||||
FromAddress = selectedAlias?.AliasAddress ?? primaryAlias?.AliasAddress ?? composerAccount.Address,
|
||||
FromName = selectedAlias?.AliasSenderName ?? composerAccount.SenderName,
|
||||
HasAttachments = false,
|
||||
Importance = MailImportance.Normal,
|
||||
Subject = createdDraftMimeMessage.Subject,
|
||||
@@ -1016,7 +1017,7 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
await _contactService.SaveAddressInformationAsync(contacts).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<MimeMessage> CreateDraftMimeAsync(MailAccount account, DraftCreationOptions draftCreationOptions)
|
||||
private async Task<MimeMessage> CreateDraftMimeAsync(MailAccount account, DraftCreationOptions draftCreationOptions, MailAccountAlias selectedAlias)
|
||||
{
|
||||
// This unique id is stored in mime headers for Wino to identify remote message with local copy.
|
||||
// Same unique id will be used for the local copy as well.
|
||||
@@ -1028,10 +1029,15 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
};
|
||||
EnsureOutgoingMessageId(message);
|
||||
|
||||
var primaryAlias = await _accountService.GetPrimaryAccountAliasAsync(account.Id) ?? throw new MissingAliasException();
|
||||
selectedAlias ??= await _accountService.GetPrimaryAccountAliasAsync(account.Id) ?? throw new MissingAliasException();
|
||||
|
||||
// Set FromName and FromAddress by alias.
|
||||
message.From.Add(new MailboxAddress(account.SenderName, primaryAlias.AliasAddress));
|
||||
message.From.Add(new MailboxAddress(selectedAlias.AliasSenderName ?? account.SenderName, selectedAlias.AliasAddress));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(selectedAlias.ReplyToAddress))
|
||||
{
|
||||
message.ReplyTo.Add(new MailboxAddress(selectedAlias.ReplyToAddress, selectedAlias.ReplyToAddress));
|
||||
}
|
||||
|
||||
var builder = new BodyBuilder();
|
||||
|
||||
@@ -1052,6 +1058,61 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
return message;
|
||||
}
|
||||
|
||||
private async Task<MailAccountAlias> ResolveDraftAliasAsync(MailAccount account, DraftCreationOptions draftCreationOptions)
|
||||
{
|
||||
var aliases = await _accountService.GetAccountAliasesAsync(account.Id).ConfigureAwait(false);
|
||||
var primaryAlias = aliases.FirstOrDefault(a => a.IsPrimary) ?? aliases.FirstOrDefault();
|
||||
|
||||
if (draftCreationOptions?.ReferencedMessage?.MimeMessage == null)
|
||||
return primaryAlias;
|
||||
|
||||
var referencedMessage = draftCreationOptions.ReferencedMessage.MimeMessage;
|
||||
|
||||
MailAccountAlias FindAlias(string address)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(address))
|
||||
return null;
|
||||
|
||||
return aliases.FirstOrDefault(a => a.AliasAddress.Equals(address.Trim(), StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
var deliveredToAlias = FindAlias(ExtractAddressFromHeader(referencedMessage.Headers["Delivered-To"]))
|
||||
?? FindAlias(ExtractAddressFromHeader(referencedMessage.Headers["X-Original-To"]));
|
||||
if (deliveredToAlias != null)
|
||||
return deliveredToAlias;
|
||||
|
||||
foreach (var mailbox in referencedMessage.To.Mailboxes)
|
||||
{
|
||||
var matchedAlias = FindAlias(mailbox.Address);
|
||||
if (matchedAlias != null)
|
||||
return matchedAlias;
|
||||
}
|
||||
|
||||
foreach (var mailbox in referencedMessage.Cc.Mailboxes)
|
||||
{
|
||||
var matchedAlias = FindAlias(mailbox.Address);
|
||||
if (matchedAlias != null)
|
||||
return matchedAlias;
|
||||
}
|
||||
|
||||
return primaryAlias;
|
||||
}
|
||||
|
||||
private static string ExtractAddressFromHeader(string headerValue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(headerValue))
|
||||
return string.Empty;
|
||||
|
||||
var trimmed = headerValue.Trim();
|
||||
var leftBracketIndex = trimmed.LastIndexOf('<');
|
||||
var rightBracketIndex = trimmed.LastIndexOf('>');
|
||||
|
||||
if (leftBracketIndex >= 0 && rightBracketIndex > leftBracketIndex)
|
||||
return trimmed[(leftBracketIndex + 1)..rightBracketIndex].Trim();
|
||||
|
||||
return trimmed.Trim().Trim('<', '>', '"', '\'');
|
||||
}
|
||||
|
||||
private string CreateHtmlGap()
|
||||
{
|
||||
var template = $"""<div style="font-family: '{_preferencesService.ComposerFont}', Arial, sans-serif; font-size: {_preferencesService.ComposerFontSize}px"><br></div>""";
|
||||
|
||||
Reference in New Issue
Block a user