<?php namespace HashOver;// Copyright (C) 2018-2021 Jacob Barkdull// This file is part of HashOver.//// HashOver is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as// published by the Free Software Foundation, either version 3 of the// License, or (at your option) any later version.//// HashOver is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with HashOver.  If not, see <http://www.gnu.org/licenses/>.class Sendmail{	// Email data to send	protected $to = array ();	protected $from = array ();	protected $reply = array ();	protected $subject;	protected $text;	// Type of content being sent	protected $type = 'text';	// Sets who we're sending email to	public function to ($email, $name = null)	{		$this->to['email'] = $email;		$this->to['name'] = $name;	}	// Sets where recipient can reply to	public function replyTo ($email, $name = null)	{		$this->reply['email'] = $email;		$this->reply['name'] = $name;	}	// Sets who email is coming from	public function from ($email, $name = null)	{		// Set "from" email address and name		$this->from['email'] = $email;		$this->from['name'] = $name;		// Set "reply-to" the same way		if (empty ($this->reply['email'])) {			$this->replyTo ($email, $name);		}	}	// Sets subject line	public function subject ($text)	{		$this->subject = strip_tags ($text);	}	// Converts text to CRLF line ending format	protected function toCRLF ($text)	{		return preg_replace ('/\r\n|\r|\n/', "\r\n", $text);	}	// Converts message to plain text	protected function plainText ($text)	{		// Strip HTML tags		$text = strip_tags ($text);		// Convert to CRLF line ending format		$text = $this->toCRLF ($text);		// Convert HTML entities to normal characters		$text = html_entity_decode ($text, ENT_COMPAT, 'UTF-8');		// Encode text in quoted-printable format		$text = quoted_printable_encode ($text);		// And return text		return $text;	}	// Sets message body	public function text ($text)	{		// Set text property		$this->text = $this->plainText ($text);		// And set type to text		$this->type = 'text';	}	// Sets message body to HTML	public function html ($html)	{		// Convert to CRLF line ending format		$this->html = $this->toCRLF ($html);		// Encode HTML in quoted-printable format		$this->html = quoted_printable_encode ($this->html);		// Set automatic text version of message		if (empty ($this->text)) {			$this->text = $this->plainText ($html);		}		// And set type to HTML		$this->type = 'html';	}	// Sets message body	public function body ($text, $html = false)	{		// Set body as HTML if told to		if ($html === true) {			return $this->html ($text);		}		// Otherwise, set body as plain text		return $this->text ($text);	}	// Encodes given text as MIME "encoded word"	protected function encode ($text)	{		return mb_encode_mimeheader ($text);	}	// Converts to/from/reply-to to a formatted string	public function format (array $recipient)	{		// Check if a name was given		if (!empty ($recipient['name'])) {			// If so, encode name			$name = $this->encode ($recipient['name']);			// And construct email address in "name <email>" format			$address = $name . ' <' . $recipient['email'] . '>';		} else {			// If not, use email address as-is			$address = $recipient['email'];		}		// And return email address		return $address;	}	// Creates mail headers	protected function getHeaders ($boundary)	{		// Initial headers data		$data = array ();		// Add recipient headers		$data[] = 'MIME-Version: 1.0';		// Set From address if one is present		if (!empty ($this->from['email'])) {			$data[] = 'From: ' . $this->format ($this->from);		}		// Set Reply-To address if one is present		if (!empty ($this->reply['email'])) {			$data[] = 'Reply-To: ' . $this->format ($this->reply);		}		// Check if message type is text		if ($this->type === 'text') {			// If so, add plain text header			$data[] = 'Content-Type: text/plain; charset="UTF-8"';			$data[] = 'Content-Transfer-Encoding: quoted-printable';		} else {			// If not, add multipart header			$data[] = 'Content-Type: multipart/alternative; boundary="' . $boundary . '"';		}		// Convert headers data to string		$headers = implode ("\r\n", $data);		// And return headers as string		return $headers;	}	// Creates mail message	protected function getMessage ($boundary)	{		// Initial message data		$data = array ();		// Check if message type is text		if ($this->type === 'text') {			// If so, only add text version			$data[] = $this->text;		} else {			// If not, start multipart boundary			$data[] = '--' . $boundary;			// Add text version			$data[] = 'Content-Type: text/plain; charset="UTF-8"';			$data[] = 'Content-Transfer-Encoding: quoted-printable';			$data[] = '';			$data[] = $this->text;			// Add another multipart boundary			$data[] = '--' . $boundary;			// Add HTML version			$data[] = 'Content-Type: text/html; charset="UTF-8"';			$data[] = 'Content-Transfer-Encoding: quoted-printable';			$data[] = '';			$data[] = $this->html;			// And end multipart boundary			$data[] = '--' . $boundary . '--';		}		// Convert message data to string		$headers = implode ("\r\n", $data);		// And return message as string		return $headers;	}	// Sends an email	public function send ()	{		// Get email address we're sending email to		$to = $this->to['email'];		// Get quoted-printable encoded subject		$subject = $this->encode ($this->subject);		// Create unique boundary		$boundary = md5 (uniqid (time ()));		// Get message body		$message = $this->getMessage ($boundary);		// Get email headers		$headers = $this->getHeaders ($boundary);		// Check if a From email address is set		if (!empty ($this->from['email'])) {			// If so, set envelope sender address with -f option			$params = '-f ' . $this->from['email'];			// And actually send the email			mail ($to, $subject, $message, $headers, $params);		} else {			// If not, send email normally			mail ($to, $subject, $message, $headers);		}	}}