mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
feat: email retry page on 550 rejection; confirmation_email optional in admin form
This commit is contained in:
@@ -447,9 +447,6 @@ function handleShareLinkSubmission(string $slug): void
|
||||
'share_slug' => $slug,
|
||||
]);
|
||||
|
||||
// Send confirmation e-mail (non-blocking; failure doesn't stop redirect)
|
||||
$emailSent = StudentEmail::sendConfirmation(Database::getInstance(), $thesisId, $_POST);
|
||||
|
||||
// Mark the link as used
|
||||
$shareLinkModel = new ShareLink(Database::getInstance());
|
||||
$shareLinkModel->incrementUsage($link['id']);
|
||||
@@ -457,7 +454,22 @@ function handleShareLinkSubmission(string $slug): void
|
||||
// Clean up share-specific session data
|
||||
unset($_SESSION[$shareCsrfKey]);
|
||||
unset($_SESSION['share_verified_' . $slug]);
|
||||
$_SESSION['share_email_sent'] = $emailSent;
|
||||
|
||||
// Send confirmation e-mail — on delivery failure, redirect to retry page
|
||||
$emailError = null;
|
||||
try {
|
||||
$emailSent = StudentEmail::sendConfirmation(Database::getInstance(), $thesisId, $_POST);
|
||||
$_SESSION['share_email_sent'] = $emailSent;
|
||||
} catch (SmtpSendException $e) {
|
||||
if ($e->isRecipientRejected()) {
|
||||
$_SESSION['share_email_retry_thesis'] = $thesisId;
|
||||
$_SESSION['share_email_retry_error'] = $e->smtpResponse;
|
||||
header('Location: /partage/retry-email?id=' . urlencode((string)$thesisId));
|
||||
exit();
|
||||
}
|
||||
// Non-recipient errors (relay down, etc.) — skip email silently
|
||||
$_SESSION['share_email_sent'] = false;
|
||||
}
|
||||
|
||||
// Redirect to thanks page
|
||||
header('Location: /partage/recapitulatif?id=' . urlencode((string)$thesisId));
|
||||
|
||||
122
app/public/partage/retry-email.php
Normal file
122
app/public/partage/retry-email.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* E-mail retry page for share-link submissions.
|
||||
*
|
||||
* Shown when the confirmation e-mail bounced with a 550 recipient-rejected
|
||||
* error. The student can correct their address and resend, or skip.
|
||||
*/
|
||||
// Always boot — this page is a direct-response route (loaded before
|
||||
// Dispatcher calls App::boot()), so we must start the session ourselves.
|
||||
App::boot();
|
||||
|
||||
require_once APP_ROOT . '/src/Database.php';
|
||||
require_once APP_ROOT . '/src/SmtpRelay.php';
|
||||
require_once APP_ROOT . '/src/StudentEmail.php';
|
||||
|
||||
$thesisId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
// Guard: only allow access when the session retry token matches
|
||||
$sessionThesisId = $_SESSION['share_email_retry_thesis'] ?? null;
|
||||
if ($thesisId <= 0 || $sessionThesisId !== $thesisId) {
|
||||
header('Location: /');
|
||||
exit;
|
||||
}
|
||||
|
||||
$smtpError = $_SESSION['share_email_retry_error'] ?? '';
|
||||
|
||||
// ── POST: retry send ──────────────────────────────────────────────────────────
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Skip button
|
||||
if (isset($_POST['skip'])) {
|
||||
unset($_SESSION['share_email_retry_thesis'], $_SESSION['share_email_retry_error']);
|
||||
$_SESSION['share_email_sent'] = false;
|
||||
header('Location: /partage/recapitulatif?id=' . urlencode((string)$thesisId));
|
||||
exit;
|
||||
}
|
||||
|
||||
$newEmail = trim($_POST['confirmation_email'] ?? '');
|
||||
$inputError = null;
|
||||
|
||||
if ($newEmail === '' || filter_var($newEmail, FILTER_VALIDATE_EMAIL) === false) {
|
||||
$inputError = 'Veuillez saisir une adresse e-mail valide.';
|
||||
} else {
|
||||
$db = Database::getInstance();
|
||||
try {
|
||||
$sent = StudentEmail::sendConfirmation($db, $thesisId, ['confirmation_email' => $newEmail]);
|
||||
unset($_SESSION['share_email_retry_thesis'], $_SESSION['share_email_retry_error']);
|
||||
$_SESSION['share_email_sent'] = $sent;
|
||||
header('Location: /partage/recapitulatif?id=' . urlencode((string)$thesisId));
|
||||
exit;
|
||||
} catch (SmtpSendException $e) {
|
||||
// Update the displayed error with the fresh response
|
||||
$smtpError = $e->smtpResponse;
|
||||
$inputError = 'Le serveur a de nouveau rejeté cette adresse. Vérifiez l\'adresse et réessayez.';
|
||||
$_SESSION['share_email_retry_error'] = $smtpError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pageTitle = 'Corriger l\'adresse e-mail';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= htmlspecialchars($pageTitle) ?></title>
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/assets/favicon/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="167x167" href="/assets/favicon/apple-touch-icon-167x167.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon/favicon-16x16.png">
|
||||
<link rel="shortcut icon" href="/assets/favicon/favicon.ico">
|
||||
<link rel="stylesheet" href="<?= App::assetV('/assets/css/common.css') ?>">
|
||||
<link rel="stylesheet" href="<?= App::assetV('/assets/css/form.css') ?>">
|
||||
</head>
|
||||
<body class="student-body">
|
||||
<main id="main-content" class="partage-retry-email">
|
||||
|
||||
<div class="thanks-success">
|
||||
<h1>✅ Votre TFE a bien été enregistré !</h1>
|
||||
<p class="thanks-message">Il y a cependant eu un problème lors de l'envoi de l'e-mail de confirmation.</p>
|
||||
</div>
|
||||
|
||||
<section class="retry-email-section">
|
||||
<h2>Corriger l'adresse e-mail</h2>
|
||||
|
||||
<div class="flash-error" role="alert">
|
||||
<strong>L'adresse e-mail a été rejetée par le serveur.</strong><br>
|
||||
<?php if ($smtpError !== ''): ?>
|
||||
<code class="retry-smtp-detail"><?= htmlspecialchars($smtpError) ?></code>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($inputError)): ?>
|
||||
<div class="flash-error" role="alert"><?= htmlspecialchars($inputError) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<p>Votre TFE est enregistré — vous pouvez corriger votre adresse ci-dessous pour recevoir le récapitulatif, ou continuer sans e-mail.</p>
|
||||
|
||||
<form method="post" action="/partage/retry-email?id=<?= urlencode((string)$thesisId) ?>" class="retry-email-form">
|
||||
<div class="field-wrap">
|
||||
<label for="confirmation_email">Adresse e-mail corrigée</label>
|
||||
<input
|
||||
type="email"
|
||||
id="confirmation_email"
|
||||
name="confirmation_email"
|
||||
placeholder="ton.email@exemple.be"
|
||||
autofocus
|
||||
required
|
||||
class="<?= !empty($inputError) ? 'input-error' : '' ?>"
|
||||
>
|
||||
</div>
|
||||
<div class="retry-email-actions">
|
||||
<button type="submit" class="btn-primary">Renvoyer l'e-mail</button>
|
||||
<button type="submit" name="skip" value="1" class="btn-secondary">Continuer sans e-mail</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user