From 2c075f9fb55fa78bbe4d64770e59d9dd45464a4a Mon Sep 17 00:00:00 2001 From: s4luorth Date: Fri, 18 Sep 2026 12:02:45 +0200 Subject: [PATCH] =?UTF-8?q?Anfragen-Team-Mails:=20vollst=C3=A4ndiger=20Inh?= =?UTF-8?q?alt=20(alle=20Felder)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Muster- und Angebotsanfragen (App sample/offer-request + WordPress inbound) senden jetzt den kompletten Inhalt als Feld-Tabelle (Name, Kontakt, Adresse, Produkt, Menge, Nachricht/Vorhaben) – bei WordPress zusätzlich alle weiteren übermittelten Formularfelder. Co-Authored-By: Claude Opus 4.8 --- .../dist/index.js | 58 ++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/extensions/directus-extension-skrift-orders/dist/index.js b/extensions/directus-extension-skrift-orders/dist/index.js index b983e58..e463f3b 100644 --- a/extensions/directus-extension-skrift-orders/dist/index.js +++ b/extensions/directus-extension-skrift-orders/dist/index.js @@ -163,6 +163,17 @@ async function paypalToken() { // Auslandsländer als GANZE Wörter (\b) – sonst matchte „schweiz" in „Schweizer // Straße", „usa" in „Neusass", „polen" in „Polenz" usw. und flaggte fälschlich Ausland. const AUSLAND_RE = /\b(österreich|schweiz|austria|switzerland|frankreich|france|italien|italy|niederlande|netherlands|belgien|belgium|luxemburg|luxembourg|spanien|spain|portugal|usa|vereinigte staaten|united states|kanada|canada|england|großbritannien|grossbritannien|united kingdom|dänemark|denmark|schweden|sweden|norwegen|norway|finnland|finland|polen|poland|tschechien|czech|ungarn|hungary|griechenland|greece|irland|ireland|australien|australia|liechtenstein)\b/i; +// HTML-Escaping + Feld-Tabelle für vollständige Anfrage-Team-Mails. +const escH = (s) => String(s == null ? '' : s).replace(/[<>&]/g, (c) => ({ '<': '<', '>': '>', '&': '&' }[c])); +function felderHtml(pairs) { + const rows = pairs + .filter(([, v]) => v != null && String(v).trim()) + .map(([k, v]) => `${escH(k)}` + + `${escH(v).replace(/\n/g, '
')}
`) + .join(''); + return `${rows}
`; +} + // Erstes nicht-leeres Feld aus mehreren möglichen Namen (App + WordPress-Varianten). function feldWert(body, ...keys) { for (const k of keys) { @@ -1577,11 +1588,16 @@ const handler = (router, { services, getSchema, logger }) => { customer: customer?.id ?? null, }); - // Schlanke interne Benachrichtigung. - const produkt = product ? clean(product) : null; + // Vollständige interne Benachrichtigung. await teamMail(schema, `Neue Angebotsanfrage: ${name}`, - `

Neue Angebotsanfrage von ${name} (${email}${body.phone ? `, ${clean(String(body.phone))}` : ''})` - + `${produkt ? ` · ${produkt}` : ''} – im Board unter „Neu".

`); + `

Neue Angebotsanfrage – im Board unter „Neu".

` + + felderHtml([ + ['Vorname', clean(vorname)], ['Nachname', clean(nachname)], + ['E-Mail', email], ['Telefon', clean(phone)], + ['Produkt', product ? clean(product) : ''], + ['Menge', Number.isFinite(quantity) && quantity > 0 ? quantity : ''], + ['Vorhaben', clean(message)], + ])); return res.json({ ok: true }); } catch (err) { @@ -1646,11 +1662,15 @@ const handler = (router, { services, getSchema, logger }) => { customer: customer?.id ?? null, }); - const musterNachricht = clean(String(body.message || '').trim().slice(0, 1000)); + const musterNachricht = clean(String(body.message || '').trim().slice(0, 2000)); await teamMail(schema, `Neue Musteranfrage: ${clean(vollName)}`, - `

Neue Musteranfrage von ${clean(vollName)} (${email}${phone ? `, ${clean(phone)}` : ''})` - + ` · Produkt: ${clean(product)} – im Board unter „Neu".

` - + (musterNachricht ? `

Nachricht:
${musterNachricht.replace(/\n/g, '
')}

` : '')); + `

Neue Musteranfrage – im Board unter „Neu".

` + + felderHtml([ + ['Vorname', clean(first)], ['Nachname', clean(last)], + ['E-Mail', email], ['Telefon', clean(phone)], ['Produkt', clean(product)], + ['Straße', clean(street)], ['PLZ', clean(zip)], ['Ort', clean(city)], ['Land', clean(country)], + ['Nachricht', musterNachricht], + ])); return res.json({ ok: true }); } catch (err) { @@ -1750,10 +1770,11 @@ const handler = (router, { services, getSchema, logger }) => { status: 'neu', customer: customer?.id ?? null, }; subject = `Neue Musteranfrage: ${name}`; - mailHtml = - `

${clean(name)} (${email}${phone ? `, ${phone}` : ''})

` + - `

Interesse: ${produkt ? clean(produkt) : 'k. A.'}

` + - `

${clean(strasse)}, ${clean(plz)} ${clean(ort)}, ${clean(land)}

`; + mailHtml = felderHtml([ + ['Vorname', clean(vorname)], ['Nachname', clean(nachname)], + ['E-Mail', email], ['Telefon', phone], ['Produkt', produkt ? clean(produkt) : ''], + ['Straße', clean(strasse)], ['PLZ', clean(plz)], ['Ort', clean(ort)], ['Land', clean(land)], + ]); } else { const unternehmen = clean(String(body.unternehmen || '').trim()); const nachricht = clean(String(body.nachricht || body.message || '').trim()); @@ -1764,11 +1785,18 @@ const handler = (router, { services, getSchema, logger }) => { status: 'neu', customer: customer?.id ?? null, }; subject = `Neue Angebotsanfrage: ${name}`; - mailHtml = - `

${clean(name)}${unternehmen ? ` · ${unternehmen}` : ''} (${email}${phone ? `, ${phone}` : ''})

` + - `

${nachricht || '—'}

`; + mailHtml = felderHtml([ + ['Vorname', clean(vorname)], ['Nachname', clean(nachname)], ['Unternehmen', unternehmen], + ['E-Mail', email], ['Telefon', phone], ['Nachricht', nachricht], + ]); } + // „Gesamter Inhalt": alle übermittelten Felder (außer technische) mit anhängen, + // damit auch nicht standardisierte Formularfelder in der Mail landen. + const TECH = new Set(['token', 'dataprotection', '__form_id', '__refer', '__is_ajax', '__is_ajax_submit']); + const rest = Object.entries(body).filter(([k, v]) => !TECH.has(k.toLowerCase()) && String(v ?? '').trim()); + if (rest.length) mailHtml += `

Alle übermittelten Felder:

` + felderHtml(rest.map(([k, v]) => [k, clean(String(v))])); + await svc('offer_requests').createOne(record); logger.info(`[skrift-orders] inbound/${kind}: Anfrage von ${email} gespeichert.`);