Subversion Repositories php_utils

Rev

Rev 5 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * Secure Mailer PHP Class
  5.  * Copyright 2009-2013 Daniel Marschall, ViaThinkSoft
  6.  * QB_SECURE_MAIL_PARAM (C) Erich Kachel
  7.  * Version 2013-04-14
  8.  *
  9.  * Licensed under the Apache License, Version 2.0 (the "License");
  10.  * you may not use this file except in compliance with the License.
  11.  * You may obtain a copy of the License at
  12.  *
  13.  *     http://www.apache.org/licenses/LICENSE-2.0
  14.  *
  15.  * Unless required by applicable law or agreed to in writing, software
  16.  * distributed under the License is distributed on an "AS IS" BASIS,
  17.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18.  * See the License for the specific language governing permissions and
  19.  * limitations under the License.
  20.  */
  21.  
  22. // TODO: getHeaders() as single string , attachments , remove headers etc, headers as array in/out, do you also need addRawHeader()?
  23.  
  24. class SecureMailer {
  25.         private $headers = '';
  26.  
  27.         // TODO: This should rather be private, but it won't work
  28.         const endl = "\n"; // GMX doesn't like CRLF! wtf?! (tested in Postfix in Linux)
  29.  
  30.         private function QB_SECURE_MAIL_PARAM($param_ = '', $level_ = 2) {
  31.                 // Prevents eMail header injections
  32.                 // Source: http://www.erich-kachel.de/?p=26 (modified)
  33.  
  34.                 /* replace until done */
  35.                 $filtered = null;
  36.                 while (is_null($filtered) || ($param_ != $filtered)) {
  37.                         if (!is_null($filtered)) {
  38.                                 $param_ = $filtered;
  39.                         }
  40.  
  41.                         $filtered = preg_replace("/(Content-Transfer-Encoding:|MIME-Version:|content-type:|Subject:|to:|cc:|bcc:|from:|reply-to:)/ims", '', $param_);
  42.                 }
  43.  
  44.                 unset($filtered);
  45.  
  46.                 if ($level_ >= 2) {
  47.                         /* replace until done */
  48.                         while (!isset($filtered) || ($param_ != $filtered)) {
  49.                                 if (isset($filtered)) {
  50.                                         $param_ = $filtered;
  51.                                 }
  52.  
  53.                                 $filtered = preg_replace("/(%0A|\\\\r|%0D|\\\\n|%00|\\\\0|%09|\\\\t|%01|%02|%03|%04|%05|%06|%07|%08|%09|%0B|%0C|%0E|%0F|%10|%11|%12|%13)/ims", '', $param_);
  54.                         }
  55.                 }
  56.  
  57.                 return $param_;
  58.         }
  59.  
  60.         private function getHeaders() {
  61.                 return $this->headers;
  62.         }
  63.  
  64.         private static function mail_base64_encode($text) {
  65.                 // Why 72? Seen here: http://linux.dsplabs.com.au/munpack-mime-base64-multi-part-attachment-php-perl-decode-email-pdf-p82/
  66.                 return wordwrap(base64_encode($text), 72, self::endl, true);
  67.         }
  68.  
  69.         private function headerLine($name, $value) {
  70.                 // Change 2011-02-09
  71.                 // LF is OK! CRLF does lead to CR+CRLF on some systems!
  72.                 // http://bugs.php.net/bug.php?id=15841
  73.                 // The mail() function is not talking to an SMTP server, so RFC2822 does not apply here. mail() is talking to a command line program on the local system, and it is reasonable to expect that program to require system-native line breaks.
  74.                 return $this->QB_SECURE_MAIL_PARAM($name).': '.$this->QB_SECURE_MAIL_PARAM($value)."\n";
  75.         }
  76.  
  77.         public function addHeader($name, $value) {
  78.                 $this->headers .= $this->headerLine($name, $value);
  79.         }
  80.  
  81.         public static function utf8Subject($subject) {
  82.                 $subject = mb_convert_encoding($subject, 'UTF-8');
  83.                 return '=?UTF-8?B?'.base64_encode($subject).'?=';
  84.         }
  85.  
  86.         private function _sendMail($recipient, $subject, $message, $add_headers='') {
  87.                 return @mail(
  88.                         $this->QB_SECURE_MAIL_PARAM($recipient),
  89.                         $this->QB_SECURE_MAIL_PARAM($subject),
  90.                         $this->QB_SECURE_MAIL_PARAM($message, 1),
  91.                         $this->getHeaders().$add_headers
  92.                 );
  93.         }
  94.  
  95.         public function sendMail($recipient, $subject, $message) {
  96.                 return $this->_sendMail($recipient, $subject, $message, '');
  97.         }
  98.  
  99.         // TODO: generate plain from html (strip tags), optional
  100.         public function sendMailHTMLandPlainMultipart($to, $subject, $msg_html, $msg_plain) {
  101.                 $boundary = uniqid('np');
  102.  
  103.                 $msg_html  = $this->QB_SECURE_MAIL_PARAM($msg_html,  1);
  104.                 $msg_plain = $this->QB_SECURE_MAIL_PARAM($msg_plain, 1);
  105.  
  106.                 $add_headers  = $this->headerLine('MIME-Version', '1.0');
  107.                 $add_headers .= $this->headerLine('Content-Type', 'multipart/alternative; boundary="'.$boundary.'"');
  108.  
  109.                 $message  = "This is a MIME encoded message.";
  110.                 $message .= self::endl;
  111.                 $message .= self::endl;
  112.                 $message .= "--" . $boundary . self::endl;
  113.                 $message .= "Content-type: text/plain; charset=utf-8".self::endl;
  114.                 $message .= "Content-Transfer-Encoding: base64".self::endl;
  115.                 $message .= self::endl;
  116.                 $message .= $this->mail_base64_encode($msg_plain); // better than wordwrap&quoted-printable because of long lines (e.g. links)
  117.                 $message .= self::endl;
  118.                 $message .= self::endl;
  119.                 $message .= "--" . $boundary . self::endl;
  120.                 $message .= "Content-type: text/html; charset=utf-8".self::endl;
  121.                 $message .= "Content-Transfer-Encoding: base64".self::endl;
  122.                 $message .= self::endl;
  123.                 $message .= $this->mail_base64_encode($msg_html);
  124.                 $message .= self::endl;
  125.                 $message .= self::endl."--" . $boundary . "--";
  126.  
  127.                 return @mail(
  128.                         $this->QB_SECURE_MAIL_PARAM($to),
  129.                         $this->QB_SECURE_MAIL_PARAM($subject),
  130.                         $message,
  131.                         $this->getHeaders().$add_headers
  132.                 );
  133.         }
  134. }
  135.