<?php
/**
 * Tiny dependency-free SMTP sender for OSCE Nexus.
 *
 * Speaks SMTP over a socket so no PHPMailer / Composer install is needed.
 * Supports implicit SSL (port 465, secure='ssl') and STARTTLS (port 587,
 * secure='tls'), with AUTH LOGIN. Good for low-volume transactional mail like
 * the account-deletion form.
 *
 * Returns true on success; on failure returns false and fills $err.
 */
function osce_smtp_send(array $cfg, $to, $subject, $body, $replyTo = '', &$err = null) {
    $host    = $cfg['host'];
    $port    = (int) $cfg['port'];
    $secure  = $cfg['secure'] ?? 'tls';
    $timeout = 25;

    $transport = ($secure === 'ssl') ? "ssl://{$host}:{$port}" : "tcp://{$host}:{$port}";
    $ctx = stream_context_create([
        'ssl' => ['verify_peer' => true, 'verify_peer_name' => true, 'SNI_enabled' => true],
    ]);
    $fp = @stream_socket_client(
        $transport, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $ctx
    );
    if (!$fp) {
        $err = "connect failed to {$transport}: {$errstr} ({$errno})";
        return false;
    }
    stream_set_timeout($fp, $timeout);

    // Read a (possibly multi-line) SMTP reply.
    $read = function () use ($fp) {
        $data = '';
        while (($line = fgets($fp, 1024)) !== false) {
            $data .= $line;
            if (isset($line[3]) && $line[3] === ' ') break;   // last line
        }
        return $data;
    };
    $send = function ($c) use ($fp) { fwrite($fp, $c . "\r\n"); };
    $ok   = function ($resp, $codes) use (&$err) {
        $code = substr($resp, 0, 3);
        if (!in_array($code, (array) $codes, true)) {
            $err = 'SMTP said: ' . trim($resp);
            return false;
        }
        return true;
    };

    $ehloName = $_SERVER['SERVER_NAME'] ?? 'localhost';

    try {
        if (!$ok($read(), '220')) return false;
        $send("EHLO {$ehloName}");
        if (!$ok($read(), '250')) return false;

        if ($secure === 'tls') {
            $send('STARTTLS');
            if (!$ok($read(), '220')) return false;
            $crypto = STREAM_CRYPTO_METHOD_TLS_CLIENT;
            if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
                $crypto |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
            }
            if (!@stream_socket_enable_crypto($fp, true, $crypto)) {
                $err = 'STARTTLS handshake failed';
                return false;
            }
            $send("EHLO {$ehloName}");
            if (!$ok($read(), '250')) return false;
        }

        $send('AUTH LOGIN');
        if (!$ok($read(), '334')) return false;
        $send(base64_encode($cfg['username']));
        if (!$ok($read(), '334')) return false;
        $send(base64_encode($cfg['password']));
        if (!$ok($read(), '235')) return false;   // 235 = auth OK

        $from = $cfg['from_email'];
        $send("MAIL FROM:<{$from}>");
        if (!$ok($read(), '250')) return false;
        $send("RCPT TO:<{$to}>");
        if (!$ok($read(), ['250', '251'])) return false;
        $send('DATA');
        if (!$ok($read(), '354')) return false;

        // Build the message. Normalise to CRLF and dot-stuff lines.
        $body = str_replace("\r\n", "\n", $body);
        $body = str_replace("\n", "\r\n", $body);
        $body = preg_replace('/^\./m', '..', $body);

        $encSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
        $encName    = '=?UTF-8?B?' . base64_encode($cfg['from_name'] ?? 'OSCE Nexus') . '?=';

        $msg  = 'Date: ' . date('r') . "\r\n";
        $msg .= "From: {$encName} <{$from}>\r\n";
        $msg .= "To: <{$to}>\r\n";
        if ($replyTo !== '' && filter_var($replyTo, FILTER_VALIDATE_EMAIL)) {
            $msg .= "Reply-To: <{$replyTo}>\r\n";
        }
        $msg .= "Subject: {$encSubject}\r\n";
        $msg .= "MIME-Version: 1.0\r\n";
        $msg .= "Content-Type: text/plain; charset=UTF-8\r\n";
        $msg .= "Content-Transfer-Encoding: 8bit\r\n";
        $msg .= "\r\n";
        $msg .= $body . "\r\n.";

        $send($msg);
        if (!$ok($read(), '250')) return false;

        $send('QUIT');
        return true;
    } finally {
        if (is_resource($fp)) {
            @fwrite($fp, "QUIT\r\n");
            @fclose($fp);
        }
    }
}
