Priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)'); $this->Boundary = md5(date('r', time())); $this->AgentIdent = 'PHP/Mail'; $this->TestMode = false; $this->Clear(); } function Clear(): void { $this->Bodies = array(); $this->Attachments = array(); $this->Recipients = array(); $this->SenderAddress = ''; $this->SenderName = ''; $this->Subject = ''; $this->Organization = ''; $this->ReplyTo = ''; $this->Headers = array(); } function AddToCombined(string $Address): void { $this->Recipients[] = array('Address' => $Address, 'Type' => 'SendCombined'); } function AddTo(string $Address, string $Name): void { $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'Send'); } function AddCc(string $Address, string $Name): void { $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'Copy'); } function AddBcc(string $Address, string $Name): void { $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'HiddenCopy'); } function AddBody(string $Content, string $MimeType = 'text/plain', string $Charset = 'utf-8'): void { $this->Bodies[] = array('Content' => $Content, 'Type' => strtolower($MimeType), 'Charset' => strtolower($Charset)); } function Organization(string $org): void { if (trim($org != '')) $this->xheaders['Organization'] = $org; } function Priority(int $Priority): bool { if (!intval($Priority)) return false; if (!isset($this->Priorities[$Priority - 1])) return false; $this->xheaders['X-Priority'] = $this->Priorities[$Priority - 1]; return true; } function AttachFile($FileName, $FileType, $Disposition = DISPOSITION_ATTACHMENT): void { $this->Attachments[] = array('FileName' => $FileName, 'FileType' => $FileType, 'Disposition' => $Disposition, 'Type' => 'File'); } function AttachData($FileName, $FileType, $Data, $Disposition = DISPOSITION_ATTACHMENT): void { $this->Attachments[] = array('FileName' => $FileName, 'FileType' => $FileType, 'Disposition' => $Disposition, 'Type' => 'Data', 'Data' => $Data); } function Send(): bool { if (count($this->Bodies) == 0) throw new Exception(T('Mail message need at least one text body')); $Body = $this->BuildAttachment($this->BuildBody()); $To = ''; $this->Headers['CC'] = ''; $this->Headers['BCC'] = ''; foreach ($this->Recipients as $Index => $Recipient) { if ($Recipient['Type'] == 'SendCombined') { if ($Index > 0) $To .= ', '; $To .= $Recipient['Address']; } else if ($Recipient['Type'] == 'Send') { if ($Index > 0) $To .= ', '; $To .= $Recipient['Name'].' <'.$Recipient['Address'].'>'; } else if ($Recipient['Type'] == 'Copy') { if ($Index > 0) $this->Headers['CC'] .= ', '; $this->Headers['CC'] .= $Recipient['Name'].' <'.$To['Address'].'>'; } else if ($Recipient['Type'] == 'HiddenCopy') { if ($Index > 0) $this->Headers['BCC'] .= ', '; $this->Headers['BCC'] .= $Recipient['Name'].' <'.$To['Address'].'>'; } } if ($To == '') throw new Exception(T('Mail message need at least one recipient address')); $this->Headers['Mime-Version'] = '1.0'; if ($this->AgentIdent != '') $this->Headers['X-Mailer'] = $this->AgentIdent; if ($this->ReplyTo != '') $this->Headers['Reply-To'] = $this->ReplyTo; if ($this->From != '') { $IndexStart = strpos($this->From, '<'); if ($IndexStart !== false) { $this->Headers['From'] = '=?utf-8?Q?'.quoted_printable_encode(trim(substr($this->From, 0, $IndexStart))).'?= '.substr($this->From, $IndexStart); } else { $this->Headers['From'] = $this->From; } } $Headers = ''; foreach ($this->Headers as $Header => $Value) { if (($Header != 'Subject') and ($Value != '')) $Headers .= $Header.': '.$Value."\n"; } $this->Subject = strtr($this->Subject, "\r\n", ' '); if ($this->Subject == '') throw new Exception(T('Mail message missing Subject')); if ($this->TestMode) { echo('to: '.$To.', subject: '.$this->Subject.', body: '.$Body.', headers: '.$Headers); $res = true; } else { $res = mail($To, $this->Subject, $Body, $Headers); } return $res; } function ValidEmail(string $Address): bool { if (preg_match(".*<(.+)>", $Address, $regs)) $Address = $regs[1]; if (preg_match("^[^@ ]+@([a-zA-Z0-9\-]+\.)+([a-zA-Z0-9\-]{2}|net|com|gov|mil|org|edu|int)\$", $Address)) return true; else return false; } function CheckAdresses(array $Addresses): void { foreach ($Addresses as $Address) { if (!$this->ValidEmail($Address)) { throw new Exception(sprintf(T('Mail message invalid address %s'), $Address)); } } } private function ContentEncoding($Charset): string { if ($Charset != CHARSET_ASCII) return '8bit'; else return '7bit'; } private function BuildAttachment($Body): string { if (count($this->Attachments) > 0) { $this->Headers['Content-Type'] = "multipart/mixed;\n boundary=\"PHP-mixed-".$this->Boundary."\""; $Result = "This is a multi-part message in MIME format.\n". "--PHP-mixed-".$this->Boundary."\n"; $Result .= $Body; foreach ($this->Attachments as $Attachment) { $FileName = $Attachment['FileName']; $BaseName = basename($FileName); $ContentType = $Attachment['FileType']; $Disposition = $Attachment['Disposition']; if ($Attachment['Type'] == 'File') { if (!file_exists($FileName)) throw new Exception(sprintf(T('Mail message attached file %s can\'t be found'), $FileName)); $Data = file_get_contents($FileName); } else if ($Attachment['Type'] == 'Data') $Data = $Attachment['Data']; else $Data = ''; $Result .= "\n".'--PHP-mixed-'.$this->Boundary."\n". "Content-Type: ".$ContentType."; name=\"".$BaseName."\"\n". "Content-Transfer-Encoding: base64\n". "Content-Disposition: ".$Disposition."\n\n"; $Result .= chunk_split(base64_encode($Data))."\r\n"; } } else $Result = $Body; return $Result; } private function BuildBody(): string { $Result = ''; if (count($this->Bodies) > 1) { $this->Headers['Content-Type'] = 'multipart/alternative; boundary="PHP-alt-'.$this->Boundary.'"'; $Result .= 'Content-Type: multipart/alternative; boundary="PHP-alt-'.$this->Boundary.'"'. "\n\n"; } else { $this->Headers['Content-Type'] = $this->Bodies[0]['Type'].'; charset='.$this->Bodies[0]['Charset']; $this->Headers['Content-Transfer-Encoding'] = $this->ContentEncoding($this->Bodies[0]['Charset']); } foreach ($this->Bodies as $Body) { if (count($this->Bodies) > 1) $Result .= "\n\n".'--PHP-alt-'.$this->Boundary."\n"; $Result .= 'Content-Type: '.$Body['Type'].'; charset='.$Body['Charset']. "\nContent-Transfer-Encoding: ".$this->ContentEncoding($Body['Charset'])."\n\n".$Body['Content']."\n"; } return $Result; } } /* // Example $Mail = new Mail(); $Mail->AddTo('nobody@nodomain', 'Recipient'); $Mail->From = 'No reply '; $Mail->Subject = 'Test message'; $Mail->AddBody('This is sample message sent by PHP Mail class'); $Mail->AddBody('This is sample HTML message sent by PHP Mail class', 'text/html'); $Mail->AttachFile('mailtest.php', 'text/plain'); $Mail->AttachData('DataFile.txt', 'text/plain', 'Sample text'); $Mail->Send(); */