/* ================================================================== AegisSight Testzugang-Formular Liegt im Anfrage-Popup der Startseite, deutsch und englisch. Sprache wird aus gelesen, wie in lagebild.js und cookie-consent.js auch. ================================================================== */ (function () { 'use strict'; var LANG = (document.documentElement.lang || 'de').toLowerCase().indexOf('en') === 0 ? 'en' : 'de'; /* ---------- Texte ---------- */ var T = { de: { sending: 'Wird gesendet...', send: 'Testzugang anfragen', freemail: 'Bitte geben Sie Ihre dienstliche E-Mail-Adresse an. Adressen bei Freemail-Anbietern wie Gmail, GMX oder web.de können wir für einen Testzugang nicht berücksichtigen.', invalidMail: 'Diese E-Mail-Adresse sieht nicht vollständig aus. Bitte prüfen Sie Ihre Eingabe.', consent: 'Bitte bestätigen Sie die Datenschutzhinweise, damit wir Ihre Anfrage bearbeiten dürfen.', tooFast: 'Bitte nehmen Sie sich einen Moment für das Formular. Versuchen Sie es gleich noch einmal.', sendError: 'Die Anfrage konnte nicht gesendet werden.', netError: 'Verbindungsfehler. Bitte versuchen Sie es erneut.', hintOfficial: 'Dienstliche Adresse erkannt.', labels: { head: 'ANFRAGE TESTZUGANG AEGISSIGHT MONITOR', name: 'Name', org: 'Behörde oder Organisation', role: 'Funktion oder Dienststelle', mail: 'Dienstliche E-Mail', phone: 'Telefon', domain: 'Domain-Einstufung', domainOk: 'Behörden- oder Organisationsdomain erkannt', domainCheck: 'nicht eindeutig, bitte manuell prüfen', empty: 'keine Angabe' } }, en: { sending: 'Sending...', send: 'Request trial access', freemail: 'Please enter your official work email address. Addresses from free providers such as Gmail, GMX or web.de cannot be accepted for trial access.', invalidMail: 'This email address looks incomplete. Please check your entry.', consent: 'Please confirm the privacy notice so that we may process your request.', tooFast: 'Please take a moment to fill in the form, then try again.', sendError: 'The request could not be sent.', netError: 'Connection error. Please try again.', hintOfficial: 'Official address recognised.', labels: { head: 'TRIAL ACCESS REQUEST AEGISSIGHT MONITOR', name: 'Name', org: 'Authority or organisation', role: 'Role or department', mail: 'Work email', phone: 'Phone', domain: 'Domain assessment', domainOk: 'official domain recognised', domainCheck: 'not conclusive, please review manually', empty: 'not provided' } } }[LANG]; /* ---------- Freemail- und Wegwerf-Anbieter ---------- Diese Adressen werden abgewiesen. Alles andere kommt durch, damit Landkreise, Hochschulen und Rettungsdienste mit eigener Domain nicht ausgesperrt werden. */ var BLOCKED = [ 'gmail.com', 'googlemail.com', 'gmx.de', 'gmx.net', 'gmx.at', 'gmx.ch', 'gmx.com', 'web.de', 't-online.de', 'freenet.de', 'arcor.de', 'online.de', 'outlook.com', 'outlook.de', 'hotmail.com', 'hotmail.de', 'live.com', 'live.de', 'msn.com', 'yahoo.com', 'yahoo.de', 'yahoo.co.uk', 'ymail.com', 'aol.com', 'icloud.com', 'me.com', 'mac.com', 'proton.me', 'protonmail.com', 'pm.me', 'posteo.de', 'posteo.net', 'mailbox.org', 'mail.de', 'mail.com', 'email.de', 'firemail.de', 'unitybox.de', 'vodafone.de', 'vodafonemail.de', 'zoho.com', 'fastmail.com', 'hey.com', 'tutanota.com', 'tutanota.de', 'tuta.io', 'yandex.com', 'yandex.ru', 'mail.ru', 'qq.com', '163.com', '126.com', 'sina.com', 'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'temp-mail.org', 'tempmail.com', 'trashmail.com', 'trashmail.de', 'wegwerfmail.de', 'yopmail.com', 'sharklasers.com', 'getnada.com', 'dispostable.com', 'maildrop.cc', 'throwawaymail.com', 'moakt.com', 'emailondeck.com', 'spam4.me', 'byom.de', 'einrot.com', 'mytemp.email' ]; /* ---------- Muster typischer Behörden- und Organisationsdomains ---------- Nur zur Kennzeichnung in der Anfrage-Mail, keine Sperre. */ var OFFICIAL_SUFFIX = [ '.bund.de', '.bundeswehr.org', '.bundestag.de', '.bundesrat.de', '.bayern.de', '.nrw.de', '.berlin.de', '.hamburg.de', '.bremen.de', '.niedersachsen.de', '.hessen.de', '.rlp.de', '.saarland.de', '.sachsen.de', '.sachsen-anhalt.de', '.thueringen.de', '.brandenburg.de', '.schleswig-holstein.de', '.mv-regierung.de', '.bwl.de', '.baden-wuerttemberg.de', '.europa.eu', '.europarl.europa.eu', '.gv.at', '.bmi.gv.at', '.admin.ch', '.gov', '.gov.uk', '.mil', '.gouv.fr', '.overheid.nl', '.edu' ]; var OFFICIAL_PART = [ 'polizei.', 'bundeswehr.', 'bundespolizei.', 'zoll.', 'thw.', 'feuerwehr.', 'stadt-', 'stadt.', 'kreis-', 'landkreis-', 'kreis.', 'bezirk-', 'gemeinde-', 'uni-', 'universitaet', 'university', 'hochschule', 'fh-', 'hs-', 'landtag', 'ministerium', 'verfassungsschutz', 'bka.', 'bfv.', 'lka.' ]; function domainOf(mail) { var at = (mail || '').lastIndexOf('@'); return at === -1 ? '' : mail.slice(at + 1).trim().toLowerCase(); } function isBlocked(mail) { return BLOCKED.indexOf(domainOf(mail)) !== -1; } function looksOfficial(mail) { var d = domainOf(mail); if (!d) return false; var i; for (i = 0; i < OFFICIAL_SUFFIX.length; i++) { if (d === OFFICIAL_SUFFIX[i].slice(1) || d.slice(-OFFICIAL_SUFFIX[i].length) === OFFICIAL_SUFFIX[i]) return true; } for (i = 0; i < OFFICIAL_PART.length; i++) { if (d.indexOf(OFFICIAL_PART[i]) !== -1) return true; } return false; } function plausibleMail(mail) { return /^[^\s@]+@[^\s@.]+(\.[^\s@.]+)+$/.test(mail || ''); } /* ---------- Initialisierung ---------- */ document.addEventListener('DOMContentLoaded', function () { var form = document.getElementById('trial-form'); if (!form) return; var loadedAt = Date.now(); var mailField = document.getElementById('tf-email'); var mailNote = document.getElementById('tf-email-note'); /* Live-Rueckmeldung am E-Mail-Feld */ if (mailField && mailNote) { mailField.addEventListener('blur', function () { var v = mailField.value.trim(); mailNote.className = 'tf-note'; if (!v) { mailNote.textContent = ''; return; } if (isBlocked(v)) { mailNote.textContent = T.freemail; mailNote.className = 'tf-note tf-note-error'; mailField.setAttribute('aria-invalid', 'true'); } else if (looksOfficial(v)) { mailNote.textContent = T.hintOfficial; mailNote.className = 'tf-note tf-note-ok'; mailField.removeAttribute('aria-invalid'); } else { mailNote.textContent = ''; mailField.removeAttribute('aria-invalid'); } }); } form.addEventListener('submit', function (e) { e.preventDefault(); var val = function (id) { var el = document.getElementById(id); return el ? el.value.trim() : ''; }; var email = val('tf-email'); var honey = val('tf-website'); var consent = document.getElementById('tf-consent'); var errorBox = document.getElementById('tf-error'); var btn = form.querySelector('button[type="submit"]'); var fail = function (msg) { if (errorBox) { errorBox.textContent = msg; errorBox.style.display = 'block'; errorBox.scrollIntoView({ behavior: 'smooth', block: 'center' }); } if (btn) { btn.disabled = false; btn.textContent = T.send; } }; if (errorBox) errorBox.style.display = 'none'; /* Honeypot. Echte Nutzer sehen dieses Feld nicht. */ if (honey) return false; /* Zeitfalle gegen Bots */ if (Date.now() - loadedAt < 4000) return fail(T.tooFast); if (!plausibleMail(email)) return fail(T.invalidMail); if (isBlocked(email)) return fail(T.freemail); if (consent && !consent.checked) return fail(T.consent); if (btn) { btn.disabled = true; btn.textContent = T.sending; } var L = T.labels; var e_ = L.empty; var zeilen = [ L.head, '', L.org + ' = ' + (val('tf-org') || e_), L.role + ' = ' + (val('tf-role') || e_), L.mail + ' = ' + email, L.phone + ' = ' + (val('tf-phone') || e_), '', L.domain + ' = ' + (looksOfficial(email) ? L.domainOk : L.domainCheck) ]; var body = zeilen.join('\n'); fetch('/api/contact', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: val('tf-name'), organisation: val('tf-org'), email: email, message: body, lang: LANG }) }) .then(function (r) { return r.json().then(function (d) { return { ok: r.ok, data: d }; }); }) .then(function (res) { if (res.ok) { form.style.display = 'none'; var ok = document.getElementById('tf-success'); if (ok) { ok.style.display = 'block'; ok.scrollIntoView({ behavior: 'smooth', block: 'center' }); } if (window.umami) umami.track('trial_request_success'); } else { fail((res.data && res.data.error) || T.sendError); } }) .catch(function () { fail(T.netError); }); return false; }); }); })();