feat: enrichir le rapport DNS avec colonnes attendu/dig/cloudflare + envoi a monitor@siteconseil.fr
src/Service/DnsCheckService.php: - Methode check() enrichie avec 4 nouveaux champs: expected (valeur attendue), dig (valeur actuelle trouvee par dig), cloudflare (valeur dans la zone CF), cf_status (statut de la colonne CF: ok/error/vide) - checkSpf(): expected = "include:X dans le SPF", dig = contenu SPF complet - checkDmarc(): expected = "p=reject ou p=quarantine", dig = contenu DMARC - checkDkim(): expected = "FQDN CNAME/TXT", dig = cible CNAME ou debut TXT - checkMx(): expected = MX attendu, dig = liste des MX trouves avec priorite - checkBounce(): expected = "feedback-smtp.*.amazonses.com", dig = valeur trouvee src/Command/CheckDnsCommand.php: - Nouveau champ MONITOR_EMAIL = 'monitor@siteconseil.fr' pour l'envoi du rapport - loadCloudflareRecords(): charge les records CF une seule fois par domaine au debut de l'execution, retourne un array indexe par domaine - enrichWithCloudflare(): apres chaque check DNS, parcourt les records CF pour trouver l'enregistrement correspondant et remplir les colonnes cloudflare et cf_status dans chaque check - checkAwsSes(): utilise DnsCheckService::check() avec expected/dig (ex: expected="Success", dig="Absent" pour la verification domaine) - checkMailcow(): utilise DnsCheckService::check() avec expected/dig (ex: expected="Cle Mailcow: abc...", dig="Cle DNS: xyz..." pour DKIM) - sendReport(): envoie a MONITOR_EMAIL au lieu de l'admin email templates/emails/dns_report.html.twig: - Tableau par domaine avec 6 colonnes: Type, Check, Attendu, Dig (actuel), Cloudflare, Statut (OK/erreur/warning) - Colonne Dig coloree en vert/rouge/jaune selon le statut du check - Colonne Cloudflare coloree selon cf_status - Colonnes avec word-break: break-all pour les longues valeurs DNS - Bandeau resume en haut avec compteurs succes/erreurs/warnings avec bordures laterales colorees - Pied de mail: "Rapport par Esy-Infra - Service de monitoring d'infra" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,73 +18,52 @@
|
||||
{{ date|date('d/m/Y H:i:s') }} • Domaines : <strong>{{ domains|join(', ') }}</strong>
|
||||
</p>
|
||||
|
||||
{# ─── Succes ─── #}
|
||||
{% if successes|length > 0 %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; color: #16a34a; margin-top: 16px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
Verifications reussies ({{ successes|length }})
|
||||
</h2>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #e5e5e5; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
{% for success in successes %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 12px; mso-line-height-rule: exactly; line-height: 18px; background-color: {{ loop.index is odd ? '#ffffff' : '#f9fafb' }}; border-bottom: 1px solid #eeeeee; color: #16a34a;">
|
||||
✓ {{ success }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{# ─── Resume ─── #}
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
<tr>
|
||||
<td style="padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; background-color: #f0fdf4; border-left: 3px solid #16a34a; font-size: 12px; font-weight: 700; color: #16a34a;">
|
||||
✓ {{ successes|length }} verification(s) OK
|
||||
</td>
|
||||
</tr>
|
||||
{% if errors|length > 0 %}
|
||||
<tr>
|
||||
<td style="padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; background-color: #fef2f2; border-left: 3px solid #dc2626; font-size: 12px; font-weight: 700; color: #dc2626;">
|
||||
✗ {{ errors|length }} erreur(s)
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if warnings|length > 0 %}
|
||||
<tr>
|
||||
<td style="padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; background-color: #fffbeb; border-left: 3px solid #f59e0b; font-size: 12px; font-weight: 700; color: #f59e0b;">
|
||||
⚠ {{ warnings|length }} avertissement(s)
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
||||
{# ─── Erreurs ─── #}
|
||||
{% if errors|length > 0 %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; color: #dc2626; margin-top: 16px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
Erreurs ({{ errors|length }})
|
||||
</h2>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #fca5a5; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
{% for error in errors %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 12px; mso-line-height-rule: exactly; line-height: 18px; background-color: #fef2f2; color: #991b1b; border-bottom: 1px solid #fca5a5;">
|
||||
✗ {{ error }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{# ─── Avertissements ─── #}
|
||||
{% if warnings|length > 0 %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; color: #f59e0b; margin-top: 16px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
Avertissements ({{ warnings|length }})
|
||||
</h2>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #fde68a; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
{% for warning in warnings %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 12px; mso-line-height-rule: exactly; line-height: 18px; background-color: #fffbeb; color: #92400e; border-bottom: 1px solid #fde68a;">
|
||||
⚠ {{ warning }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{# ─── Detail par domaine ─── #}
|
||||
{# ─── Detail par domaine avec valeurs attendue / dig / cloudflare ─── #}
|
||||
{% for domainData in domainResults %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; margin-top: 20px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
<h2 style="font-size: 16px; font-weight: 700; margin-top: 24px; margin-right: 0; margin-bottom: 8px; margin-left: 0; border-bottom: 2px solid #fabf04; padding-bottom: 4px;">
|
||||
{{ domainData.domain }}
|
||||
</h2>
|
||||
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #e5e5e5; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
<tr>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; width: 80px;">Type</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">Verification</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 12px; padding-right: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; text-align: center; width: 60px;">Statut</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; width: 60px;">Type</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">Check</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">Attendu</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">Dig (actuel)</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">Cloudflare</td>
|
||||
<td style="background-color: #111827; color: #ffffff; padding-top: 8px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; text-align: center; width: 30px;">OK</td>
|
||||
</tr>
|
||||
{% for check in domainData.checks %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 11px; font-weight: 700; border-bottom: 1px solid #eeeeee; color: #666666;">{{ check.type }}</td>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 11px; border-bottom: 1px solid #eeeeee;">
|
||||
<strong>{{ check.label }}</strong>
|
||||
{% if check.detail %}<br><span style="color: #888888; font-size: 10px;">{{ check.detail }}</span>{% endif %}
|
||||
</td>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 12px; text-align: center; border-bottom: 1px solid #eeeeee; font-weight: 700; color: {{ check.status == 'ok' ? '#16a34a' : (check.status == 'error' ? '#dc2626' : '#f59e0b') }};">
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; border-bottom: 1px solid #eeeeee; color: #666666; vertical-align: top;">{{ check.type }}</td>
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 9px; font-weight: 700; border-bottom: 1px solid #eeeeee; vertical-align: top;">{{ check.label }}</td>
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 9px; border-bottom: 1px solid #eeeeee; color: #444444; vertical-align: top; word-break: break-all;">{{ check.expected|default('—') }}</td>
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 9px; border-bottom: 1px solid #eeeeee; color: {{ check.status == 'ok' ? '#16a34a' : (check.status == 'error' ? '#dc2626' : '#92400e') }}; vertical-align: top; word-break: break-all;">{{ check.dig|default('—') }}</td>
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 9px; border-bottom: 1px solid #eeeeee; color: {{ check.cf_status|default('') == 'ok' ? '#16a34a' : (check.cf_status|default('') == 'error' ? '#dc2626' : '#888888') }}; vertical-align: top; word-break: break-all;">{{ check.cloudflare|default('—') }}</td>
|
||||
<td style="padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 12px; text-align: center; border-bottom: 1px solid #eeeeee; font-weight: 700; color: {{ check.status == 'ok' ? '#16a34a' : (check.status == 'error' ? '#dc2626' : '#f59e0b') }}; vertical-align: top;">
|
||||
{{ check.status == 'ok' ? '✓' : (check.status == 'error' ? '✗' : '⚠') }}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -92,8 +71,39 @@
|
||||
</table>
|
||||
{% endfor %}
|
||||
|
||||
{# ─── Erreurs detaillees ─── #}
|
||||
{% if errors|length > 0 %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; color: #dc2626; margin-top: 16px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
Erreurs a corriger ({{ errors|length }})
|
||||
</h2>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #fca5a5; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
{% for error in errors %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 11px; mso-line-height-rule: exactly; line-height: 16px; background-color: #fef2f2; color: #991b1b; border-bottom: 1px solid #fca5a5;">
|
||||
✗ {{ error }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if warnings|length > 0 %}
|
||||
<h2 style="font-size: 14px; font-weight: 700; color: #f59e0b; margin-top: 16px; margin-right: 0; margin-bottom: 8px; margin-left: 0;">
|
||||
Avertissements ({{ warnings|length }})
|
||||
</h2>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border: 1px solid #fde68a; margin-top: 0; margin-right: 0; margin-bottom: 16px; margin-left: 0;">
|
||||
{% for warning in warnings %}
|
||||
<tr>
|
||||
<td style="padding-top: 6px; padding-bottom: 6px; padding-left: 12px; padding-right: 12px; font-size: 11px; mso-line-height-rule: exactly; line-height: 16px; background-color: #fffbeb; color: #92400e; border-bottom: 1px solid #fde68a;">
|
||||
⚠ {{ warning }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<p style="font-size: 11px; color: #888888; mso-line-height-rule: exactly; line-height: 16px; margin-top: 16px; margin-right: 0; margin-bottom: 0; margin-left: 0;">
|
||||
Rapport genere par la commande <strong>app:dns:check</strong>. Verifiez la configuration dans Cloudflare et AWS SES si necessaire.
|
||||
Rapport par <strong>Esy-Infra</strong> - Service de monitoring d'infra
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user