230 lines
7.4 KiB
PHP
230 lines
7.4 KiB
PHP
<?php
|
|
|
|
require_once("Mail.php");
|
|
require_once("Mail/mime.php");
|
|
|
|
class Emailnotification {
|
|
private $headers = [];
|
|
private $subject;
|
|
private $body;
|
|
private $html;
|
|
private $from_name = false;
|
|
private $email_from = false;
|
|
private $email_to = false;
|
|
private $attachments = [];
|
|
|
|
private $object_type = "";
|
|
private $object_id = 0;
|
|
private $object_data = "";
|
|
|
|
private $_mimeheaders;
|
|
|
|
public function __construct($object_type = false, $object_id = false, $object_data = false) {
|
|
$this->headers = [
|
|
'X-Mailer' => MFAPPNAME.' Mailer',
|
|
];
|
|
|
|
$this->email_from = TT_OUTGOING_EMAIL;
|
|
$this->from_name = TT_OUTGOING_EMAIL_NAME;
|
|
|
|
if($object_type !== false) $this->object_type = $object_type;
|
|
if($object_id !== false) $this->object_id = $object_id;
|
|
if($object_data !== false) $this->object_data = $object_data;
|
|
}
|
|
|
|
public function addAttachment($filepath = null, $content = null, $name = false, $c_type = "application/octet-stream", $disposition = "attachment", $encoding = "base64" , $charset = "utf-8") {
|
|
$attachment = [
|
|
"file" => $filepath,
|
|
"content" => $content,
|
|
"name" => $name,
|
|
"c_type" => $c_type,
|
|
"disposition" => $disposition,
|
|
"encoding" => $encoding,
|
|
"charset" => $charset
|
|
];
|
|
|
|
$attachment["isfile"] = false;
|
|
if($filepath) {
|
|
$attachment['isfile'] = true;
|
|
}
|
|
|
|
$this->attachments[] = $attachment;
|
|
}
|
|
|
|
public function setHeader($name, $value) {
|
|
$this->headers[$name] = $value;
|
|
}
|
|
|
|
public function setSubject($subject) {
|
|
$this->subject = $subject;
|
|
}
|
|
|
|
public function setBody($body) {
|
|
$this->body = $body;
|
|
}
|
|
|
|
public function setHtmlBody($html) {
|
|
$this->html = $html;
|
|
}
|
|
|
|
public function setFrom($email, $name = false) {
|
|
$this->email_from = $email;
|
|
$this->from_name = $name;
|
|
}
|
|
|
|
public function setTo($email) {
|
|
$this->email_to = $email;
|
|
}
|
|
|
|
public function send() {
|
|
if(!$this->email_to) {
|
|
return false;
|
|
}
|
|
if(!$this->body && !$this->html) {
|
|
return false;
|
|
}
|
|
if(!is_array($this->headers) || !count($this->headers)) {
|
|
return false;
|
|
}
|
|
if(!$this->subject) {
|
|
return false;
|
|
}
|
|
|
|
if(!array_key_exists("Subject", $this->headers) || !$this->headers['Subject']) {
|
|
$this->setHeader("Subject", $this->subject);
|
|
}
|
|
|
|
if((!array_key_exists("From", $this->headers) || !$this->headers['From']) && $this->from_name) {
|
|
$this->headers['From'] = '"'.$this->from_name.'" <'.$this->email_from.'>';
|
|
}
|
|
|
|
$log = mfLoghandler::singleton();
|
|
|
|
//var_dump($this);exit;
|
|
|
|
$mimeparams['text_encoding']="8bit";
|
|
$mimeparams['text_charset']="utf-8";
|
|
$mimeparams['html_charset']="utf-8";
|
|
$mimeparams['head_charset']="utf-8";
|
|
|
|
$mime = new Mail_mime();
|
|
if($this->body) {
|
|
$mime->setTXTBody($this->body);
|
|
}
|
|
if($this->html) {
|
|
$mime->setHTMLBody($this->html);
|
|
}
|
|
|
|
//var_dump($this->attachments);exit;
|
|
|
|
if(count($this->attachments)) {
|
|
foreach($this->attachments as $att) {
|
|
if($att['isfile']) {
|
|
$mime->addAttachment($att["file"], $att["c_type"], $att["name"], true, $att['encoding'], $att['disposition'], $att['charset']);
|
|
} else {
|
|
$mime->addAttachment($att["content"], $att["c_type"], $att["name"], false, $att['encoding'], $att['disposition'], $att['charset']);
|
|
}
|
|
}
|
|
}
|
|
|
|
$body = $mime->get($mimeparams);
|
|
$headers = $mime->headers($this->headers);
|
|
$this->_mimeheaders = $headers;
|
|
//$log->debug(print_r($headers, true));
|
|
|
|
$mail =& Mail::factory('mail', ["-f ".$this->email_from]);
|
|
/*
|
|
* PHP 8's mail() function now outputs proper line endings in headers (CRLF instead of LF).
|
|
* Mail_mail < 2.0 would detect a unix system and change the headers line ending to LF.
|
|
* On Mail submission to Exim (via sendmail), mail() adds its own headers first with CRLF line ending,
|
|
* making Exim treat every subsequent header's LF as an invalid line ending, adding a whitespace after the LF,
|
|
* making all our custom headers into one long header.
|
|
*
|
|
* See: https://www.exim.org/exim-html-current/doc/html/spec_html/ch-message_processing.html#SECTlineendings
|
|
*
|
|
* So we force CRLF line endings for headers here.
|
|
*/
|
|
$mail->sep = "\r\n";
|
|
$mail->send($this->email_to, $headers, $body);
|
|
|
|
$this->_createEmailLog();
|
|
|
|
return true;
|
|
}
|
|
|
|
private function _createEmailLog() {
|
|
if(!$this->object_id || !$this->object_type) return true;
|
|
|
|
$log = mfLoghandler::singleton();
|
|
|
|
if(array_key_exists("To", $this->_mimeheaders)) {
|
|
$this->_mimeheaders['To'] = $this->email_to;
|
|
}
|
|
|
|
FronkDB::singleton()->startTransaction();
|
|
|
|
$el = EmailLog::create([
|
|
'object_type' => $this->object_type,
|
|
'object_id' => $this->object_id,
|
|
'object_data' => $this->object_data,
|
|
'from' => $this->email_from,
|
|
'to' => $this->email_to,
|
|
'headers' => json_encode($this->_mimeheaders),
|
|
'subject' => $this->subject,
|
|
'body_text' => $this->body,
|
|
'body_html' => $this->html,
|
|
]);
|
|
if(!$el->save()) {
|
|
$log->error(__METHOD__.": Error saving EmailLog. {$this->object_type}: {$this->object_id} from: '{$this->email_from}' | to: '{$this->email_to}' | subject: '{$this->subject}'");
|
|
FronkDB::singleton()->rollbackTransaction();
|
|
return false;
|
|
}
|
|
|
|
if(is_array($this->attachments) && count($this->attachments)) {
|
|
foreach($this->attachments as $att) {
|
|
if($att['isfile']) {
|
|
if(!file_exists($att["file"])) {
|
|
$log->error(__METHOD__.": File not found. ".$this->object_type.": ".$this->object_id." / Filename: ".$att['name']);
|
|
continue;
|
|
}
|
|
$sha256_hash = hash_file("sha256", $att["file"]);
|
|
$filesize = filesize($att["file"]);
|
|
$file_content = file_get_contents($att["file"]);
|
|
} else {
|
|
$sha256_hash = hash("sha256", $att["content"]);
|
|
$filesize = strlen($att["content"]);
|
|
$file_content = $att["content"];
|
|
}
|
|
|
|
// find attachment content or create it
|
|
$ela_content = EmailLogAttachmentContent::getFirst(['sha256' => $sha256_hash]);
|
|
if(!$ela_content) {
|
|
$ela_content = EmailLogAttachmentContent::create([
|
|
'mimetype' => $att['c_type'],
|
|
'filesize' => $filesize,
|
|
'sha256' => $sha256_hash,
|
|
'content' => $file_content,
|
|
]);
|
|
|
|
if (!$ela_content->save()) {
|
|
$log->error(__METHOD__ . ": Error saving EmailLogAttachmentContent. " . $this->object_type . ": " . $this->object_id . " / Filename: " . $att['name']);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$ela = EmailLogAttachment::create([
|
|
'emaillog_id' => $el->id,
|
|
'content_id' => $ela_content->id,
|
|
'filename' => $att['name'],
|
|
]);
|
|
if(!$ela->save()) {
|
|
$log->error(__METHOD__.": Error saving EmailLogAttachment. ".$this->object_type.": ".$this->object_id." / Filename: ".$att['name']);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
FronkDB::singleton()->commitTransaction();
|
|
}
|
|
|
|
} |