HEX
Server: LiteSpeed
System: Linux php-prod-3.spaceapp.ru 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: sarli3128 (1010)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/662498/root/home/retile.ru/public_html/system/library/mail/smtp.php
<?php
declare(strict_types=1);

namespace Mail;

class Smtp {
	/** @var string */
	public $smtp_hostname = '';
	/** @var string */
	public $smtp_username = '';
	/** @var string */
	public $smtp_password = '';
	/** @var int|string */
	public $smtp_port = 25;
	/** @var int|string */
	public $smtp_timeout = 5;
	/** @var bool */
	public $verp = false;
	/** @var string */
	public $parameter = '';
	/** @var array<int, string>|string */
	public $to = [];
	/** @var string */
	public $from = '';
	/** @var string */
	public $sender = '';
	/** @var string */
	public $reply_to = '';
	/** @var string */
	public $subject = '';
	/** @var string */
	public $text = '';
	/** @var string */
	public $html = '';
	/** @var array<int, string>|string */
	public $attachments = [];

	public function send(): void {
		$recipients = $this->normalizeRecipients();
	 	$this->from = 'cart@retile.ru';
	    $this->sender = 'cart@retile.ru';
	    $this->reply_to = 'cart@retile.ru';
		if (!$recipients) {
			throw new \Exception('Error: No recipients specified for SMTP message!');
		}

		if (!$this->from) {
			throw new \Exception('Error: The "from" address is not configured for SMTP message!');
		}

		$boundary = '----=_NextPart_' . md5((string) microtime(true));
		$replyToName = $this->reply_to ?: $this->sender;
		$replyToAddress = $this->reply_to ?: $this->from;
		$serverIdentity = $this->getServerIdentity();

		$header  = 'MIME-Version: 1.0' . PHP_EOL;
		$header .= 'To: <' . implode(',', $recipients) . '>' . PHP_EOL;
		$header .= 'Subject: =?UTF-8?B?' . base64_encode($this->subject) . '?=' . PHP_EOL;
		$header .= 'Date: ' . date('D, d M Y H:i:s O') . PHP_EOL;
		$header .= 'From: =?UTF-8?B?' . base64_encode($this->sender ?: $this->from) . '?= <' . $this->from . '>' . PHP_EOL;
		$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($replyToName) . '?= <' . $replyToAddress . '>' . PHP_EOL;
		$header .= 'Return-Path: ' . $this->from . PHP_EOL;
		$header .= 'X-Mailer: PHP/' . PHP_VERSION . PHP_EOL;
		$header .= 'Content-Type: multipart/mixed; boundary="' . $boundary . '"' . PHP_EOL . PHP_EOL;

		if (!$this->html) {
			$message  = '--' . $boundary . PHP_EOL;
			$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
			$message .= ($this->text ?: '') . PHP_EOL;
		} else {
			$message  = '--' . $boundary . PHP_EOL;
			$message .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '_alt"' . PHP_EOL . PHP_EOL;
			$message .= '--' . $boundary . '_alt' . PHP_EOL;
			$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
			$message .= ($this->text ?: 'This is a HTML email and your email client software does not support HTML email!') . PHP_EOL;
			$message .= '--' . $boundary . '_alt' . PHP_EOL;
			$message .= 'Content-Type: text/html; charset="utf-8"' . PHP_EOL;
			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
			$message .= $this->html . PHP_EOL;
			$message .= '--' . $boundary . '_alt--' . PHP_EOL;
		}

		foreach ($this->normalizeAttachments() as $attachment) {
			if (!is_file($attachment) || !is_readable($attachment)) {
				continue;
			}

			$content = file_get_contents($attachment);

			if ($content === false) {
				continue;
			}

			$filename = basename($attachment);

				$message .= '--' . $boundary . PHP_EOL;
			$message .= 'Content-Type: application/octet-stream; name="' . $filename . '"' . PHP_EOL;
				$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL;
			$message .= 'Content-Disposition: attachment; filename="' . $filename . '"' . PHP_EOL;
			$message .= 'Content-ID: <' . urlencode($filename) . '>' . PHP_EOL;
			$message .= 'X-Attachment-Id: ' . urlencode($filename) . PHP_EOL . PHP_EOL;
				$message .= chunk_split(base64_encode($content));
		}

		$message .= '--' . $boundary . '--' . PHP_EOL;

		$hostname = $this->resolveHostname();
		$port = (int) $this->smtp_port ?: 25;
		$timeout = max(1, (int) $this->smtp_timeout ?: 5);

		$handle = @fsockopen($hostname, $port, $errno, $errstr, $timeout);

		if (!$handle) {
			throw new \Exception(sprintf(
				'Error: %s (%s) while connecting to SMTP host %s:%s',
				$errstr ?: 'Unable to connect',
				$errno ?: 'n/a',
				$hostname,
				$port
			));
		}

		stream_set_timeout($handle, $timeout, 0);

		try {
			$greeting = $this->readReply($handle);

			if (substr($greeting, 0, 3) !== '220') {
				throw new \Exception('Error: SMTP server greeting was not accepted: ' . trim($greeting));
			}

			$this->sendCommand($handle, 'EHLO ' . $serverIdentity, ['250'], true);

			if ($this->isTls()) {
				$this->sendCommand($handle, 'STARTTLS', ['220']);

				$cryptoEnabled = @stream_socket_enable_crypto(
					$handle,
					true,
					STREAM_CRYPTO_METHOD_TLS_CLIENT
					| (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT') ? STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT : 0)
					| (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') ? STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT : 0)
				);

				if ($cryptoEnabled !== true) {
					throw new \Exception('Error: Failed to enable TLS on SMTP connection.');
				}

				$this->sendCommand($handle, 'EHLO ' . $serverIdentity, ['250']);
			}

			if ($this->smtp_username !== '' && $this->smtp_password !== '') {
				$this->sendCommand($handle, 'AUTH LOGIN', ['334']);
				$this->sendCommand($handle, base64_encode($this->smtp_username), ['334']);
				$this->sendCommand($handle, base64_encode($this->smtp_password), ['235']);
			} else {
				$this->sendCommand($handle, 'HELO ' . $serverIdentity, ['250']);
			}

			$mailFromCommand = $this->verp ? 'MAIL FROM: <' . $this->from . '> XVERP' : 'MAIL FROM: <' . $this->from . '>';
			$this->sendCommand($handle, $mailFromCommand, ['250']);

			foreach ($recipients as $recipient) {
				$this->sendCommand($handle, 'RCPT TO: <' . $recipient . '>', ['250', '251']);
			}

			$this->sendCommand($handle, 'DATA', ['354']);

			foreach ($this->prepareMessageLines($header, $message) as $line) {
				$this->write($handle, $line);
			}

			$this->sendCommand($handle, '.', ['250']);
			$this->sendCommand($handle, 'QUIT', ['221']);
		} finally {
			fclose($handle);
		}
	}

	/**
	 * @return array<int, string>
	 */
	private function normalizeRecipients(): array {
		if (is_array($this->to)) {
			$recipients = $this->to;
		} elseif (is_string($this->to) && $this->to !== '') {
			$recipients = array_map('trim', explode(',', $this->to));
		} else {
			$recipients = [];
		}

		return array_values(array_filter(array_map('trim', $recipients), static function ($value) {
			return $value !== '';
		}));
	}

	/**
	 * @return array<int, string>
	 */
	private function normalizeAttachments(): array {
		if (empty($this->attachments)) {
			return [];
		}

		$attachments = is_array($this->attachments) ? $this->attachments : [$this->attachments];

		return array_values(array_filter(array_map(static function ($attachment) {
			return is_string($attachment) ? trim($attachment) : '';
		}, $attachments), static function ($path) {
			return $path !== '';
		}));
	}

	private function resolveHostname(): string {
		if ($this->isTls()) {
			return substr($this->smtp_hostname, 6);
		}

		return $this->smtp_hostname ?: 'localhost';
	}

	private function isTls(): bool {
		return strncmp($this->smtp_hostname, 'tls://', 6) === 0;
	}

	private function getServerIdentity(): string {
		$identity = getenv('SERVER_NAME') ?: ($_SERVER['SERVER_NAME'] ?? '');

		return $identity ?: 'localhost';
	}

	private function sendCommand($handle, string $command, array $expectedCodes, bool $ignoreInitial220 = false): string {
		$this->write($handle, $command . "\r\n");
		$reply = $this->readReply($handle, $ignoreInitial220);

		$code = substr($reply, 0, 3);

		foreach ($expectedCodes as $expectedCode) {
			if ((string) $expectedCode === $code) {
				return $reply;
			}
		}

		throw new \Exception(sprintf(
			'Error: Unexpected SMTP response for "%s": %s',
			trim($command),
			trim($reply)
		));
	}

	private function readReply($handle, bool $ignoreInitial220 = false): string {
			$reply = '';

		while (($line = fgets($handle, 515)) !== false) {
			if (
				$ignoreInitial220
				&& $reply === ''
				&& substr($line, 0, 3) === '220'
				&& (strlen($line) >= 4 && $line[3] === ' ')
			) {
				continue;
			}

					$reply .= $line;

			if (strlen($line) >= 4 && $line[3] === ' ') {
						break;
					}
				}

		if ($reply === '') {
			throw new \Exception('Error: Empty response from SMTP server.');
		}

		return $reply;
	}

	private function prepareMessageLines(string $header, string $message): array {
		$normalized = str_replace(["\r\n", "\r"], "\n", $header . $message);
		$lines = explode("\n", $normalized);
		$isWindows = strncasecmp(PHP_OS, 'WIN', 3) === 0;
		$output = [];

			foreach ($lines as $line) {
			$chunks = str_split($line, 998);

			foreach ($chunks as $chunk) {
				if ($isWindows) {
					$chunk = str_replace("\n", "\r\n", $chunk);
				}

				$output[] = $chunk . "\r\n";
			}
		}

		return $output;
	}

	private function write($handle, string $data): void {
		if (false === fwrite($handle, $data)) {
			throw new \Exception('Error: Unable to write to SMTP socket.');
		}
	}
}