<?php
// smtp_mailer.php
// A lightweight, Native PHP SMTP Mailer class (No dependencies)
// Supports: None, STARTTLS (port 587), SSL (port 465)

class SmtpMailer
{
    private $host;
    private $port;
    private $username;
    private $password;
    private $encryption; // 'ssl', 'tls', or 'none'
    private $timeout = 30;
    private $debug = false;
    private $from_email;
    private $from_name;
    private $last_error = '';

    public function __construct($host = null, $port = null, $username = null, $password = null, $encryption = null)
    {
        // Try to fetch settings from DB if not provided
        $this->load_settings_from_db();

        // Override with constructor args if provided (fallback mechanism)
        if ($host)
            $this->host = $host;
        if ($port)
            $this->port = $port;
        if ($username)
            $this->username = $username;
        if ($password)
            $this->password = $password;
        if ($encryption !== null)
            $this->encryption = $encryption;

        // Final fallback to constants if defined and not set yet
        if (empty($this->host) && defined('SMTP_HOST'))
            $this->host = SMTP_HOST;
        if (empty($this->port) && defined('SMTP_PORT'))
            $this->port = SMTP_PORT;
        if (empty($this->username) && defined('SMTP_USER'))
            $this->username = SMTP_USER;
        if (empty($this->password) && defined('SMTP_PASS'))
            $this->password = SMTP_PASS;

        if (empty($this->from_email) && defined('SMTP_FROM_EMAIL'))
            $this->from_email = SMTP_FROM_EMAIL;
        if (empty($this->from_name) && defined('SMTP_FROM_NAME'))
            $this->from_name = SMTP_FROM_NAME;

        // Auto-detect encryption if not set
        if (empty($this->encryption)) {
            if ($this->port == 465) {
                $this->encryption = 'ssl';
            } elseif ($this->port == 587 || $this->port == 2525) {
                $this->encryption = 'tls';
            } else {
                $this->encryption = 'none';
            }
        }
    }

    private function load_settings_from_db()
    {
        global $conn;

        if ($conn) {
            $this->fetch_settings($conn);
        } else {
            if (defined('DB_HOST') && defined('DB_USER') && defined('DB_PASS') && defined('DB_NAME')) {
                $temp_conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
                if (!$temp_conn->connect_error) {
                    $this->fetch_settings($temp_conn);
                    $temp_conn->close();
                }
            }
        }
    }

    private function fetch_settings($db_connection)
    {
        $result = $db_connection->query("SELECT setting_key, setting_value FROM settings");
        if ($result) {
            while ($row = $result->fetch_assoc()) {
                switch ($row['setting_key']) {
                    case 'smtp_host':
                        $this->host = $row['setting_value'];
                        break;
                    case 'smtp_port':
                        $this->port = $row['setting_value'];
                        break;
                    case 'smtp_user':
                        $this->username = $row['setting_value'];
                        break;
                    case 'smtp_pass':
                        $this->password = $row['setting_value'];
                        break;
                    case 'smtp_from_email':
                        $this->from_email = $row['setting_value'];
                        break;
                    case 'smtp_from_name':
                        $this->from_name = $row['setting_value'];
                        break;
                    case 'smtp_encryption':
                        $this->encryption = $row['setting_value'];
                        break;
                }
            }
        }
    }

    public function getLastError()
    {
        return $this->last_error;
    }

    public function send($to, $subject, $html_body)
    {
        $this->last_error = '';
        try {
            // For SSL, use ssl:// wrapper
            $host = $this->host;
            if ($this->encryption === 'ssl') {
                $host = 'ssl://' . $this->host;
            }

            $socket = @fsockopen($host, $this->port, $errno, $errstr, $this->timeout);
            if (!$socket) {
                throw new Exception("Could not connect to SMTP host {$this->host}:{$this->port} - $errstr ($errno)");
            }

            // Read initial greeting
            $this->read($socket);

            // EHLO
            $this->cmd($socket, 'EHLO ' . gethostname());

            // STARTTLS for TLS encryption (port 587/2525)
            if ($this->encryption === 'tls') {
                $this->cmd($socket, 'STARTTLS');
                $crypto = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLS_CLIENT);
                if (!$crypto) {
                    throw new Exception("Failed to enable TLS encryption");
                }
                $this->cmd($socket, 'EHLO ' . gethostname());
            }

            // AUTH LOGIN
            $auth_response = $this->cmd($socket, 'AUTH LOGIN');
            $this->cmd($socket, base64_encode($this->username));
            $pass_response = $this->cmd($socket, base64_encode($this->password));

            // Check if auth failed (5xx response)
            if (strpos($pass_response, '535') !== false || strpos($pass_response, '5') === 0) {
                throw new Exception("SMTP authentication failed. Check username/password.");
            }

            // MAIL FROM & RCPT TO
            $from = $this->from_email ?: $this->username;
            $this->cmd($socket, "MAIL FROM: <{$from}>");
            $this->cmd($socket, "RCPT TO: <$to>");

            // DATA
            $this->cmd($socket, 'DATA');

            // Headers & Body
            $headers = "MIME-Version: 1.0\r\n";
            $headers .= "From: " . ($this->from_name ?: 'SaniBook') . " <" . $from . ">\r\n";
            $headers .= "To: $to\r\n";
            $headers .= "Subject: $subject\r\n";
            $headers .= "Content-Type: text/html; charset=UTF-8\r\n";
            $headers .= "\r\n"; // End of headers

            fputs($socket, $headers . $html_body . "\r\n.\r\n");
            $this->read($socket);

            // QUIT
            $this->cmd($socket, 'QUIT');
            fclose($socket);

            return true;
        } catch (Exception $e) {
            $this->last_error = $e->getMessage();
            error_log("SMTP Error: " . $e->getMessage());
            return false;
        }
    }

    private function cmd($socket, $command)
    {
        fputs($socket, $command . "\r\n");
        return $this->read($socket);
    }

    private function read($socket)
    {
        $response = '';
        while ($str = fgets($socket, 515)) {
            $response .= $str;
            if (substr($str, 3, 1) == ' ')
                break;
        }
        if ($this->debug)
            error_log("SMTP: $response");
        return $response;
    }
}
?>