Files
xamxam/app/src/StudentEmail.php
Pontoporeia 89b7ab476e Handle SMTP 550 recipient-rejected errors with structured SmtpSendException
- Add SmtpSendException with smtpCode/smtpResponse/isRecipientRejected()
- smtpSend() $expect closure throws SmtpSendException (with code) instead of RuntimeException
- SmtpRelay::send() re-throws SmtpSendException so callers can inspect it
- request-access.php (new): catch 550 → roll back token+approval, return HTTP 422 with FR user message
- request-access.php (resend): catch 550 → HTTP 422 instead of silently claiming success
- StudentEmail::sendConfirmation(): catch SmtpSendException → log+false (submission not aborted)
- admin/actions/access-request.php: catch SmtpSendException post-approval → flash warning (recipient-rejected vs transient)
2026-05-05 11:04:52 +02:00

119 lines
5.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* StudentEmail — builds and sends confirmation e-mails to students
* after a successful TFE submission via a share-link form.
*
* The e-mail is addressed to the confirmation e-mail field provided
* by the student and contains a recap of every field submitted.
*/
class StudentEmail {
/**
* Build the HTML body for the confirmation e-mail.
*
* @param array $thesis Thesis row (from getThesis / v_theses_full)
* @return string HTML body
*/
private static function buildHtml(array $thesis): string {
$rows = '';
$fields = [
'Identifiant' => $thesis['identifier'] ?? '',
'Titre' => $thesis['title'] ?? '',
'Sous-titre' => $thesis['subtitle'] ?? '',
'Auteur·ice(s)'=> $thesis['authors'] ?? '',
'Année' => $thesis['year'] ?? '',
'Orientation' => $thesis['orientation'] ?? '',
'Atelier pluridisciplinaire' => $thesis['ap_program'] ?? '',
'Finalité' => $thesis['finality_type'] ?? '',
'Synopsis' => $thesis['synopsis'] ?? '',
'Langue(s)' => $thesis['languages'] ?? '',
'Format(s)' => $thesis['formats'] ?? '',
'Mots-clés' => $thesis['keywords'] ?? '',
'Promoteur·ice(s)' => $thesis['jury_promoteurs'] ?? '',
'Président·e du jury' => $thesis['jury_president'] ?? '',
'Lecteurs·rices' => $thesis['jury_lecteurs'] ?? '',
'Durée / Taille' => $thesis['file_size_info'] ?? '',
'Lien' => $thesis['baiu_link'] ?? '',
'Type d\'accès' => $thesis['access_type'] ?? '',
'Licence' => $thesis['license_type'] ?? '',
];
foreach ($fields as $label => $value) {
$v = $value === '' ? '' : htmlspecialchars((string)$value);
$rows .= "<tr><th style='text-align:left;padding:6px 10px;border-bottom:1px solid #eee'>"
. htmlspecialchars($label) . "</th>"
. "<td style='padding:6px 10px;border-bottom:1px solid #eee'>{$v}</td></tr>\n";
}
return <<<HTML
<div style="font-family:system-ui,sans-serif;max-width:600px;margin:0 auto;color:#333">
<h1 style="font-size:1.4rem;color:#222">Merci — ton TFE a bien été enregistré 🎉</h1>
<p style="color:#555;font-size:0.95rem">
Voici un récapitulatif de ta soumission. Tu n'as pas besoin de répondre à cet e-mail.
</p>
<table style="width:100%;border-collapse:collapse;margin-top:1.5rem">
{$rows}
</table>
<p style="margin-top:2rem;font-size:0.85rem;color:#999">
Plateforme xamxam · erg Bruxelles
</p>
</div>
HTML;
}
/**
* Send a confirmation e-mail for a given thesis.
*
* @param Database $db
* @param int $thesisId
* @param array $postData Raw $_POST (must contain 'confirmation_email')
* @return bool True when sent, false otherwise
*/
public static function sendConfirmation(
Database $db,
int $thesisId,
array $postData
): bool {
// ── 1. Read e-mail from confirmation field ─────────────────────────
$to = trim($postData['confirmation_email'] ?? '');
if ($to === '' || filter_var($to, FILTER_VALIDATE_EMAIL) === false) {
error_log('[StudentEmail] No valid confirmation e-mail — skipping thesis #' . $thesisId);
return false;
}
// ── 2. Check SMTP config ────────────────────────────────────────────
if (!SmtpRelay::isConfigured($db)) {
error_log('[StudentEmail] SMTP not configured — skipping thesis #' . $thesisId);
return false;
}
// ── 3. Fetch thesis data ────────────────────────────────────────────
$thesis = $db->getThesis($thesisId);
if (!$thesis) {
error_log('[StudentEmail] Thesis #' . $thesisId . ' not found after creation');
return false;
}
// ── 4. Send ─────────────────────────────────────────────────────────
$subject = 'Merci — ton TFE a bien été enregistré';
$htmlBody = self::buildHtml($thesis);
try {
$result = SmtpRelay::send($db, $to, $subject, $htmlBody);
} catch (SmtpSendException $e) {
// Confirmation email failure must not abort the successful submission.
error_log("[StudentEmail] SMTP error sending to {$to} for thesis #{$thesisId}: " . $e->getMessage());
return false;
}
if ($result) {
error_log("[StudentEmail] Confirmation sent to {$to} for thesis #{$thesisId}");
} else {
error_log("[StudentEmail] Failed to send to {$to} for thesis #{$thesisId}");
}
return $result;
}
}