'MIME-Version', '/^Message-ID$/i' => 'Message-ID', '/^Content-Type$/i' => 'Content-Type', '/^Content-Disposition$/i' => 'Content-Disposition', '/^Content-Transfer-Encoding$/i' => 'Content-Transfer-Encoding', '/^From$/i' => 'From', '/^To$/i' => 'To', '/^Subject$/i' => 'Subject', '/^Date$/i' => 'Date', '/^Reply-To$/i' => 'Reply-To', '/^CC$/i' => 'CC', '/^BCC$/i' => 'BCC', '/^Return-Path$/i' => 'Return-Path', ]; function __construct($pagename, $properties=[]) { global $Charset; # TODO Exit with warning if missing functions # curl_init, mb_encode_mimeheader $this->pagename = $pagename; $this->init($properties); if($this->imapfolder && !$this->imapuserpass) $this->imapuserpass = $this->userpass; $arfrom = array_keys($this->rcpts($this->from)); $this->mailfrom = $arfrom[0]; $this->initprops = $properties; } public function init($properties) { foreach ($properties as $key => $value) { if (property_exists($this, $key)) $this->$key = $value; } } public function queue($to, $subject, $message, $headers = []) { # TODO } public function send($to, $subject, $message, $headers = []) { global $Charset, $Now; $atos = $this->rcpts($to); $headers = array_merge(['MIME-Version' => '1.0'], $this->normheaders($headers)); if(!empty($headers['CC'])) $atos = array_merge($atos, $this->rcpts($headers['CC'])); if(!empty($headers['BCC'])) { $atos = array_merge($atos, $this->rcpts($headers['CC'])); unset($headers['BCC']); } $tos = array_keys($atos); if(empty($headers['To'])) $headers['To'] = $to; $headers['From'] = $this->from; if(empty($headers['Reply-To'])) $headers['Reply-To'] = $this->from; $headers['Date'] = date('r'); $headers['Subject'] = $subject; $rand = mt_rand(100000, 999999); $headers['Message-ID'] = "<$rand.$Now.{$this->mailfrom}>"; if(is_array($message) || (is_string($message) && substr($message, 0, 7) == 'markup:')) { list($mmm, $hhh) = PmMultipartMail($message, $this->pagename); $headers = array_merge($headers, $hhh); $message = $mmm; } if(empty($headers['Content-Type'])) $headers['Content-Type'] = "text/plain; charset=$Charset"; $envelope = ''; foreach($headers as $k=>$v) { if(preg_match('/^(From|To|Subject|Reply-To)$/i', $k)) $envelope .= mb_encode_mimeheader("$k: $v", $Charset, 'B'); else $envelope .= "$k: $v"; $envelope .= "\r\n"; } $message = str_replace("\r", '', $message); $message = str_replace("\n", "\r\n", $message); $envelope .= "\r\n$message"; $sret = $this->upload_phpcurl($this->server, $this->userpass, $envelope, $tos); if($sret && $this->imapfolder) $iret = $this->upload_phpcurl($this->imapfolder, $this->imapuserpass, $envelope); return $sret === false? false:true; } protected function normheaders($headers) { $norm = []; foreach($headers as $k=>$v) { $nk = PPRA($this->req, $k); $norm[$nk] = $v; } return $norm; } protected function rcpts($header) { $x = preg_replace('/ *".*?" */', '', $header); $x = preg_split("/[,;\n]+/", $x, -1, PREG_SPLIT_NO_EMPTY); $out = []; if(count($x)>1) { foreach($x as $e) $out = array_merge($out, $this->rcpts($e)); return $out; } $r = trim($header); if(filter_var($r, FILTER_VALIDATE_EMAIL)) { $out[$r] = 1; } else if(preg_match('!<([^\\s<>@]+@[^\\s<>@]+?)>!', $r, $m)) { if(filter_var($m[1], FILTER_VALIDATE_EMAIL)) { $out[$m[1]] = 1; } } return $out; } protected function upload_syscurl($server, $userpass, $envelope, $tos = false) { # TODO reuse from MailSMTP } protected function upload_phpcurl($server, $userpass, $envelope, $tos = false) { $fpp = fopen('php://temp', 'r+'); fwrite($fpp, $envelope); rewind($fpp); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $server, CURLOPT_USERPWD => $userpass, CURLOPT_INFILE => $fpp, CURLOPT_INFILESIZE => strlen($envelope), CURLOPT_UPLOAD => true, CURLOPT_VERBOSE => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPAUTH => CURLAUTH_ANY, CURLOPT_USE_SSL => CURLUSESSL_ALL, ]); if($tos) { curl_setopt($ch, CURLOPT_MAIL_FROM, $this->mailfrom); curl_setopt($ch, CURLOPT_MAIL_RCPT, $tos); } if(!$this->verify) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); } $start_time = microtime(true); $x = curl_exec($ch); $end_time = microtime(true); $time = number_format($end_time - $start_time, 6); curl_close($ch); fclose($fpp); return $x; } }