diff --git a/backend/src/routes/emailAsUser.ts b/backend/src/routes/emailAsUser.ts
index ff68692..017c193 100644
--- a/backend/src/routes/emailAsUser.ts
+++ b/backend/src/routes/emailAsUser.ts
@@ -23,27 +23,62 @@ export default async function emailAsUserRoutes(server: FastifyInstance) {
const encryptedValue = (value: unknown) => value ? decrypt(value as any) : null
- const accountResponse = (row: any) => ({
- id: row.id,
- createdAt: row.createdAt,
- updatedAt: row.updatedAt,
- userId: row.userId,
- tenantId: row.tenantId,
- type: row.type,
- email: encryptedValue(row.emailEncrypted),
- smtpHost: encryptedValue(row.smtpHostEncrypted),
- smtpPort: row.smtpPort ? Number(row.smtpPort) : null,
- smtpSsl: row.smtpSsl,
- imapHost: encryptedValue(row.imapHostEncrypted),
- imapPort: row.imapPort ? Number(row.imapPort) : null,
- imapSsl: row.imapSsl,
- hasPassword: Boolean(row.passwordEncrypted),
- })
+ const accountResponse = (row: any) => {
+ const invalidEncryptedFields: string[] = []
+ const safeEncryptedValue = (value: unknown, field: string) => {
+ if (!value) return null
+ try {
+ return encryptedValue(value)
+ } catch {
+ invalidEncryptedFields.push(field)
+ return null
+ }
+ }
- const accountCredentials = (row: any) => ({
- ...accountResponse(row),
- password: encryptedValue(row.passwordEncrypted),
- })
+ const email = safeEncryptedValue(row.emailEncrypted, "email")
+ const smtpHost = safeEncryptedValue(row.smtpHostEncrypted, "smtpHost")
+ const imapHost = safeEncryptedValue(row.imapHostEncrypted, "imapHost")
+ safeEncryptedValue(row.passwordEncrypted, "password")
+
+ if (invalidEncryptedFields.length) {
+ server.log.warn({
+ accountId: row.id,
+ invalidEncryptedFields,
+ }, "E-Mail-Kontodaten können mit dem aktuellen ENCRYPTION_KEY nicht entschlüsselt werden")
+ }
+
+ return {
+ id: row.id,
+ createdAt: row.createdAt,
+ updatedAt: row.updatedAt,
+ userId: row.userId,
+ tenantId: row.tenantId,
+ type: row.type,
+ email,
+ displayName: email || `Mailkonto ${String(row.id).slice(0, 8)} muss repariert werden`,
+ smtpHost,
+ smtpPort: row.smtpPort ? Number(row.smtpPort) : null,
+ smtpSsl: row.smtpSsl,
+ imapHost,
+ imapPort: row.imapPort ? Number(row.imapPort) : null,
+ imapSsl: row.imapSsl,
+ hasPassword: Boolean(row.passwordEncrypted),
+ credentialsReadable: invalidEncryptedFields.length === 0,
+ invalidEncryptedFields,
+ }
+ }
+
+ const accountCredentials = (row: any) => {
+ const account = accountResponse(row)
+ if (!account.credentialsReadable) {
+ throw new Error("Die verschlüsselten Kontodaten sind nicht lesbar. Bitte das E-Mail-Konto in den Einstellungen vollständig neu speichern.")
+ }
+
+ return {
+ ...account,
+ password: encryptedValue(row.passwordEncrypted),
+ }
+ }
const bodyValue = (body: any, camelKey: string, snakeKey: string) => body[camelKey] ?? body[snakeKey]
diff --git a/frontend/pages/email/index.vue b/frontend/pages/email/index.vue
index 568f2cd..cca6da7 100644
--- a/frontend/pages/email/index.vue
+++ b/frontend/pages/email/index.vue
@@ -5,6 +5,8 @@ import { de as deLocale } from "date-fns/locale"
type EmailAccount = {
id: string
email: string
+ displayName?: string
+ credentialsReadable?: boolean
imapHost?: string | null
hasPassword?: boolean
}
@@ -657,7 +659,7 @@ onMounted(loadAccounts)
v-else-if="accounts.length"
v-model="selectedAccountId"
:items="accounts"
- label-key="email"
+ label-key="displayName"
value-key="id"
class="w-full"
/>
diff --git a/frontend/pages/email/new.vue b/frontend/pages/email/new.vue
index 9651398..9e66b48 100644
--- a/frontend/pages/email/new.vue
+++ b/frontend/pages/email/new.vue
@@ -302,7 +302,7 @@ const sendEmail = async () => {
>
- {{ account.email }} + {{ account.displayName || account.email }}
+ Die verschlüsselten Zugangsdaten sind nicht lesbar. Öffne das Konto und trage alle Zugangsdaten neu ein. +