feat: add UTF-8 conversion for email body and enhance MailViewer processing
This commit is contained in:
17
app.go
17
app.go
@@ -10,8 +10,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
|
"golang.org/x/text/encoding/charmap"
|
||||||
|
"golang.org/x/text/transform"
|
||||||
|
|
||||||
"emly/backend/utils"
|
"emly/backend/utils"
|
||||||
internal "emly/backend/utils/mail"
|
internal "emly/backend/utils/mail"
|
||||||
@@ -517,3 +520,17 @@ func (a *App) IsDebuggerRunning() bool {
|
|||||||
}
|
}
|
||||||
return utils.IsDebugged()
|
return utils.IsDebugged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) ConvertToUTF8(s string) string {
|
||||||
|
if utf8.ValidString(s) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// If invalid UTF-8, assume Windows-1252 (superset of ISO-8859-1)
|
||||||
|
decoder := charmap.Windows1252.NewDecoder()
|
||||||
|
decoded, _, err := transform.String(decoder, s)
|
||||||
|
if err != nil {
|
||||||
|
return s // Return as-is if decoding fails
|
||||||
|
}
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[EMLy]
|
[EMLy]
|
||||||
SDK_DECODER_SEMVER="1.3.1"
|
SDK_DECODER_SEMVER="1.3.1"
|
||||||
SDK_DECODER_RELEASE_CHANNEL="beta"
|
SDK_DECODER_RELEASE_CHANNEL="beta"
|
||||||
GUI_SEMVER="1.3.0"
|
GUI_SEMVER="1.3.1"
|
||||||
GUI_RELEASE_CHANNEL="beta"
|
GUI_RELEASE_CHANNEL="beta"
|
||||||
LANGUAGE="it"
|
LANGUAGE="it"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { X, MailOpen, Image, FileText, File, ShieldCheck, Shield, Signature, FileCode, Loader2 } from "@lucide/svelte";
|
import { X, MailOpen, Image, FileText, File, ShieldCheck, Shield, Signature, FileCode, Loader2 } from "@lucide/svelte";
|
||||||
import { ShowOpenFileDialog, ReadEML, OpenPDF, OpenImageWindow, OpenPDFWindow, OpenImage, ReadMSG, ReadPEC, OpenEMLWindow } from "$lib/wailsjs/go/main/App";
|
import { ShowOpenFileDialog, ReadEML, OpenPDF, OpenImageWindow, OpenPDFWindow, OpenImage, ReadMSG, ReadPEC, OpenEMLWindow, ConvertToUTF8 } from "$lib/wailsjs/go/main/App";
|
||||||
import type { internal } from "$lib/wailsjs/go/models";
|
import type { internal } from "$lib/wailsjs/go/models";
|
||||||
import { sidebarOpen } from "$lib/stores/app";
|
import { sidebarOpen } from "$lib/stores/app";
|
||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
import { settingsStore } from "$lib/stores/settings.svelte";
|
import { settingsStore } from "$lib/stores/settings.svelte";
|
||||||
import * as m from "$lib/paraglide/messages";
|
import * as m from "$lib/paraglide/messages";
|
||||||
import { dev } from "$app/environment";
|
import { dev } from "$app/environment";
|
||||||
|
import { isBase64, isHtml } from "$lib/utils";
|
||||||
|
|
||||||
let unregisterEvents = () => {};
|
let unregisterEvents = () => {};
|
||||||
let isLoading = $state(false);
|
let isLoading = $state(false);
|
||||||
@@ -23,13 +24,49 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if(dev) {
|
const process = async () => {
|
||||||
console.log(mailState.currentEmail)
|
if (mailState.currentEmail?.body) {
|
||||||
}
|
let content = mailState.currentEmail.body;
|
||||||
console.info("Current email changed:", mailState.currentEmail?.subject);
|
// 1. Try to decode if not HTML
|
||||||
if(mailState.currentEmail !== null) {
|
if (!isHtml(content)) {
|
||||||
sidebarOpen.set(false);
|
const clean = content.replace(/[\s\r\n]+/g, '');
|
||||||
}
|
if (isBase64(clean)) {
|
||||||
|
try {
|
||||||
|
const decoded = window.atob(clean);
|
||||||
|
content = decoded;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to decode base64 body:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. If it is HTML (original or decoded), try to fix encoding
|
||||||
|
if (isHtml(content)) {
|
||||||
|
try {
|
||||||
|
const fixed = await ConvertToUTF8(content);
|
||||||
|
if (fixed) {
|
||||||
|
content = fixed;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to fix encoding:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Update if changed
|
||||||
|
if (content !== mailState.currentEmail.body) {
|
||||||
|
mailState.currentEmail.body = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dev) {
|
||||||
|
console.log(mailState.currentEmail)
|
||||||
|
}
|
||||||
|
console.info("Current email changed:", mailState.currentEmail?.subject);
|
||||||
|
if(mailState.currentEmail !== null) {
|
||||||
|
sidebarOpen.set(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process();
|
||||||
})
|
})
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
|||||||
@@ -10,4 +10,18 @@ export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
|
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
|
||||||
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
||||||
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|
||||||
|
|
||||||
|
export function isBase64(str: string): boolean {
|
||||||
|
if (!str) return false;
|
||||||
|
const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
||||||
|
return base64Regex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isHtml(str: string): boolean {
|
||||||
|
if (!str) return false;
|
||||||
|
const htmlRegex = /<[^>]+>/;
|
||||||
|
return htmlRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#define ApplicationName 'EMLy'
|
#define ApplicationName 'EMLy'
|
||||||
#define ApplicationVersion GetVersionNumbersString('EMLy.exe')
|
#define ApplicationVersion GetVersionNumbersString('EMLy.exe')
|
||||||
#define ApplicationVersion '1.2.4_beta'
|
#define ApplicationVersion '1.3.1_beta'
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
AppName={#ApplicationName}
|
AppName={#ApplicationName}
|
||||||
|
|||||||
Reference in New Issue
Block a user