<?php
/**
 * Minimal, dependency-free SMTP sender for Uppal Construction.
 * Supports SSL (465), STARTTLS (587) and plain ('none', for testing),
 * with AUTH LOGIN. Returns [bool success, string error].
 *
 * Not a full mail library — just enough to reliably hand a message to
 * an authenticated cPanel mailbox so it lands in the inbox.
 */

declare(strict_types=1);

/** Encode a header value as UTF-8 base64 only when it contains non-ASCII. */
function smtp_header(string $s): string
{
    return preg_match('/[^\x20-\x7E]/', $s)
        ? '=?UTF-8?B?' . base64_encode($s) . '?='
        : $s;
}

/**
 * @param array $c   config (smtp_host, smtp_port, smtp_secure, smtp_user,
 *                   smtp_pass, smtp_verify, smtp_ehlo)
 */
function smtp_send(
    array $c,
    string $to,
    string $subject,
    string $body,
    string $fromEmail,
    string $fromName,
    string $replyTo
): array {
    $host   = (string)($c['smtp_host'] ?? '');
    $port   = (int)($c['smtp_port'] ?? 465);
    $secure = strtolower((string)($c['smtp_secure'] ?? 'ssl')); // ssl | tls | none
    $user   = (string)($c['smtp_user'] ?? '');
    $pass   = (string)($c['smtp_pass'] ?? '');
    $verify = $c['smtp_verify'] ?? true;
    $ehlo   = (string)($c['smtp_ehlo'] ?? ($_SERVER['SERVER_NAME'] ?? 'localhost'));
    $timeout = 20;

    if ($host === '') {
        return [false, 'smtp_host not set'];
    }

    $ctx = stream_context_create(['ssl' => [
        'verify_peer'       => (bool)$verify,
        'verify_peer_name'  => (bool)$verify,
        'allow_self_signed' => !$verify,
    ]]);
    $transport = ($secure === 'ssl' ? 'ssl://' : 'tcp://') . $host . ':' . $port;

    $fp = @stream_socket_client($transport, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $ctx);
    if (!$fp) {
        return [false, "connect failed: {$errstr} ({$errno})"];
    }
    stream_set_timeout($fp, $timeout);

    $read = static function () use ($fp): string {
        $data = '';
        while (($line = fgets($fp, 515)) !== false) {
            $data .= $line;
            // Last line of a reply has a space at position 3 (e.g. "250 OK")
            if (strlen($line) >= 4 && $line[3] === ' ') {
                break;
            }
        }
        return $data;
    };
    $send = static function (string $s) use ($fp): void {
        fwrite($fp, $s . "\r\n");
    };
    $ok = static function (string $resp, $codes): bool {
        return in_array(substr($resp, 0, 3), (array)$codes, true);
    };

    try {
        if (!$ok($read(), '220')) { fclose($fp); return [false, 'no greeting']; }

        $send('EHLO ' . $ehlo);
        if (!$ok($read(), '250')) {
            $send('HELO ' . $ehlo);
            if (!$ok($read(), '250')) { fclose($fp); return [false, 'EHLO rejected']; }
        }

        if ($secure === 'tls') {
            $send('STARTTLS');
            if (!$ok($read(), '220')) { fclose($fp); return [false, 'STARTTLS rejected']; }
            if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                fclose($fp); return [false, 'TLS handshake failed'];
            }
            $send('EHLO ' . $ehlo);
            if (!$ok($read(), '250')) { fclose($fp); return [false, 'EHLO (post-TLS) rejected']; }
        }

        if ($user !== '') {
            $send('AUTH LOGIN');
            if (!$ok($read(), '334')) { fclose($fp); return [false, 'AUTH not accepted']; }
            $send(base64_encode($user));
            if (!$ok($read(), '334')) { fclose($fp); return [false, 'username rejected']; }
            $send(base64_encode($pass));
            if (!$ok($read(), '235')) { fclose($fp); return [false, 'authentication failed']; }
        }

        $send('MAIL FROM:<' . $fromEmail . '>');
        if (!$ok($read(), '250')) { fclose($fp); return [false, 'MAIL FROM rejected']; }
        $send('RCPT TO:<' . $to . '>');
        if (!$ok($read(), ['250', '251'])) { fclose($fp); return [false, 'RCPT TO rejected']; }
        $send('DATA');
        if (!$ok($read(), '354')) { fclose($fp); return [false, 'DATA rejected']; }

        $headers  = 'From: ' . smtp_header($fromName) . ' <' . $fromEmail . ">\r\n";
        $headers .= 'To: <' . $to . ">\r\n";
        $headers .= 'Reply-To: <' . $replyTo . ">\r\n";
        $headers .= 'Subject: ' . smtp_header($subject) . "\r\n";
        $headers .= 'Date: ' . date('r') . "\r\n";
        $headers .= "MIME-Version: 1.0\r\n";
        $headers .= "Content-Type: text/plain; charset=utf-8\r\n";
        $headers .= "Content-Transfer-Encoding: 8bit\r\n";

        // Normalise newlines to CRLF and dot-stuff lines beginning with '.'
        $bodyOut = str_replace("\n", "\r\n", str_replace("\r\n", "\n", $body));
        $bodyOut = preg_replace('/^\./m', '..', $bodyOut);

        fwrite($fp, $headers . "\r\n" . $bodyOut . "\r\n.\r\n");
        if (!$ok($read(), '250')) { fclose($fp); return [false, 'message not accepted']; }

        $send('QUIT');
        fclose($fp);
        return [true, ''];
    } catch (Throwable $e) {
        if (is_resource($fp)) { fclose($fp); }
        return [false, 'smtp exception: ' . $e->getMessage()];
    }
}
