The mail page under System tries SMTP, PHP mail() and both sendmail modes one by one or all at once, and saves the chosen way to .env without ever showing the password. IONOS answers everything under /.well-known/ itself with 403, so the address and HTTPS checks never reached the installation; the probe now lives at /kantsites-origin (ADR 122). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
133 lines
8.3 KiB
Twig
133 lines
8.3 KiB
Twig
{% extends 'admin/shell.html.twig' %}
|
||
{% set nav = 'mail' %}
|
||
{% block title %}E-Mail-Versand{% endblock %}
|
||
{% block heading %}E-Mail-Versand{% endblock %}
|
||
{% block lead %}Wie Formulare ihre Mails verschicken – ausprobieren, speichern und sehen, woran es hakt.{% endblock %}
|
||
{% block content %}
|
||
|
||
{# E-Mail-Versand (ADR 121, 122): Weg wählen und ausprobieren, alle Wege des Servers testen,
|
||
speichern - und die letzten Versuche mit Ursache. Das SMTP-Passwort steht nie im Formular. #}
|
||
{% set f = mailForm ?? {} %}
|
||
{% set e = mail.einstellung %}
|
||
{% set weg = f.weg ?? e.weg %}
|
||
<div class="card" id="mail">
|
||
<div class="card-head"><h2>Versandweg</h2><span class="muted">gilt für alle Formulare</span></div>
|
||
<div class="card-body">
|
||
<dl class="facts">
|
||
<dt>Eingestellt</dt>
|
||
<dd>
|
||
{% if mail.gueltig %}
|
||
<strong>{{ mail.art }}</strong>{% if mail.ziel %} <code>{{ mail.ziel }}</code>{% endif %}{% if mail.benutzer %} <span class="muted">· angemeldet als</span> <code>{{ mail.benutzer }}</code>{% endif %}
|
||
{% else %}
|
||
<span class="check-bad"><strong>Die Einstellung ist ungültig.</strong></span>
|
||
{% endif %}
|
||
<br><span class="muted">Gespeichert in <code>{{ mail.quelle }}</code> als <code>MAILER_DSN</code>.{% if mail.quelle != '.env' %} Sie hat dort Vorrang; speichern lässt sich hier nichts, testen schon.{% endif %}</span>
|
||
</dd>
|
||
</dl>
|
||
|
||
{% if mailNotice %}
|
||
<p class="notice {{ mailNotice.art == 'ok' ? 'ok' : 'error' }} mail-result" role="{{ mailNotice.art == 'ok' ? 'status' : 'alert' }}">{{ mailNotice.text }}</p>
|
||
{% endif %}
|
||
|
||
{% if mailResult %}
|
||
<div class="notice {{ mailResult.ok ? 'ok' : 'error' }} mail-result" role="{{ mailResult.ok ? 'status' : 'alert' }}">
|
||
<p><strong>{{ mailResult.ok ? 'Testmail an ' ~ mailResult.an ~ ' vom Mailserver angenommen' : 'Testmail an ' ~ mailResult.an ~ ' nicht versendet' }}</strong>{% if mailResult.weg is defined %} <span>({{ mailResult.weg }})</span>{% endif %}.{% if not mailResult.ok %} {{ mailResult.meldung }}{% endif %}</p>
|
||
{% if mailResult.hinweis %}<p>{{ mailResult.hinweis }}</p>{% endif %}
|
||
{% if mailResult.dialog %}<details><summary>Antworten des Mailservers</summary><pre>{{ mailResult.dialog }}</pre></details>{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if mailResults %}
|
||
<div class="mail-result">
|
||
<p><strong>Alle Wege ausprobiert</strong> <span class="muted">– an {{ (f.an ?? '') }}. Was angenommen wurde, kann gespeichert werden; angekommen ist es damit noch nicht, bitte im Postfach nachsehen.</span></p>
|
||
<ul class="log-list">
|
||
{% for r in mailResults %}
|
||
<li class="{{ r.ok ? 'check-ok' : 'check-bad' }}">
|
||
<strong>{{ r.ok ? 'Angenommen' : 'Fehlgeschlagen' }}</strong> · {{ r.weg }}
|
||
{% if not r.ok %}<br><code>{{ r.meldung }}</code>{% if r.hinweis %}<br><span class="muted">{{ r.hinweis }}</span>{% endif %}{% endif %}
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<form class="mail-form" action="{{ path('admin_mail_save') }}" method="post">
|
||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('system') }}">
|
||
<fieldset>
|
||
<legend>Versandweg</legend>
|
||
<label class="check-label" for="weg-smtp"><input id="weg-smtp" type="radio" name="weg" value="smtp"{% if weg == 'smtp' %} checked{% endif %}> <span>SMTP mit Postfach <span class="muted">– empfohlen, unabhängig vom Hoster</span></span></label>
|
||
{% for key, w in mail.wege %}
|
||
<label class="check-label" for="weg-{{ key }}"><input id="weg-{{ key }}" type="radio" name="weg" value="{{ key }}"{% if weg == key %} checked{% endif %}> {{ w.label }}</label>
|
||
{% endfor %}
|
||
</fieldset>
|
||
|
||
<fieldset class="smtp-fields">
|
||
<legend>SMTP</legend>
|
||
<div class="mail-grid">
|
||
<div>
|
||
<label for="mail-server">Server</label>
|
||
<input id="mail-server" name="server" type="text" inputmode="url" autocomplete="off" spellcheck="false" maxlength="200" placeholder="smtp.ionos.de" value="{{ f.server ?? e.server }}">
|
||
</div>
|
||
<div>
|
||
<label for="mail-port">Port</label>
|
||
<input id="mail-port" name="port" type="number" min="1" max="65535" value="{{ f.port ?? e.port }}" aria-describedby="mail-port-help">
|
||
</div>
|
||
<div>
|
||
<label for="mail-user">Benutzer</label>
|
||
<input id="mail-user" name="benutzer" type="text" autocomplete="off" spellcheck="false" maxlength="200" placeholder="formular@meine-firma.de" value="{{ f.benutzer ?? e.benutzer }}">
|
||
</div>
|
||
<div>
|
||
<label for="mail-pass">Passwort</label>
|
||
<input id="mail-pass" name="passwort" type="password" autocomplete="new-password" maxlength="500" placeholder="{{ e.passwort ? 'gespeichert – leer lassen zum Behalten' : '' }}">
|
||
</div>
|
||
</div>
|
||
<p class="field-help" id="mail-port-help">587 mit STARTTLS ist üblich (IONOS, Microsoft 365: <code>smtp.office365.com</code>), 465 verschlüsselt von Anfang an. Das Passwort wird nie angezeigt und landet nur in <code>.env</code>.</p>
|
||
</fieldset>
|
||
|
||
<fieldset>
|
||
<legend>Testmail</legend>
|
||
<div class="mail-grid">
|
||
<div>
|
||
<label for="mail-to">An</label>
|
||
<input id="mail-to" name="to" type="email" autocomplete="email" maxlength="200" placeholder="name@beispiel.de" value="{{ f.an ?? (mailResult.an ?? '') }}">
|
||
</div>
|
||
<div>
|
||
<label for="mail-from">Absender</label>
|
||
<input id="mail-from" name="from" type="email" maxlength="200" placeholder="leer: dieselbe Adresse" value="{{ f.von ?? mail.absender }}" aria-describedby="mail-from-help">
|
||
</div>
|
||
</div>
|
||
<p class="field-help" id="mail-from-help">Derselbe Absender wie bei den Formularen. Über den Server (mail(), sendmail) muss er zu einer eigenen Domain beim Hoster gehören, bei SMTP ist es meist das angemeldete Postfach.</p>
|
||
</fieldset>
|
||
|
||
<div class="mail-actions">
|
||
<button class="secondary" type="submit" name="aktion" value="test">Diesen Weg testen</button>
|
||
<button class="secondary" type="submit" name="aktion" value="alle">Alle Wege testen</button>
|
||
{% if mail.quelle == '.env' %}<button type="submit" name="aktion" value="speichern">Diesen Weg speichern</button>{% endif %}
|
||
</div>
|
||
<p class="field-help">„Alle Wege testen“ schickt je Weg eine Testmail – bis zu vier. Gespeichert wird {{ mail.quelle == '.env' ? 'nur mit „Diesen Weg speichern“' : 'hier nichts, weil MAILER_DSN in der Server-Umgebung steht' }}.</p>
|
||
</form>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div class="card-head"><h2>Letzte Versuche</h2><span class="muted">var/log/mail.log</span></div>
|
||
<div class="card-body">
|
||
{% if mail.protokoll is empty %}
|
||
<p class="muted">Noch nichts versendet – weder Testmail noch Formular.</p>
|
||
{% else %}
|
||
<ul class="log-list">
|
||
{% for eintrag in mail.protokoll %}
|
||
<li class="{{ eintrag.ok ? 'check-ok' : 'check-bad' }}">
|
||
<strong>{{ eintrag.ok ? 'Angenommen' : 'Fehlgeschlagen' }}</strong> · {{ eintrag.zeit }} UTC · {{ eintrag.anlass }} an <code>{{ eintrag.an }}</code>{% if eintrag.von %} von <code>{{ eintrag.von }}</code>{% endif %}{% if eintrag.weg is defined and eintrag.weg %} · {{ eintrag.weg }}{% endif %}
|
||
{% if not eintrag.ok %}<br><code>{{ eintrag.meldung }}</code>{% if eintrag.hinweis %}<br><span class="muted">{{ eintrag.hinweis }}</span>{% endif %}{% endif %}
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<p class="footnote">KantSites · Arbeitsstand</p>
|
||
{% endblock %}
|