From 70e5bef61a007c7f654b24f02d729d0eb1a5fe98 Mon Sep 17 00:00:00 2001 From: Yuan-Yi Chang Date: Thu, 5 Sep 2019 23:42:40 +0800 Subject: [PATCH] Try to help #1824 --- examples/smtp_reduce_mime_encoding.phps | 234 ++++++++++++++++++++++++ src/PHPMailer.php | 37 +++- 2 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 examples/smtp_reduce_mime_encoding.phps diff --git a/examples/smtp_reduce_mime_encoding.phps b/examples/smtp_reduce_mime_encoding.phps new file mode 100644 index 0000000000..dd4b8d9ebd --- /dev/null +++ b/examples/smtp_reduce_mime_encoding.phps @@ -0,0 +1,234 @@ +isSMTP(); + //Enable SMTP debugging + // 0 = off (for production use) + // 1 = client messages + // 2 = client and server messages + $mail->SMTPDebug = 0; + //Set the hostname of the mail server + $mail->Host = 'mail.example.com'; + //Set the SMTP port number - likely to be 25, 465 or 587 + $mail->Port = 25; + //Whether to use SMTP authentication + $mail->SMTPAuth = true; + //Username to use for SMTP authentication + $mail->Username = 'yourname@example.com'; + //Password to use for SMTP authentication + $mail->Password = 'yourpassword'; + //Set who the message is to be sent from + $mail->setFrom('from@example.com', 'First Last'); + //Set an alternative reply-to address + $mail->addReplyTo('replyto@example.com', 'First Last'); + //Set who the message is to be sent to + $mail->addAddress($receiver); + //Set the subject line + $mail->Subject = 'Hi '.$receiver.'!'; + //Read an HTML message body from an external file, convert referenced images to embedded, + //convert HTML into a basic plain-text alternative body + $mail->msgHTML(str_replace( '

This is a test of PHPMailer.

', '

Hi '.$receiver.'

', file_get_contents('contents.html')), __DIR__); + //Replace the plain text body with one created manually + $mail->AltBody = 'This is a plain-text message body for '.$receiver; + //Attach an image file + $mail->addAttachment('images/phpmailer_mini.png'); + + //Build the mail content + $mail->preSend(); + unset($mail); +} +$cost = microtime(true) - $start; + +echo $cost." sec\n"; + +echo "Sending $receiver_count mails with only one PHPMailer instance: "; + +$start = microtime(true); +{ + //Create a new PHPMailer instance + $mail = new PHPMailer; + //Tell PHPMailer to use SMTP + $mail->isSMTP(); + //Enable SMTP debugging + // 0 = off (for production use) + // 1 = client messages + // 2 = client and server messages + $mail->SMTPDebug = 0; + //Set the hostname of the mail server + $mail->Host = 'mail.example.com'; + //Set the SMTP port number - likely to be 25, 465 or 587 + $mail->Port = 25; + //Whether to use SMTP authentication + $mail->SMTPAuth = true; + //Username to use for SMTP authentication + $mail->Username = 'yourname@example.com'; + //Password to use for SMTP authentication + $mail->Password = 'yourpassword'; + //Set who the message is to be sent from + $mail->setFrom('from@example.com', 'First Last'); + //Set an alternative reply-to address + $mail->addReplyTo('replyto@example.com', 'First Last'); + + //Attach an image file + $mail->addAttachment('images/phpmailer_mini.png'); + + foreach ($receiver_list as $receiver) { + //Reset addresses + $mail->clearAddresses(); + //Set who the message is to be sent to + $mail->addAddress($receiver); + //Set the subject line + $mail->Subject = 'Hi '.$receiver.'!'; + //Read an HTML message body from an external file, convert referenced images to embedded, + //convert HTML into a basic plain-text alternative body + $mail->msgHTML(str_replace( '

This is a test of PHPMailer.

', '

Hi '.$receiver.'

', file_get_contents('contents.html')), __DIR__); + //Replace the plain text body with one created manually + $mail->AltBody = 'This is a plain-text message body for '.$receiver; + + //Build the mail content + $mail->preSend(); + } +} +$cost = microtime(true) - $start; + +echo $cost." sec\n"; +// +// --- +// +echo "Sending $receiver_count mails with creating a new PHPMailer instance and ReduceMIMEEncodeCacheStore: "; + +$start = microtime(true); +$cacheLookupTable = []; +foreach ($receiver_list as $receiver) { + //Create a new PHPMailer instance + $mail = new PHPMailer; + //Tell PHPMailer to use SMTP + $mail->isSMTP(); + //Enable SMTP debugging + // 0 = off (for production use) + // 1 = client messages + // 2 = client and server messages + $mail->SMTPDebug = 0; + //Set the hostname of the mail server + $mail->Host = 'mail.example.com'; + //Set the SMTP port number - likely to be 25, 465 or 587 + $mail->Port = 25; + //Whether to use SMTP authentication + $mail->SMTPAuth = true; + //Username to use for SMTP authentication + $mail->Username = 'yourname@example.com'; + //Password to use for SMTP authentication + $mail->Password = 'yourpassword'; + //Set who the message is to be sent from + $mail->setFrom('from@example.com', 'First Last'); + //Set an alternative reply-to address + $mail->addReplyTo('replyto@example.com', 'First Last'); + //Set who the message is to be sent to + $mail->addAddress($receiver); + //Set the subject line + $mail->Subject = 'Hi '.$receiver.'!'; + //Read an HTML message body from an external file, convert referenced images to embedded, + //convert HTML into a basic plain-text alternative body + $mail->msgHTML(str_replace( '

