Anfragen-Team-Mails: vollständiger Inhalt (alle Felder)
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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]) => `<tr><td style="padding:3px 14px 3px 0;color:#666;vertical-align:top;white-space:nowrap;">${escH(k)}</td>`
|
||||
+ `<td style="padding:3px 0;"><strong>${escH(v).replace(/\n/g, '<br>')}</strong></td></tr>`)
|
||||
.join('');
|
||||
return `<table style="border-collapse:collapse;font-size:14px;line-height:1.5;">${rows}</table>`;
|
||||
}
|
||||
|
||||
// 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}`,
|
||||
`<p>Neue Angebotsanfrage von <strong>${name}</strong> (${email}${body.phone ? `, ${clean(String(body.phone))}` : ''})`
|
||||
+ `${produkt ? ` · ${produkt}` : ''} – im Board unter „Neu".</p>`);
|
||||
`<p>Neue Angebotsanfrage – im Board unter „Neu".</p>`
|
||||
+ 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)}`,
|
||||
`<p>Neue Musteranfrage von <strong>${clean(vollName)}</strong> (${email}${phone ? `, ${clean(phone)}` : ''})`
|
||||
+ ` · Produkt: ${clean(product)} – im Board unter „Neu".</p>`
|
||||
+ (musterNachricht ? `<p><strong>Nachricht:</strong><br>${musterNachricht.replace(/\n/g, '<br>')}</p>` : ''));
|
||||
`<p>Neue Musteranfrage – im Board unter „Neu".</p>`
|
||||
+ 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 =
|
||||
`<p><strong>${clean(name)}</strong> (${email}${phone ? `, ${phone}` : ''})</p>` +
|
||||
`<p>Interesse: <strong>${produkt ? clean(produkt) : 'k. A.'}</strong></p>` +
|
||||
`<p>${clean(strasse)}, ${clean(plz)} ${clean(ort)}, ${clean(land)}</p>`;
|
||||
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 =
|
||||
`<p><strong>${clean(name)}</strong>${unternehmen ? ` · ${unternehmen}` : ''} (${email}${phone ? `, ${phone}` : ''})</p>` +
|
||||
`<p style="white-space:pre-wrap">${nachricht || '—'}</p>`;
|
||||
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 += `<p style="margin:14px 0 4px;color:#888;font-size:12px;">Alle übermittelten Felder:</p>` + 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.`);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user