<?php
/**
 * PHPMailer - A full-featured email creation and transfer class for PHP
 * @package PHPMailer
 * @author PHPMailer team
 * @license LGPL
 */

namespace PHPMailer\PHPMailer;

/**
 * PHPMailer - A full-featured email creation and transfer class for PHP
 * @package PHPMailer
 * @author PHPMailer team
 * @license LGPL
 */
class PHPMailer
{
    /**
     * The PHPMailer Version number.
     * @var string
     */
    const VERSION = '6.8.0';

    /**
     * Email priority.
     * @var int
     */
    const PRIORITY_LOWEST = 5;
    const PRIORITY_LOW = 4;
    const PRIORITY_NORMAL = 3;
    const PRIORITY_HIGH = 2;
    const PRIORITY_HIGHEST = 1;

    /**
     * Encryption types.
     * @var string
     */
    const ENCRYPTION_STARTTLS = 'tls';
    const ENCRYPTION_SMTPS = 'ssl';

    /**
     * The SMTP host.
     * @var string
     */
    public $Host = 'localhost';

    /**
     * The SMTP port.
     * @var int
     */
    public $Port = 25;

    /**
     * The SMTP username.
     * @var string
     */
    public $Username = '';

    /**
     * The SMTP password.
     * @var string
     */
    public $Password = '';

    /**
     * Whether to use SMTP authentication.
     * @var bool
     */
    public $SMTPAuth = false;

    /**
     * The SMTP security type.
     * @var string
     */
    public $SMTPSecure = '';

    /**
     * Whether to use SMTP.
     * @var bool
     */
    public $isSMTP = false;

    /**
     * The SMTP debug level.
     * @var int
     */
    public $SMTPDebug = 0;

    /**
     * The from email address.
     * @var string
     */
    public $From = '';

    /**
     * The from name.
     * @var string
     */
    public $FromName = '';

    /**
     * The subject.
     * @var string
     */
    public $Subject = '';

    /**
     * The body.
     * @var string
     */
    public $Body = '';

    /**
     * The alt body.
     * @var string
     */
    public $AltBody = '';

    /**
     * The recipients.
     * @var array
     */
    public $to = [];

    /**
     * The reply-to addresses.
     * @var array
     */
    public $ReplyTo = [];

    /**
     * Whether to use HTML.
     * @var bool
     */
    public $isHTML = false;

    /**
     * The charset.
     * @var string
     */
    public $CharSet = 'utf-8';

    /**
     * The content type.
     * @var string
     */
    public $ContentType = 'text/plain';

    /**
     * The encoding.
     * @var string
     */
    public $Encoding = '8bit';

    /**
     * The priority.
     * @var int
     */
    public $Priority = self::PRIORITY_NORMAL;

    /**
     * The message ID.
     * @var string
     */
    public $MessageID = '';

    /**
     * The X-Mailer.
     * @var string
     */
    public $XMailer = '';

    /**
     * The error info.
     * @var string
     */
    public $ErrorInfo = '';

    /**
     * The SMTP object.
     * @var SMTP
     */
    public $smtp;

    /**
     * Constructor.
     */
    public function __construct($exceptions = null)
    {
        $this->XMailer = 'PHPMailer ' . self::VERSION;
        $this->MessageID = $this->getServerVar('SERVER_NAME') . '@' . $this->getServerVar('SERVER_ADDR');
    }

    /**
     * Set the SMTP host.
     * @param string $host
     * @return $this
     */
    public function setHost($host)
    {
        $this->Host = $host;
        return $this;
    }

    /**
     * Set the SMTP port.
     * @param int $port
     * @return $this
     */
    public function setPort($port)
    {
        $this->Port = $port;
        return $this;
    }

    /**
     * Set the SMTP username.
     * @param string $username
     * @return $this
     */
    public function setUsername($username)
    {
        $this->Username = $username;
        return $this;
    }

    /**
     * Set the SMTP password.
     * @param string $password
     * @return $this
     */
    public function setPassword($password)
    {
        $this->Password = $password;
        return $this;
    }

    /**
     * Set SMTP authentication.
     * @param bool $auth
     * @return $this
     */
    public function setSMTPAuth($auth)
    {
        $this->SMTPAuth = $auth;
        return $this;
    }

    /**
     * Set the SMTP security.
     * @param string $secure
     * @return $this
     */
    public function setSMTPSecure($secure)
    {
        $this->SMTPSecure = $secure;
        return $this;
    }

    /**
     * Set to use SMTP.
     * @param bool $smtp
     * @return $this
     */
    public function isSMTP($smtp = true)
    {
        $this->isSMTP = $smtp;
        return $this;
    }

    /**
     * Set the SMTP debug level.
     * @param int $debug
     * @return $this
     */
    public function setSMTPDebug($debug)
    {
        $this->SMTPDebug = $debug;
        return $this;
    }

    /**
     * Set the from email address.
     * @param string $from
     * @param string $name
     * @return $this
     */
    public function setFrom($from, $name = '')
    {
        $this->From = $from;
        $this->FromName = $name;
        return $this;
    }

