From 91790e41f3fa307658077043bc2fa5f71e270cf4 Mon Sep 17 00:00:00 2001 From: alecpl Date: Tue, 9 Feb 2010 13:10:12 +0000 Subject: - Fix attachment excessive memory use, support messages of any size (#1484660) --- CHANGELOG | 1 + INSTALL | 4 + program/include/rcube_imap.php | 20 +++- program/include/rcube_mail_mime.php | 190 ------------------------------------ program/include/rcube_smtp.php | 28 ++++-- program/lib/imap.inc | 20 +++- program/steps/mail/attachments.inc | 7 +- program/steps/mail/func.inc | 69 +++++++++---- program/steps/mail/sendmail.inc | 130 +++++++++++++++--------- 9 files changed, 196 insertions(+), 273 deletions(-) delete mode 100644 program/include/rcube_mail_mime.php diff --git a/CHANGELOG b/CHANGELOG index 8578fdc08..02cce9fd8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG RoundCube Webmail =========================== +- Fix attachment excessive memory use, support messages of any size (#1484660) - Fix setting task name according to auth state - Password: fix vpopmaild driver (#1486478) - Add workaround for MySQL bug [http://bugs.mysql.com/bug.php?id=46293] (#1486474) diff --git a/INSTALL b/INSTALL index 00fb083a6..b2156e528 100644 --- a/INSTALL +++ b/INSTALL @@ -15,6 +15,10 @@ REQUIREMENTS - PCRE, DOM, JSON, XML, Session, Sockets (required) - libiconv (recommended) - mbstring, fileinfo, mcrypt (optional) +* PEAR packages distributed with Roundcube or external: + - MDB2 2.5.0 or newer + - Mail_Mime 1.6.0 or newer + - Net_SMTP 1.4.1 or newer * php.ini options (see .htaccess file): - error_reporting E_ALL & ~E_NOTICE (or lower) - memory_limit>16MB (increase as suitable to support large attachments) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 6ab0b6a88..ecde6f958 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -1699,17 +1699,27 @@ class rcube_imap /** * Append a mail message (source) to a specific mailbox * - * @param string Target mailbox - * @param string Message source + * @param string Target mailbox + * @param string The message source string or filename + * @param string Headers string if $message contains only the body + * @param boolean True if $message is a filename + * * @return boolean True on success, False on error */ - function save_message($mbox_name, &$message) + function save_message($mbox_name, &$message, $headers='', $is_file=false) { $mailbox = $this->mod_mailbox($mbox_name); // make sure mailbox exists - if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes())) - $saved = iil_C_Append($this->conn, $mailbox, $message); + if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes())) { + if ($is_file) { + $separator = rcmail::get_instance()->config->header_delimiter(); + $saved = iil_C_AppendFromFile($this->conn, $mailbox, $message, + $headers, $separator.$separator); + } + else + $saved = iil_C_Append($this->conn, $mailbox, $message); + } if ($saved) { diff --git a/program/include/rcube_mail_mime.php b/program/include/rcube_mail_mime.php deleted file mode 100644 index 2176e6452..000000000 --- a/program/include/rcube_mail_mime.php +++ /dev/null @@ -1,190 +0,0 @@ - | - +-----------------------------------------------------------------------+ - - $Id$ - -*/ - - -/** - * Replacement PEAR:Mail_mime with some additional or overloaded methods - * - * @package Mail - */ -class rcube_mail_mime extends Mail_mime -{ - - protected $mime_content; - - /** - * Set build parameters - */ - function setParam($param) - { - if (is_array($param)) { - $this->_build_params = array_merge($this->_build_params, $param); - } - } - - /** - * Adds an image to the list of embedded images. - * - * @param string $file The image file name OR image data itself - * @param string $c_type The content type - * @param string $name The filename of the image. - * Only use if $file is the image data - * @param bool $isfilename Whether $file is a filename or not - * Defaults to true - * @param string $contentid Desired Content-ID of MIME part - * Defaults to generated unique ID - * @return mixed true on success or PEAR_Error object - * @access public - */ - function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $contentid = '') - { - $filedata = ($isfilename === true) ? $this->_file2str($file) : $file; - if ($isfilename === true) { - $filename = ($name == '' ? $file : $name); - } - else { - $filename = $name; - } - - if (PEAR::isError($filedata)) { - return $filedata; - } - - if ($contentid == '') { - $contentid = md5(uniqid(time())); - } - - $this->_html_images[] = array( - 'body' => $filedata, - 'name' => $filename, - 'c_type' => $c_type, - 'cid' => $contentid - ); - - return true; - } - - - /** - * returns the HTML body portion of the message - * @return string HTML body of the message - * @access public - */ - function getHTMLBody() - { - return $this->_htmlbody; - } - - - /** - * Encodes a header as per RFC2047 - * - * @param array $input The header data to encode - * @param array $params Extra build parameters - * @return array Encoded data - * @access private - * @override - */ - function _encodeHeaders($input, $params = array()) - { - $maxlen = 73; - $params += $this->_build_params; - - foreach ($input as $hdr_name => $hdr_value) - { - // if header contains e-mail addresses - if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) { - $chunks = rcube_explode_quoted_string(',', $hdr_value); - } - else { - $chunks = array($hdr_value); - } - - $hdr_value = ''; - $line_len = 0; - - foreach ($chunks as $i => $value) { - $value = trim($value); - - //This header contains non ASCII chars and should be encoded. - if (preg_match('/[\x80-\xFF]{1}/', $value)) { - $suffix = ''; - // Don't encode e-mail address - if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches)) { - $value = $matches[1]; - $suffix = ' '.$matches[2]; - } - - switch ($params['head_encoding']) { - case 'base64': - // Base64 encoding has been selected. - $mode = 'B'; - $encoded = base64_encode($value); - break; - - case 'quoted-printable': - default: - // quoted-printable encoding has been selected - $mode = 'Q'; - // replace ?, =, _ and spaces - $encoded = str_replace(array('=','_','?',' '), array('=3D','=5F','=3F','_'), $value); - $encoded = preg_replace('/([\x80-\xFF])/e', "'='.sprintf('%02X', ord('\\1'))", $encoded); - } - - $value = '=?' . $params['head_charset'] . '?' . $mode . '?' . $encoded . '?=' . $suffix; - } - - // add chunk to output string by regarding the header maxlen - $len = strlen($value); - if ($i == 0 || $line_len + $len < $maxlen) { - $hdr_value .= ($i>0?', ':'') . $value; - $line_len += $len + ($i>0?2:0); - } - else { - $hdr_value .= ($i>0?', ':'') . "\n " . $value; - $line_len = $len; - } - } - - $input[$hdr_name] = wordwrap($hdr_value, 990, "\n", true); // hard limit header length - } - - return $input; - } - - - /** - * Provides caching of body of constructed MIME Message to avoid - * duplicate construction of message and damage of MIME headers - * - * @return string The mime content - * @access public - * @override - */ - public function &get($build_params = null) - { - if(empty($this->mime_content)) - $this->mime_content = parent::get($build_params); - return $this->mime_content; - } - -} - diff --git a/program/include/rcube_smtp.php b/program/include/rcube_smtp.php index 92534688d..299126267 100644 --- a/program/include/rcube_smtp.php +++ b/program/include/rcube_smtp.php @@ -141,7 +141,8 @@ class rcube_smtp { * Either as an associative array or a finally * formatted string * - * @param string The full text of the message body, including any Mime parts, etc. + * @param mixed The full text of the message body, including any Mime parts + * or file handle * * @return bool Returns true on success, or false on error */ @@ -206,17 +207,24 @@ class rcube_smtp { } } - // Concatenate headers and body so it can be passed by reference to SMTP_CONN->data - // so preg_replace in SMTP_CONN->quotedata will store a reference instead of a copy. - // We are still forced to make another copy here for a couple ticks so we don't really - // get to save a copy in the method call. - $data = $text_headers . "\r\n" . $body; + if (is_resource($body)) + { + // file handle + $data = $body; + $text_headers = preg_replace('/[\r\n]+$/', '', $text_headers); + } else { + // Concatenate headers and body so it can be passed by reference to SMTP_CONN->data + // so preg_replace in SMTP_CONN->quotedata will store a reference instead of a copy. + // We are still forced to make another copy here for a couple ticks so we don't really + // get to save a copy in the method call. + $data = $text_headers . "\r\n" . $body; + + // unset old vars to save data and so we can pass into SMTP_CONN->data by reference. + unset($text_headers, $body); + } - // unset old vars to save data and so we can pass into SMTP_CONN->data by reference. - unset($text_headers, $body); - // Send the message's headers and the body as SMTP data. - if (PEAR::isError($result = $this->conn->data($data))) + if (PEAR::isError($result = $this->conn->data($data, $text_headers))) { $this->error = array('label' => 'smtperror', 'vars' => array('msg' => $result->getMessage())); $this->response[] .= "Failed to send data"; diff --git a/program/lib/imap.inc b/program/lib/imap.inc index 7607a1c71..ed30937fa 100644 --- a/program/lib/imap.inc +++ b/program/lib/imap.inc @@ -2418,7 +2418,7 @@ function iil_C_Append(&$conn, $folder, &$message) { return false; } -function iil_C_AppendFromFile(&$conn, $folder, $path) { +function iil_C_AppendFromFile(&$conn, $folder, $path, $headers=null, $separator="\n\n") { if (!$folder) { return false; } @@ -2438,7 +2438,12 @@ function iil_C_AppendFromFile(&$conn, $folder, $path) { if (!$len) { return false; } - + + if ($headers) { + $headers = preg_replace('/[\r\n]+$/', '', $headers); + $len += strlen($headers) + strlen($separator); + } + //send APPEND command $request = 'a APPEND "' . iil_Escape($folder) . '" (\\Seen) {' . $len . '}'; if (iil_PutLine($fp, $request)) { @@ -2450,16 +2455,21 @@ function iil_C_AppendFromFile(&$conn, $folder, $path) { return false; } - //send file + // send headers with body separator + if ($headers) { + iil_PutLine($fp, $headers . $separator, false); + } + + // send file while (!feof($in_fp)) { - $buffer = fgets($in_fp, 4096); + $buffer = fgets($in_fp, 4096); iil_PutLine($fp, $buffer, false); } fclose($in_fp); iil_PutLine($fp, ''); // \r\n - //read response + // read response do { $line = iil_ReadLine($fp); } while (!iil_StartsWith($line, 'a ', true)); diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc index d0808d080..2b4a59024 100644 --- a/program/steps/mail/attachments.inc +++ b/program/steps/mail/attachments.inc @@ -53,9 +53,11 @@ if ($RCMAIL->action=='display-attachment') $attachment = $RCMAIL->plugins->exec_hook('display_attachment', $attachment); if ($attachment['status']) { - $size = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']); + if (empty($attachment['size'])) + $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']); + header('Content-Type: ' . $attachment['mimetype']); - header('Content-Length: ' . $size); + header('Content-Length: ' . $attachment['size']); if ($attachment['data']) echo $attachment['data']; @@ -80,6 +82,7 @@ if (is_array($_FILES['_attachments']['tmp_name'])) { foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) { $attachment = array( 'path' => $filepath, + 'size' => $_FILES['_attachments']['size'][$i], 'name' => $_FILES['_attachments']['name'][$i], 'mimetype' => rc_mime_content_type($filepath, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]) ); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index dea85c2c5..73919d3aa 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -1332,13 +1332,20 @@ function rcmail_compose_cleanup() /** - * Send the given message compose object using the configured method + * Send the given message using the configured method + * + * @param object $message Reference to Mail_MIME object + * @param string $from Sender address string + * @param array $mailto Array of recipient address strings + * @param array $smtp_error SMTP error array (reference) + * @param string $body_file Location of file with saved message body (reference) + * + * @return boolean Send status. */ -function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error) +function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file) { global $CONFIG, $RCMAIL; - $msg_body = $message->get(); $headers = $message->headers(); // send thru SMTP server using custom SMTP library @@ -1357,14 +1364,36 @@ function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error) // here too, it because txtHeaders() below use $message->_headers not only $send_headers unset($message->_headers['Bcc']); + $smtp_headers = $message->txtHeaders($send_headers, true); + + if ($message->getParam('delay_file_io')) { + // use common temp dir + $temp_dir = $RCMAIL->config->get('temp_dir'); + $body_file = tempnam($temp_dir, 'rcmMsg'); + if (PEAR::isError($mime_result = $message->saveMessageBody($body_file))) { + raise_error(array('code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not create message: ".$mime_result->getMessage()), + TRUE, FALSE); + return false; + } + $msg_body = fopen($body_file, 'r'); + } else { + $msg_body = $message->get(); + } + // send message if (!is_object($RCMAIL->smtp)) $RCMAIL->smtp_init(true); - $sent = $RCMAIL->smtp->send_mail($from, $a_recipients, ($foo = $message->txtHeaders($send_headers, true)), $msg_body); + $sent = $RCMAIL->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body); $smtp_response = $RCMAIL->smtp->get_response(); $smtp_error = $RCMAIL->smtp->get_error(); + if (is_resource($msg_body)) { + fclose($msg_body); + } + // log error if (!$sent) raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, @@ -1387,8 +1416,15 @@ function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error) $headers_enc['To'] = implode(', ', $m[1]); } } - - if (ini_get('safe_mode')) + + $msg_body = $message->get(); + + if (PEAR::isError($msg_body)) + raise_error(array('code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not create message: ".$msg_body->getMessage()), + TRUE, FALSE); + else if (ini_get('safe_mode')) $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str); else $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from"); @@ -1408,7 +1444,7 @@ function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error) !empty($smtp_response) ? join('; ', $smtp_response) : '')); } } - + $message->_headers = array(); $message->headers($headers); @@ -1430,15 +1466,14 @@ function rcmail_send_mdn($uid, &$smtp_error) $recipient = array_shift($IMAP->decode_address_list($message->headers->mdn_to)); $mailto = $recipient['mailto']; - $compose = new rcube_mail_mime($RCMAIL->config->header_delimiter()); - $compose->setParam(array( - 'text_encoding' => 'quoted-printable', - 'html_encoding' => 'quoted-printable', - 'head_encoding' => 'quoted-printable', - 'head_charset' => RCMAIL_CHARSET, - 'html_charset' => RCMAIL_CHARSET, - 'text_charset' => RCMAIL_CHARSET, - )); + $compose = new Mail_mime($RCMAIL->config->header_delimiter()); + + $compose->setParam('text_encoding', 'quoted-printable'); + $compose->setParam('html_encoding', 'quoted-printable'); + $compose->setParam('head_encoding', 'quoted-printable'); + $compose->setParam('head_charset', RCMAIL_CHARSET); + $compose->setParam('html_charset', RCMAIL_CHARSET); + $compose->setParam('text_charset', RCMAIL_CHARSET); // compose headers array $headers = array( @@ -1474,7 +1509,7 @@ function rcmail_send_mdn($uid, &$smtp_error) $compose->setTXTBody(rc_wordwrap($body, 75, "\r\n")); $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline'); - $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error); + $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file); if ($sent) { diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 724feb80c..13c162d96 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -20,7 +20,6 @@ */ - // remove all scripts and act as called in frame $OUTPUT->reset(); $OUTPUT->framed = TRUE; @@ -111,7 +110,7 @@ function rcmail_attach_emoticons(&$mime_message) { global $CONFIG; - $body = $mime_message->getHtmlBody(); + $body = $mime_message->getHTMLBody(); // remove any null-byte characters before parsing $body = preg_replace('/\x00/', '', $body); @@ -134,7 +133,7 @@ function rcmail_attach_emoticons(&$mime_message) if (! in_array($image_name, $included_images)) { // add the image to the MIME message - if(! $mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name)) + if (! $mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name)) $OUTPUT->show_message("emoticonerror", 'error'); array_push($included_images, $image_name); } @@ -360,8 +359,26 @@ if (!$savedraft) { // set line length for body wrapping $LINE_LENGTH = $RCMAIL->config->get('line_length', 75); -// create extended PEAR::Mail_mime instance -$MAIL_MIME = new rcube_mail_mime($RCMAIL->config->header_delimiter()); +// Since we can handle big messages with disk usage, we need more time to work +@set_time_limit(0); + +// create PEAR::Mail_mime instance +$MAIL_MIME = new Mail_mime($RCMAIL->config->header_delimiter()); + +// Check if we have enough memory to handle the message in it +// It's faster than using files, so we'll do this if we only can +if (is_array($_SESSION['compose']['attachments']) && $CONFIG['smtp_server'] + && ($mem_limit = parse_bytes(ini_get('memory_limit')))) +{ + $memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB + + foreach ($_SESSION['compose']['attachments'] as $id => $attachment) + $memory += $attachment['size']; + + // Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64 + if ($memory * 1.33 * 12 > $mem_limit) + $MAIL_MIME->setParam('delay_file_io', true); +} // For HTML-formatted messages, construct the MIME message with both // the HTML part and the plain-text part @@ -403,7 +420,8 @@ $charset_7bit = array('ASCII', 'ISO-2022-JP', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8 $transfer_encoding = in_array(strtoupper($message_charset), $charset_7bit) ? '7bit' : '8bit'; // add stored attachments, if any -if (is_array($_SESSION['compose']['attachments'])) { +if (is_array($_SESSION['compose']['attachments'])) +{ foreach ($_SESSION['compose']['attachments'] as $id => $attachment) { // This hook retrieves the attachment contents from the file storage backend $attachment = $RCMAIL->plugins->exec_hook('get_attachment', $attachment); @@ -438,30 +456,13 @@ if (is_array($_SESSION['compose']['attachments'])) { } } -// add submitted attachments -if (is_array($_FILES['_attachments']['tmp_name'])) { - foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) { - $ctype = $files['type'][$i]; - $ctype = str_replace('image/pjpeg', 'image/jpeg', $ctype); // #1484914 - - $MAIL_MIME->addAttachment($filepath, $ctype, $files['name'][$i], true, - $ctype == 'message/rfc822' ? $transfer_encoding : 'base64', - 'attachment', $message_charset, '', '', - $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, - $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL - ); - } -} - // encoding settings for mail composing -$MAIL_MIME->setParam(array( - 'text_encoding' => $transfer_encoding, - 'html_encoding' => 'quoted-printable', - 'head_encoding' => 'quoted-printable', - 'head_charset' => $message_charset, - 'html_charset' => $message_charset, - 'text_charset' => $message_charset, -)); +$MAIL_MIME->setParam('text_encoding', $transfer_encoding); +$MAIL_MIME->setParam('html_encoding', 'quoted-printable'); +$MAIL_MIME->setParam('head_encoding', 'quoted-printable'); +$MAIL_MIME->setParam('head_charset', $message_charset); +$MAIL_MIME->setParam('html_charset', $message_charset); +$MAIL_MIME->setParam('text_charset', $message_charset); $data = $RCMAIL->plugins->exec_hook('outgoing_message_headers', array('headers' => $headers)); $headers = $data['headers']; @@ -487,11 +488,16 @@ if (!$savedraft) $OUTPUT->send('iframe'); } - $sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto, $smtp_error); - + $sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto, $smtp_error, $mailbody_file); + // return to compose page if sending failed if (!$sent) { + // remove temp file + if ($mailbody_file) { + unlink($mailbody_file); + } + if ($smtp_error) $OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']); else @@ -512,7 +518,6 @@ if (!$savedraft) } // End of SMTP Delivery Block - // Determine which folder to save message if ($savedraft) $store_target = $CONFIG['drafts_mbox']; @@ -522,31 +527,63 @@ else if ($store_target) { // check if mailbox exists - if (!in_array_nocase($store_target, $IMAP->list_mailboxes())) + if (!in_array($store_target, $IMAP->list_mailboxes())) { // folder may be existing but not subscribed (#1485241) - if (!in_array_nocase($store_target, $IMAP->list_unsubscribed())) + if (!in_array($store_target, $IMAP->list_unsubscribed())) $store_folder = $IMAP->create_mailbox($store_target, TRUE); else if ($IMAP->subscribe($store_target)) $store_folder = TRUE; } else $store_folder = TRUE; - + // append message to sent box - if ($store_folder) - $saved = $IMAP->save_message($store_target, $MAIL_MIME->getMessage()); + if ($store_folder) { - // raise error if saving failed - if (!$saved) - { - raise_error(array('code' => 800, 'type' => 'imap', + // message body in file + if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) { + $headers = $MAIL_MIME->txtHeaders(); + + // file already created + if ($mailbody_file) + $msg = $mailbody_file; + else { + $temp_dir = $RCMAIL->config->get('temp_dir'); + $mailbody_file = tempnam($temp_dir, 'rcmMsg'); + if (!PEAR::isError($msg = $MAIL_MIME->saveMessageBody($mailbody_file))) + $msg = $mailbody_file; + } + } + else { + $msg = $MAIL_MIME->getMessage(); + $headers = ''; + } + + if (PEAR::isError($msg)) + raise_error(array('code' => 600, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Could not create message: ".$msg->getMessage()), + TRUE, FALSE); + else { + $saved = $IMAP->save_message($store_target, $msg, $headers, $mailbody_file ? true : false); + } + + if ($mailbody_file) { + unlink($mailbody_file); + $mailbody_file = null; + } + + // raise error if saving failed + if (!$saved) { + raise_error(array('code' => 800, 'type' => 'imap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not save message in $store_target"), TRUE, FALSE); - if ($savedraft) { - $OUTPUT->show_message('errorsaving', 'error'); - $OUTPUT->send('iframe'); + if ($savedraft) { + $OUTPUT->show_message('errorsaving', 'error'); + $OUTPUT->send('iframe'); + } } } @@ -564,6 +601,11 @@ if ($store_target) 'message' => "Could not delete message from ".$CONFIG['drafts_mbox']), TRUE, FALSE); } } +// remove temp file +else if ($mailbody_file) { + unlink($mailbody_file); + } + if ($savedraft) { -- cgit v1.2.3