diff --git a/program/include/rcmail_resend_mail.php b/program/include/rcmail_resend_mail.php new file mode 100644 index 000000000..9670e48d6 --- /dev/null +++ b/program/include/rcmail_resend_mail.php @@ -0,0 +1,188 @@ + | + | Author: Aleksander Machniak | + +-----------------------------------------------------------------------+ +*/ + +/** + * Mail_mime wrapper to handle mail resend/bounce + * + * @package Webmail + */ +class rcmail_resend_mail extends Mail_mime +{ + protected $orig_head; + protected $orig_body; + + + /** + * Constructor function + * + * Added two parameters: + * 'bounce_message' - rcube_message object of the original message + * 'bounce_headers' - An array of headers to be added to the original message + */ + public function __construct($params = array()) + { + // To make the code simpler always use delay_file_io=true + $params['delay_file_io'] = true; + $params['eol'] = "\r\n"; + + parent::__construct($params); + } + + /** + * Returns/Sets message headers + */ + public function headers($headers = array(), $overwrite = false, $skip_content = false) + { + // headers() wrapper that returns Resent-Cc, Resent-Bcc instead of Cc,Bcc + // it's also called to re-add Resent-Bcc after it has been sent (to store in Sent) + + if (array_key_exists('Bcc', $headers)) { + $this->build_params['bounce_headers']['Resent-Bcc'] = $headers['Bcc']; + } + + foreach ($this->build_params['bounce_headers'] as $key => $val) { + $headers[str_replace('Resent-', '', $key)] = $val; + } + + return $headers; + } + + /** + * Returns all message headers as string + */ + public function txtHeaders($headers = array(), $overwrite = false, $skip_content = false) + { + // i.e. add Resent-* headers on top of the original message head + $this->init_message(); + + $result = array(); + + foreach ($this->build_params['bounce_headers'] as $name => $value) { + $key = str_replace('Resent-', '', $name); + + // txtHeaders() can be used to unset Bcc header + if (array_key_exists($key, $headers)) { + $value = $headers[$key]; + $this->build_params['bounce_headers']['Resent-'.$key] = $value; + } + + if ($value) { + $result[] = "$name: $value"; + } + } + + $result = implode($this->build_params['eol'], $result); + + if (strlen($this->orig_head)) { + $result .= $this->build_params['eol'] . $this->orig_head; + } + + return $result; + } + + /** + * Save the message body to a file (if delay_file_io=true) + */ + public function saveMessageBody($file, $params = null) + { + $this->init_message(); + + // this will be called only once, so let just move the file + rename($this->orig_body, $file); + + $this->orig_head = null; + } + + protected function init_message() + { + if ($this->orig_head !== null) { + return; + } + + $rcmail = rcmail::get_instance(); + $storage = $rcmail->get_storage(); + $message = $this->build_params['bounce_message']; + $temp_dir = unslashify($rcmail->config->get('temp_dir')); + $path = tempnam($temp_dir, 'rcmBounce'); + + // We'll write the body to the file and the headers to a variable + if ($fp = fopen($path, 'w')) { + stream_filter_register('bounce_source', 'rcmail_bounce_stream_filter'); + stream_filter_append($fp, 'bounce_source'); + + // message part + if ($message->context) { + $message->get_part_body($message->context, false, 0, $fp); + } + // complete message + else { + $storage->set_folder($message->folder); + $storage->get_raw_body($message->uid, $fp); + } + + fclose($fp); + + $this->orig_head = rcmail_bounce_stream_filter::$headers; + $this->orig_body = $path; + } + } +} + +/** + * Stream filter to remove message headers from the streamed + * message source (and store them in a variable) + * + * @package Webmail + */ +class rcmail_bounce_stream_filter extends php_user_filter +{ + public static $headers; + + protected $in_body = false; + + public function onCreate() + { + self::$headers = ''; + } + + public function filter($in, $out, &$consumed, $closing) + { + while ($bucket = stream_bucket_make_writeable($in)) { + if (!$this->in_body) { + self::$headers .= $bucket->data; + if (($pos = strpos(self::$headers, "\r\n\r\n")) === false) { + continue; + } + + $bucket->data = substr(self::$headers, $pos + 4); + $bucket->datalen = strlen($bucket->data); + + self::$headers = substr(self::$headers, 0, $pos); + $this->in_body = true; + } + + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + } + + return PSFS_PASS_ON; + } +} diff --git a/program/steps/mail/bounce.inc b/program/steps/mail/bounce.inc index 24175e9bb..bfdb6a5b2 100644 --- a/program/steps/mail/bounce.inc +++ b/program/steps/mail/bounce.inc @@ -19,166 +19,6 @@ +-----------------------------------------------------------------------+ */ -/** - * Mail_mime wrapper to handle mail bounce - * - * @FIXME: For some reason this class definition - * cannot be put at the end of the file - */ -class rcmail_bounce_mail extends Mail_mime -{ - /** - * Constructor function - */ - public function __construct($params = array()) - { - // To make the code simpler always use delay_file_io=true - $params['delay_file_io'] = true; - $params['eol'] = "\r\n"; - - parent::__construct($params); - } - - /** - * Returns/Sets message headers - */ - public function headers($headers = array(), $overwrite = false, $skip_content = false) - { - // headers() wrapper that returns Resent-Cc, Resent-Bcc instead of Cc,Bcc - // it's also called to re-add Resent-Bcc after it has been sent (to store in Sent) - - if (array_key_exists('Bcc', $headers)) { - $this->build_params['bounce_headers']['Resent-Bcc'] = $headers['Bcc']; - } - - foreach ($this->build_params['bounce_headers'] as $key => $val) { - $headers[str_replace('Resent-', '', $key)] = $val; - } - - return $headers; - } - - /** - * Returns all message headers as string - */ - public function txtHeaders($headers = array(), $overwrite = false, $skip_content = false) - { - // i.e. add Resent-* headers on top of the original message head - $this->init_message(); - - $result = array(); - - foreach ($this->build_params['bounce_headers'] as $name => $value) { - $key = str_replace('Resent-', '', $name); - - // txtHeaders() can be used to unset Bcc header - if (array_key_exists($key, $headers)) { - $value = $headers[$key]; - $this->build_params['bounce_headers']['Resent-'.$key] = $value; - } - - if ($value) { - $result[] = "$name: $value"; - } - } - - $result = implode($this->build_params['eol'], $result); - - if (strlen($this->bounce_head)) { - $result .= $this->build_params['eol'] . $this->bounce_head; - } - - return $result; - } - - /** - * Save the message body to a file (if delay_file_io=true) - */ - public function saveMessageBody($file, $params = null) - { - $this->init_message(); - - // this will be called only once, so let just move the file - rename($this->bounce_body, $file); - - $this->bounce_head = null; - } - - protected function init_message() - { - if ($this->bounce_head !== null) { - return; - } - - $rcmail = rcmail::get_instance(); - $storage = $rcmail->get_storage(); - $message = $this->build_params['bounce_message']; - $temp_dir = unslashify($rcmail->config->get('temp_dir')); - $path = tempnam($temp_dir, 'rcmBounce'); - - // We'll write the body to the file and the headers to a variable - if ($fp = fopen($path, 'w')) { - stream_filter_register('bounce_source', 'rcmail_bounce_stream_filter'); - stream_filter_append($fp, 'bounce_source'); - - // message part - if ($message->context) { - $message->get_part_body($message->context, false, 0, $fp); - } - // complete message - else { - $storage->set_folder($message->folder); - $storage->get_raw_body($message->uid, $fp); - } - - fclose($fp); - - $this->bounce_head = rcmail_bounce_stream_filter::$headers; - $this->bounce_body = $path; - } - } -} - -/** - * Stream filter to remove message headers from the streamed - * message source (and store them in a variable) - */ -class rcmail_bounce_stream_filter extends php_user_filter -{ - public static $headers; - - protected $in_body = false; - - public function onCreate() - { - self::$headers = ''; - } - - public function filter($in, $out, &$consumed, $closing) - { - while ($bucket = stream_bucket_make_writeable($in)) { - if (!$this->in_body) { - self::$headers .= $bucket->data; - if (($pos = strpos(self::$headers, "\r\n\r\n")) === false) { - continue; - } - - $bucket->data = substr(self::$headers, $pos + 4); - $bucket->datalen = strlen($bucket->data); - - self::$headers = substr(self::$headers, 0, $pos); - $this->in_body = true; - } - - $consumed += $bucket->datalen; - stream_bucket_append($out, $bucket); - } - - return PSFS_PASS_ON; - } -} - - $msg_uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GP); $msg_folder = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GP, true); $MESSAGE = new rcube_message($msg_uid, $msg_folder); @@ -230,7 +70,7 @@ $headers = array_filter(array( )); // Create the bounce message -$BOUNCE = new rcmail_bounce_mail(array( +$BOUNCE = new rcmail_resend_mail(array( 'bounce_message' => $MESSAGE, 'bounce_headers' => $headers, ));