debug_toSingleAddress = $debug_email; } public function setSubject($newsubject) { $this->subject = $newsubject; } public function setSender($email, $name = '') { $this->sender = array('mail' => $email, 'name' => $name); } public function setReplyTo($email, $name = '') { $this->replyto = array('mail' => $email, 'name' => $name); } public function addRecipient($email, $name = '') { $this->recipients[] = array('mail' => $email, 'name' => $name); } public function addCC($email, $name = '') { $this->cc[] = array('mail' => $email, 'name' => $name); } public function addBCC($email, $name = '') { $this->bcc[] = array('mail' => $email, 'name' => $name); } public function addHeader($hname, $hcontent = '') { $this->headers[] = array('name' => $hname, 'content' => $hcontent); } public function addHeaderAddress($hname, $email, $name = '') { if (strlen($name)) { $hcontent = $this->mimeencode($name, true).' <'.$email.'>'; } else { $hcontent = $email; } $this->headers[] = array('name' => $hname, 'content' => $hcontent); } public function setCharset($newcharset) { $this->charset = $newcharset; } public function addMailText($textpart) { $this->mailtext .= $textpart; } public function addAttachment($aname, $acontent, $atype = 'application/octet-stream') { $this->attachments[] = array('name' => $aname, 'content' => $acontent, 'type' => $atype); } public function getAddresses($addrtype = null) { // returns all addresses this mail gets sent to if (!is_array($addrtype)) { if (strlen($addrtype)) { $addrtype = explode(',', strtolower($addrtype)); } else { $addrtype = array('to','cc','bcc'); } } $mailaddresses = array(); if (in_array('to', $addrtype)) { foreach ($this->recipients as $address) { if (strlen($address['mail'] ?? '')) { $mailaddresses[] = array('mail'=>$address['mail'], 'name'=>strlen($address['name'])?$address['name']:'', 'addrtype'=>'to'); } } } if (in_array('cc', $addrtype)) { foreach ($this->cc as $address) { if (strlen($address['mail'] ?? '')) { $mailaddresses[] = array('mail'=>$address['mail'], 'name'=>strlen($address['name'])?$address['name']:'', 'addrtype'=>'cc'); } } } if (in_array('bcc', $addrtype)) { foreach ($this->bcc as $address) { if (strlen($address['mail'] ?? '')) { $mailaddresses[] = array('mail'=>$address['mail'], 'name'=>strlen($address['name'])?$address['name']:'', 'addrtype'=>'bcc'); } } } return $mailaddresses; } public function send() { global $util; $mtxt = ''; $hdrs = 'MIME-Version: 1.0'."\n"; $subj = $this->mimeencode($this->subject); if (strlen($this->sender['name'])) { $hdrs .= 'From: '.$this->mimeencode($this->sender['name'], true).' <'.$this->sender['mail'].'>'."\n"; } else { $hdrs .= 'From: '.$this->sender['mail']."\n"; } if (count($this->replyto)) { if (strlen($this->replyto['name'])) { $hdrs .= 'Reply-to: '.$this->mimeencode($this->replyto['name'], true).' <'.$this->replyto['mail'].'>'."\n"; } else { $hdrs .= 'Reply-to: '.$this->replyto['mail']."\n"; } } if (count($this->recipients)) { $recpt = ''; foreach ($this->recipients as $address) { if (strlen($address['mail'] ?? '')) { if (strlen($address['name'])) { $recpt .= $this->mimeencode($address['name'], true).' <'.$address['mail'].'>,'; } else { $recpt .= $address['mail'].','; } } } $recpt = preg_replace('/,$/', '', $recpt); } if (!strlen($recpt)) { return null; } if (count($this->cc)) { $adrs = ''; foreach ($this->cc as $address) { if (strlen($address['name'])) { $adrs .= $this->mimeencode($address['name'], true).' <'.$address['mail'].'>,'; } else { $adrs .= $address['mail'].','; } } $adrs = preg_replace('/,$/', '', $adrs); $hdrs .= (strlen($this->debug_toSingleAddress)?'X-Real-':'').'Cc: '.$adrs."\n"; } if (count($this->bcc)) { $adrs = ''; foreach ($this->bcc as $address) { if (strlen($address['name'])) { $adrs .= $this->mimeencode($address['name'], true).' <'.$address['mail'].'>,'; } else { $adrs .= $address['mail'].','; } } $adrs = preg_replace('/,$/', '', $adrs); $hdrs .= (strlen($this->debug_toSingleAddress)?'X-Real-':'').'Bcc: '.$adrs."\n"; } if (count($this->headers)) { foreach ($this->headers as $header) { $hdrs .= $header['name'].': '.$header['content']."\n"; } } if (count($this->attachments)) { // create random boundary, 20 chars, always beginning with KaiRo ;-) $boundary = 'KaiRo'; for ($i = 1; $i <= 15; $i++) { $r = rand(0, 61); if ($r < 10) { $boundary .= chr($r + 48); } elseif ($r < 36) { $boundary .= chr($r + 55); } elseif ($r < 62) { $boundary .= chr($r + 61); } } $hdrs .= 'Content-Type: multipart/mixed; boundary="'.$boundary.'";'."\n"; $hdrs .= 'Content-Transfer-Encoding: 7bit'."\n"; $mtxt .= 'This part of the E-mail should never be seen. If'."\n"; $mtxt .= 'you are reading this, consider upgrading your e-mail'."\n"; $mtxt .= 'client to a MIME-compatible client.'."\n"; $mtxt .= "\n".'--'.$boundary."\n"; if (preg_match('|^text/|', $this->content_type)) { $mtxt .= 'Content-Type: '.$this->content_type.'; charset="'.$this->charset.'"'."\n"; } else { $mtxt .= 'Content-Type: '.$this->content_type."\n"; } $mtxt .= 'Content-Transfer-Encoding: 8bit'."\n\n"; } else { if (preg_match('|^text/|', $this->content_type)) { $hdrs .= 'Content-Type: '.$this->content_type.'; charset="'.$this->charset.'"'."\n"; } else { $hdrs .= 'Content-Type: '.$this->content_type."\n"; } $hdrs .= 'Content-Transfer-Encoding: 8bit'."\n"; } $mtxt .= stripslashes($this->mailtext); if (count($this->attachments)) { foreach ($this->attachments as $attach) { $mtxt .= "\n".'--'.$boundary."\n"; $mtxt .= 'Content-Type: '.$attach['type'].'; name="'.$attach['name'].'";'."\n"; if (preg_match('/^(text|message)\//', $attach['type'])) { $mtxt .= 'Content-Transfer-Encoding: 8bit'."\n"; $mtxt .= 'Content-Disposition: attachment'."\n\n"; $mtxt .= $attach['content']; $mtxt .= "\n"; } else { $mtxt .= 'Content-Transfer-Encoding: base64'."\n"; $mtxt .= 'Content-Disposition: attachment'."\n\n"; $mtxt .= rtrim(chunk_split(base64_encode($attach['content']), 76)); ; $mtxt .= "\n"; } } $mtxt .= '--'.$boundary.'--'."\n"; } if (strlen($this->debug_toSingleAddress)) { $hdrs .= 'X-Real-To: '.$recpt."\n"; $recpt = $this->debug_toSingleAddress; } //print('Subject: '.$util->htmlify($subj).'
'."\n"); //print('To: '.$util->htmlify($recpt).'
'."\n"); //print(nl2br($util->htmlify($hdrs))); //print(nl2br($util->htmlify($mtxt))); return mail($recpt, $subj, $mtxt, $hdrs); } private function mimeencode($fieldtext, $stringescape = false) { if (function_exists('imap_8bit')) { $mText = imap_8bit($fieldtext); } else { $mText = quoted_printable_encode($fieldtext); } $is_qpformat = ($mText != $fieldtext); if ($stringescape && preg_match('/[^\w !#$%&\'*+\/=?^`{|}~-]/', $mText)) { // if needed, make this a quoted-string instead of an atom (to speak in RFC2822 language) $mText = '"'.strtr($mText, array('"' => '\"', '\\' => '\\\\')).'"'; } if ($is_qpformat) { $mText = strtr($mText, array('_' => '=5F', ' ' => '_', '?' => '=3F')); $mText = '=?'.strtoupper($this->charset).'?Q?'.$mText.'?='; } return $mText; } private function quoted_printable_encode($sText, $bEmulate_imap_8bit=true) { /* by ...deed.ztinmehc-ut.zrh@umuumu@hrz.tu-chemnitz.deed... from https://secure.php.net/manual/en/function.imap-8bit.php#61216 I use the following function instead of imap_8bit when using PHP without the IMAP module, which is based on code found in http://www.php.net/quoted_printable_decode, and giving (supposedly) exactly the same results as imap_8bit, (tested on thousands of random strings containing lots of spaces, tabs, crlf, lfcr, lf, cr and so on, no counterexample found SO FAR:) AND you can force a trailing space to be encoded, as opposed to what imap_8bit does, which I consider is a violation of RFC2045, (see http://bugs.php.net/bug.php?id=35290) by commenting that one central line. */ // split text into lines $aLines=explode(chr(13).chr(10),$sText); for ($i=0;$i