<?php
// ============================================================
// Minimal SMTP client - no external libraries required.
// Supports AUTH LOGIN over plain, STARTTLS, or implicit SSL connections.
// Good enough for transactional notification emails (single recipient, HTML body).
// ============================================================

class SimpleSmtpMailer
{
    private $host, $port, $username, $password, $encryption;
    public $lastError = '';

    public function __construct($host, $port, $username, $password, $encryption = 'tls') {
        $this->host = $host;
        $this->port = $port;
        $this->username = $username;
        $this->password = $password;
        $this->encryption = $encryption; // 'tls', 'ssl', or ''
    }

    public function send($fromEmail, $fromName, $toEmail, $subject, $htmlBody) {
        $transport = $this->encryption === 'ssl' ? 'ssl://' : '';
        $sock = @stream_socket_client($transport . $this->host . ':' . $this->port, $errno, $errstr, 15);
        if (!$sock) { $this->lastError = "Connection failed: $errstr"; return false; }

        $read = function () use ($sock) {
            $data = '';
            while ($line = fgets($sock, 515)) {
                $data .= $line;
                if (substr($line, 3, 1) === ' ') break;
            }
            return $data;
        };
        $write = function ($cmd) use ($sock) { fwrite($sock, $cmd . "\r\n"); };

        $read(); // banner
        $write('EHLO ' . parse_url(APP_URL, PHP_URL_HOST) ?: 'localhost');
        $ehlo = $read();

        if ($this->encryption === 'tls') {
            $write('STARTTLS');
            $resp = $read();
            if (substr($resp, 0, 3) !== '220') { $this->lastError = "STARTTLS refused: $resp"; fclose($sock); return false; }
            if (!stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                $this->lastError = 'TLS negotiation failed'; fclose($sock); return false;
            }
            $write('EHLO ' . (parse_url(APP_URL, PHP_URL_HOST) ?: 'localhost'));
            $read();
        }

        if ($this->username) {
            $write('AUTH LOGIN');
            $read();
            $write(base64_encode($this->username));
            $read();
            $write(base64_encode($this->password));
            $resp = $read();
            if (substr($resp, 0, 3) !== '235') { $this->lastError = "SMTP auth failed: $resp"; fclose($sock); return false; }
        }

        $write("MAIL FROM:<$fromEmail>");
        $resp = $read();
        if (substr($resp, 0, 3) !== '250') { $this->lastError = "MAIL FROM refused: $resp"; fclose($sock); return false; }

        $write("RCPT TO:<$toEmail>");
        $resp = $read();
        if (substr($resp, 0, 1) !== '2') { $this->lastError = "RCPT TO refused: $resp"; fclose($sock); return false; }

        $write('DATA');
        $read();

        $headers = "From: $fromName <$fromEmail>\r\n";
        $headers .= "To: <$toEmail>\r\n";
        $headers .= "Subject: $subject\r\n";
        $headers .= "MIME-Version: 1.0\r\n";
        $headers .= "Content-Type: text/html; charset=UTF-8\r\n";
        $headers .= "Date: " . date('r') . "\r\n";

        // Escape lines starting with a lone "." per SMTP data rules
        $escapedBody = preg_replace('/^\./m', '..', $htmlBody);

        $write($headers . "\r\n" . $escapedBody . "\r\n.");
        $resp = $read();
        if (substr($resp, 0, 3) !== '250') { $this->lastError = "Message rejected: $resp"; fclose($sock); return false; }

        $write('QUIT');
        fclose($sock);
        return true;
    }
}