    /**
     * Add a recipient.
     * @param string $address
     * @param string $name
     * @return $this
     */
    public function addAddress($address, $name = '')
    {
        $this->to[] = ['address' => $address, 'name' => $name];
        return $this;
    }

    /**
     * Add a reply-to address.
     * @param string $address
     * @param string $name
     * @return $this
     */
    public function addReplyTo($address, $name = '')
    {
        $this->ReplyTo[] = ['address' => $address, 'name' => $name];
        return $this;
    }

    /**
     * Set the subject.
     * @param string $subject
     * @return $this
     */
    public function setSubject($subject)
    {
        $this->Subject = $subject;
        return $this;
    }

    /**
     * Set the body.
     * @param string $body
     * @return $this
     */
    public function setBody($body)
    {
        $this->Body = $body;
        return $this;
    }

    /**
     * Set the alt body.
     * @param string $altBody
     * @return $this
     */
    public function setAltBody($altBody)
    {
        $this->AltBody = $altBody;
        return $this;
    }

    /**
     * Set to use HTML.
     * @param bool $html
     * @return $this
     */
    public function isHTML($html = true)
    {
        $this->isHTML = $html;
        return $this;
    }

    /**
     * Set the charset.
     * @param string $charset
     * @return $this
     */
    public function setCharSet($charset)
    {
        $this->CharSet = $charset;
        return $this;
    }

    /**
     * Set the content type.
     * @param string $contentType
     * @return $this
     */
    public function setContentType($contentType)
    {
        $this->ContentType = $contentType;
        return $this;
    }

    /**
     * Set the encoding.
     * @param string $encoding
     * @return $this
     */
    public function setEncoding($encoding)
    {
        $this->Encoding = $encoding;
        return $this;
    }

    /**
     * Set the priority.
     * @param int $priority
     * @return $this
     */
    public function setPriority($priority)
    {
        $this->Priority = $priority;
        return $this;
    }

    /**
     * Send the email.
     * @return bool
     */
    public function send()
    {
        try {
            if ($this->isSMTP) {
                return $this->sendViaSMTP();
            } else {
                return $this->sendViaMail();
            }
        } catch (Exception $e) {
            $this->ErrorInfo = $e->getMessage();
            return false;
        }
    }

    /**
     * Send via SMTP.
     * @return bool
     */
    private function sendViaSMTP()
    {
        $this->smtp = new SMTP();
        $this->smtp->setHost($this->Host);
        $this->smtp->setPort($this->Port);
        $this->smtp->setUsername($this->Username);
        $this->smtp->setPassword($this->Password);
        $this->smtp->setSMTPAuth($this->SMTPAuth);
        $this->smtp->setSMTPSecure($this->SMTPSecure);
        $this->smtp->setSMTPDebug($this->SMTPDebug);

        if (!$this->smtp->connect()) {
            throw new Exception('SMTP connection failed: ' . $this->smtp->getLastError());
        }

        if ($this->SMTPAuth && !$this->smtp->authenticate()) {
            throw new Exception('SMTP authentication failed: ' . $this->smtp->getLastError());
        }

        if (!$this->smtp->mail($this->From)) {
            throw new Exception('SMTP MAIL command failed: ' . $this->smtp->getLastError());
        }

        foreach ($this->to as $recipient) {
            if (!$this->smtp->recipient($recipient['address'])) {
                throw new Exception('SMTP RCPT command failed for ' . $recipient['address'] . ': ' . $this->smtp->getLastError());
            }
        }

        if (!$this->smtp->data()) {
            throw new Exception('SMTP DATA command failed: ' . $this->smtp->getLastError());
        }

        $headers = $this->getHeaders();
        $body = $this->getBody();

        if (!$this->smtp->send($headers . "\r\n" . $body)) {
            throw new Exception('SMTP send failed: ' . $this->smtp->getLastError());
        }

        $this->smtp->quit();
        return true;
    }

    /**
     * Send via mail() function.
     * @return bool
     */
    private function sendViaMail()
    {
        $headers = $this->getHeaders();
        $body = $this->getBody();

        return mail($this->to[0]['address'], $this->Subject, $body, $headers);
    }

    /**
     * Get the headers.
     * @return string
     */
    private function getHeaders()
    {
        $headers = [];
        $headers[] = 'From: ' . $this->FromName . ' <' . $this->From . '>';
        $headers[] = 'Reply-To: ' . $this->From;
        $headers[] = 'Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet;
        $headers[] = 'X-Mailer: ' . $this->XMailer;
        $headers[] = 'Message-ID: <' . $this->MessageID . '>';

        return implode("\r\n", $headers);
    }

    /**
     * Get the body.
     * @return string
     */
    private function getBody()
    {
        if ($this->isHTML) {
            return $this->Body;
        } else {
            return $this->AltBody ?: $this->Body;
        }
    }

    /**
     * Get server variable.
     * @param string $var
     * @return string
     */
    private function getServerVar($var)
    {
        return $_SERVER[$var] ?? '';
    }
}
?>