This is a test of PHPMailer.

', '

Hi '.$receiver.'

', file_get_contents('contents.html')), __DIR__); + //Replace the plain text body with one created manually + $mail->AltBody = 'This is a plain-text message body for '.$receiver; + //Attach an image file + $mail->addAttachment('images/phpmailer_mini.png'); + + //Set Reduce MIME Encode Cache Store + $mail->ReduceMIMEEncodeCacheStore = &$cacheLookupTable; + + //Build the mail content + $mail->preSend(); + unset($mail); +} +$cost = microtime(true) - $start; + +echo $cost." sec\n"; +// +// --- +// +echo "Sending $receiver_count mails with only one PHPMailer instance and ReduceMIMEEncodeCacheStore: "; + +$start = microtime(true); +$cacheLookupTable = []; +{ + //Create a new PHPMailer instance + $mail = new PHPMailer; + //Tell PHPMailer to use SMTP + $mail->isSMTP(); + //Enable SMTP debugging + // 0 = off (for production use) + // 1 = client messages + // 2 = client and server messages + $mail->SMTPDebug = 0; + //Set the hostname of the mail server + $mail->Host = 'mail.example.com'; + //Set the SMTP port number - likely to be 25, 465 or 587 + $mail->Port = 25; + //Whether to use SMTP authentication + $mail->SMTPAuth = true; + //Username to use for SMTP authentication + $mail->Username = 'yourname@example.com'; + //Password to use for SMTP authentication + $mail->Password = 'yourpassword'; + //Set who the message is to be sent from + $mail->setFrom('from@example.com', 'First Last'); + //Set an alternative reply-to address + $mail->addReplyTo('replyto@example.com', 'First Last'); + //Attach an image file + $mail->addAttachment('images/phpmailer_mini.png'); + + //Set Reduce MIME Encode Cache Store + $mail->ReduceMIMEEncodeCacheStore = &$cacheLookupTable; + + foreach ($receiver_list as $receiver) { + //Reset addresses + $mail->clearAddresses(); + //Set who the message is to be sent to + $mail->addAddress($receiver); + //Set the subject line + $mail->Subject = 'Hi '.$receiver.'!'; + //Read an HTML message body from an external file, convert referenced images to embedded, + //convert HTML into a basic plain-text alternative body + $mail->msgHTML(str_replace( '

This is a test of PHPMailer.

', '

Hi '.$receiver.'

', file_get_contents('contents.html')), __DIR__); + //Replace the plain text body with one created manually + $mail->AltBody = 'This is a plain-text message body for '.$receiver; + + //Build the mail content + $mail->preSend(); + } +} +$cost = microtime(true) - $start; + +echo $cost." sec\n"; + + diff --git a/src/PHPMailer.php b/src/PHPMailer.php index 16359fabe5..1130d23095 100644 --- a/src/PHPMailer.php +++ b/src/PHPMailer.php @@ -420,6 +420,17 @@ class PHPMailer */ protected $SingleToArray = []; + /** + * Whether to send the same message to each receiver + * with small changes in mail content. + * Use a lookup table to reduce attachment encoding. + * + * Storage for attachment encoding. + * + * @var array + */ + public $ReduceMIMEEncodeCacheStore = false; + /** * Whether to generate VERP addresses on send. * Only applicable when sending via SMTP. @@ -3031,12 +3042,28 @@ protected function encodeFile($path, $encoding = self::ENCODING_BASE64) if (!static::isPermittedPath($path) || !file_exists($path)) { throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE); } - $file_buffer = file_get_contents($path); - if (false === $file_buffer) { - throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE); + $file_buffer = ''; + if (is_array($this->ReduceMIMEEncodeCacheStore)) { + $cache_key = "$path\t$encoding"; + if (isset($this->ReduceMIMEEncodeCacheStore[$cache_key])) { + $file_buffer = $this->ReduceMIMEEncodeCacheStore[$cache_key]; + $this->edebug('encodeFile: use cache ['.$path.']['.$encoding.']'); + } else { + $file_buffer = file_get_contents($path); + if (false === $file_buffer) { + throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE); + } + $file_buffer = $this->encodeString($file_buffer, $encoding); + $this->ReduceMIMEEncodeCacheStore[$cache_key] = $file_buffer; + $this->edebug('encodeFile: set cache ['.$path.']['.$encoding.']'); + } + } else { + $file_buffer = file_get_contents($path); + if (false === $file_buffer) { + throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE); + } + $file_buffer = $this->encodeString($file_buffer, $encoding); } - $file_buffer = $this->encodeString($file_buffer, $encoding); - return $file_buffer; } catch (Exception $exc) { $this->setError($exc->getMessage());