@using AliasVault.Shared.Models.Spamok @using AliasVault.Shared.Utilities @using AliasVault.Shared.Core; @using AliasVault.Client.Main.Components.Layout @using AliasVault.RazorComponents.Services @using Microsoft.Extensions.Localization @inject JsInteropService JsInteropService @inject GlobalNotificationService GlobalNotificationService @inject IHttpClientFactory HttpClientFactory @inject EmailService EmailService @inject HttpClient HttpClient @inject ConfirmModalService ConfirmModalService @inject IStringLocalizerFactory LocalizerFactory

@if (IsSpamOk) { @Email.Subject } else { @Email?.Subject }

@Localizer["FromLabel"] @(Email?.FromLocal)@@@(Email?.FromDomain)

@Localizer["ToLabel"] @(Email?.ToLocal)@@@(Email?.ToDomain)

@Localizer["DateLabel"] @Email?.DateSystem

@Localizer["ActionsLabel"]

@if (Email?.Attachments?.Any() == true) {

@Localizer["AttachmentsLabel"]

@foreach (var attachment in Email.Attachments) {
}
}
@code { private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Email.EmailModal", "AliasVault.Client"); private IStringLocalizer SharedLocalizer => LocalizerFactory.Create("SharedResources", "AliasVault.Client"); /// /// The email to show in the modal. /// [Parameter] public EmailApiModel? Email { get; set; } /// /// Boolean that indicates if the email is from SpamOK public API. /// [Parameter] public bool IsSpamOk { get; set; } /// /// Callback when the modal is closed. /// [Parameter] public EventCallback OnClose { get; set; } /// /// Callback when an email is deleted. /// [Parameter] public EventCallback OnEmailDeleted { get; set; } /// /// The message body to display /// private string EmailBody = string.Empty; /// /// Show confirmation modal before deleting email. /// private async Task ShowDeleteConfirmation() { if (Email == null) { return; } var result = await ConfirmModalService.ShowConfirmation( Localizer["DeleteEmailTitle"], Localizer["DeleteEmailConfirmation"], SharedLocalizer["Confirm"], SharedLocalizer["Cancel"] ); if (result) { await DeleteEmail(); } } /// /// Close the modal. /// [JSInvokable] public Task Close() { return OnClose.InvokeAsync(false); } /// /// Delete the current email. /// private async Task DeleteEmail() { if (Email == null) { return; } if (IsSpamOk) { await DeleteEmailSpamOk(); } else { await DeleteEmailAliasVault(); } } /// /// Delete the current email in SpamOk. /// private async Task DeleteEmailSpamOk() { if (Email == null) { return; } try { var client = HttpClientFactory.CreateClient("EmailClient"); var request = new HttpRequestMessage(HttpMethod.Delete, $"https://api.spamok.com/v2/Email/{Email.ToLocal}/{Email.Id}"); request.Headers.Add("X-Asdasd-Platform-Id", "av-web"); request.Headers.Add("X-Asdasd-Platform-Version", AppInfo.GetFullVersion()); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { await OnEmailDeleted.InvokeAsync(Email.Id); GlobalNotificationService.AddSuccessMessage(Localizer["EmailDeletedSuccess"], true); await Close(); } else { var errorMessage = await response.Content.ReadAsStringAsync(); GlobalNotificationService.AddErrorMessage($"{Localizer["EmailDeleteFailed"]}: {errorMessage}", true); } } catch (Exception ex) { GlobalNotificationService.AddErrorMessage($"{Localizer["GenericError"]}: {ex.Message}", true); } } /// /// Delete the current email in AliasVault. /// private async Task DeleteEmailAliasVault() { if (Email == null) { return; } try { var response = await HttpClient.DeleteAsync($"v1/Email/{Email.Id}"); if (response.IsSuccessStatusCode) { await OnEmailDeleted.InvokeAsync(Email.Id); GlobalNotificationService.AddSuccessMessage(Localizer["EmailDeletedSuccess"], true); } else { GlobalNotificationService.AddErrorMessage(Localizer["EmailDeleteFailed"], true); } } catch (Exception ex) { GlobalNotificationService.AddErrorMessage($"{Localizer["EmailDeleteFailed"]}: {ex.Message}", true); } } /// protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); // Determine email body if (Email != null) { // Check if there is HTML content, if not, then set default viewtype to plain if (Email.MessageHtml is not null && !string.IsNullOrWhiteSpace(Email.MessageHtml)) { // HTML is available EmailBody = ConversionUtility.ConvertAnchorTagsToOpenInNewTab(Email.MessageHtml); } else if (Email.MessagePlain is not null) { // No HTML but plain text is available // Escape HTML entities and wrap in pre tag to preserve formatting var escapedText = System.Net.WebUtility.HtmlEncode(Email.MessagePlain); EmailBody = $"
{escapedText}
"; } else { // No HTML and no plain text available EmailBody = Localizer["NoEmailBody"]; } } } /// /// Download an attachment. /// private async Task DownloadAttachment(AttachmentApiModel attachment) { try { if (IsSpamOk) { var client = HttpClientFactory.CreateClient("EmailClient"); var request = new HttpRequestMessage(HttpMethod.Get, $"https://api.spamok.com/v2/Attachment/{Email!.Id}/{attachment.Id}/download"); request.Headers.Add("X-Asdasd-Platform-Id", "av-web"); request.Headers.Add("X-Asdasd-Platform-Version", AppInfo.GetFullVersion()); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var bytes = await response.Content.ReadAsByteArrayAsync(); await JsInteropService.DownloadFileFromStream(attachment.Filename, bytes); } else { GlobalNotificationService.AddErrorMessage(Localizer["AttachmentDownloadFailed"], true); } } else { var response = await HttpClient.GetAsync($"v1/Email/{Email!.Id}/attachments/{attachment.Id}"); if (response.IsSuccessStatusCode) { // Get attachment bytes from API. var bytes = await response.Content.ReadAsByteArrayAsync(); // Decrypt the attachment locally with email's encryption key. var decryptedBytes = await EmailService.DecryptEmailAttachment(Email, bytes); // Offer the decrypted attachment as download to the user's browser. if (decryptedBytes != null) { await JsInteropService.DownloadFileFromStream(attachment.Filename, decryptedBytes); } } else { GlobalNotificationService.AddErrorMessage(Localizer["AttachmentDownloadFailed"], true); } } } catch (Exception ex) { GlobalNotificationService.AddErrorMessage($"{Localizer["AttachmentDownloadError"]}: {ex.Message}", true); } } }