downloadRemailers(); // Reload after download $entryRemailers = getRemailers('entry'); $middleRemailers = getRemailers('middle'); $exitRemailers = getRemailers('exit'); } catch (Exception $e) { error_log("Failed to download remailers: " . $e->getMessage()); } } $message = ''; $messageType = ''; // Check for flash messages from previous redirect (PRG pattern) if (isset($_SESSION['flash_message'])) { $message = $_SESSION['flash_message']; $messageType = isset($_SESSION['flash_type']) ? $_SESSION['flash_type'] : 'info'; // Clear flash messages after displaying unset($_SESSION['flash_message']); unset($_SESSION['flash_type']); } // Handle form submission if ($_SERVER['REQUEST_METHOD'] === 'POST') { // CSRF validation - IMPROVED with better error handling if (!isset($_POST['csrf_token'])) { // Save error in session and redirect $_SESSION['flash_message'] = "Security token missing. Please reload the page and try again."; $_SESSION['flash_type'] = 'error'; header('Location: ' . $_SERVER['PHP_SELF']); exit; } elseif ($_POST['csrf_token'] !== $currentCsrfToken) { // Save error in session and redirect $_SESSION['flash_message'] = "Security token mismatch. Please try submitting again."; $_SESSION['flash_type'] = 'error'; header('Location: ' . $_SERVER['PHP_SELF']); exit; } else { try { if (isset($_POST['update_remailers'])) { if (!class_exists('SecureRemailerDownloader')) { throw new Exception('Remailer list updater is not available.'); } set_time_limit(0); $downloader = new SecureRemailerDownloader(); if (!$downloader->forceUpdate()) { throw new Exception('Remailer list update failed. The previous list was kept where possible.'); } $_SESSION['flash_message'] = 'Remailer list and public keyring updated successfully.'; $_SESSION['flash_type'] = 'success'; $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); header('Location: ' . $_SERVER['PHP_SELF']); exit; } // Get and sanitize form data with additional validation $entryRemailer = isset($_POST['entry_remailer']) ? filter_var($_POST['entry_remailer'], FILTER_SANITIZE_STRING) : ''; $middleRemailer = isset($_POST['middle_remailer']) ? filter_var($_POST['middle_remailer'], FILTER_SANITIZE_STRING) : ''; $exitRemailer = isset($_POST['exit_remailer']) ? filter_var($_POST['exit_remailer'], FILTER_SANITIZE_STRING) : ''; $from = isset($_POST['from']) ? filter_var($_POST['from'], FILTER_SANITIZE_STRING) : ''; $replyTo = isset($_POST['reply_to']) ? filter_var($_POST['reply_to'], FILTER_SANITIZE_STRING) : ''; $to = isset($_POST['to']) ? filter_var($_POST['to'], FILTER_SANITIZE_EMAIL) : ''; $subject = isset($_POST['subject']) ? filter_var($_POST['subject'], FILTER_SANITIZE_STRING) : ''; $newsgroups = isset($_POST['newsgroups']) ? filter_var($_POST['newsgroups'], FILTER_SANITIZE_STRING) : ''; $references = isset($_POST['references']) ? filter_var($_POST['references'], FILTER_SANITIZE_STRING) : ''; $data = isset($_POST['data']) ? $_POST['data'] : ''; // Keep original formatting $copies = isset($_POST['copies']) ? intval($_POST['copies']) : 1; // Validate copies if ($copies < 1 || $copies > 3) { throw new Exception("Number of copies must be between 1 and 3."); } if (empty($from)) { throw new Exception("Sender (From) is required."); } $messageKind = trim($newsgroups) === '' ? 'email' : 'usenet'; if ($messageKind === 'email' && empty($to)) { throw new Exception("Email recipient is required when Newsgroup is empty."); } if ($messageKind === 'usenet') { $to = yamnConfig('YAMN_USENET_GATEWAY', 'mail2news@mail2news.tcpreset.net'); if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { throw new Exception("Usenet gateway is not configured correctly."); } } // Validate remailer chain if (empty($entryRemailer) || empty($middleRemailer) || empty($exitRemailer)) { throw new Exception("All three remailers must be specified."); } // Resolve asterisks (*) to actual random remailers $resolvedEntry = resolveRemailer($entryRemailer, $entryRemailers); $resolvedMiddle = resolveRemailer($middleRemailer, $middleRemailers); $resolvedExit = resolveRemailer($exitRemailer, $exitRemailers); $encoded = encodeYamnMessage([ 'kind' => $messageKind, 'entry' => $resolvedEntry, 'chain' => [$resolvedEntry, $resolvedMiddle, $resolvedExit], 'from' => $from, 'reply_to' => $replyTo, 'to' => $to, 'subject' => $subject, 'newsgroup' => $newsgroups, 'body' => $data, 'references' => $references, ]); if (!$encoded['success']) { throw new Exception($encoded['error'] ?? 'YAMN encoding failed'); } $responseFinished = false; $onHandoff = null; if (function_exists('fastcgi_finish_request')) { $onHandoff = static function () use (&$responseFinished): void { ignore_user_abort(true); $_SESSION['flash_message'] = 'Message handed to the local Nym transport. The sender is completing delivery in the background; YAMN queues may take several hours, and this confirmation does not mean the message has been published or delivered yet.'; $_SESSION['flash_type'] = 'success'; $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); session_write_close(); header('Location: ' . $_SERVER['PHP_SELF']); fastcgi_finish_request(); $responseFinished = true; }; } $result = sendNymEnvelope($encoded['envelope'], 1, $encoded['entry_address'], $onHandoff); if ($responseFinished) { exit; } if (!$result['success']) { throw new Exception($result['error'] ?? 'Nym submission failed'); } $_SESSION['flash_message'] = 'Message accepted by the Nym transport. Delivery through the YAMN queues may take several hours; this confirmation does not mean the message has been published or delivered yet.'; $_SESSION['flash_type'] = 'success'; $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); header('Location: ' . $_SERVER['PHP_SELF']); exit; } catch (Exception $e) { // Save error in session and redirect (PRG pattern for errors too) $_SESSION['flash_message'] = "✗ Error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN submission error: " . $e->getMessage() . "\nStack: " . $e->getTraceAsString()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } catch (Error $e) { // Catch PHP 7+ Error class (for fatal errors) $_SESSION['flash_message'] = "✗ Fatal Error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN fatal error: " . $e->getMessage() . "\nStack: " . $e->getTraceAsString()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } catch (Throwable $e) { // Catch everything else $_SESSION['flash_message'] = "✗ Unexpected error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN unexpected error: " . $e->getMessage()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } } } ?> YAMN Web, invio anonimo

⚡ YAMN WEB INTERFACE ⚡

YAMN composition, local encryption, send-only Nym transport
This interface prepares and submits YAMN packets. Read more: detailed architecture and operation
Remailer data

The primary statistics source is Victor's YAMN pinger at echolot.virebent.art. Fallback pingers are tried automatically if needed.

This may take a few minutes because the update uses Tor and tries fallback sources if necessary.
Entry receives the YAMN packet, Middle forwards it through the chain, and Exit delivers the decoded message.
Used as the From header.
Optional. It is not used to retrieve replies.
Required for email delivery. Leave empty when publishing to a newsgroup.
Optional. When set, the message is routed through the configured Mail-to-News gateway. Leave empty for email.
Optional. Links the article to an existing thread.
The server creates the encrypted YAMN envelope in memory and sends only that packet through Nym. Remailer queues may take several hours.