#9390: linebreaks missing when replying mail via Android
authorPhilipp Schüle <p.schuele@metaways.de>
Wed, 26 Feb 2014 15:45:19 +0000 (16:45 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 26 Feb 2014 16:19:52 +0000 (17:19 +0100)
- moves convertFromTextToHTML to Tinebase_Mail
- converts plain/text body to html when
  * appending reply/forward body to mail sent via ActiveSync
  * purifier removes to much and we return plain/text part instead
- adds gitignore for other Felamimail test files

https://forge.tine20.org/mantisbt/view.php?id=9390

Change-Id: Id6da95d65a36739d8f82f4b8c63c308c15cb81ba
Reviewed-on: http://gerrit.tine20.com/customers/365
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/ActiveSync/Controller/EmailTests.php
tests/tine20/Felamimail/Controller/MessageTest.php
tests/tine20/Felamimail/Model/MessageTest.php
tests/tine20/Felamimail/files/other/.gitignore [new file with mode: 0644]
tine20/Felamimail/Controller/Message.php
tine20/Felamimail/Frontend/Json.php
tine20/Felamimail/Message.php
tine20/Felamimail/Model/Message.php
tine20/Felamimail/js/GridDetailsPanel.js
tine20/Tinebase/Mail.php

index 1c6722e..4305626 100644 (file)
@@ -4,7 +4,7 @@
  * 
  * @package     ActiveSync
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2010-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2010-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
@@ -420,6 +420,7 @@ dGVzdAo=&#13;
      * reply email test
      * 
      * @see 0007512: SmartReply with HTML message fails
+     * @see 0009390: linebreaks missing when replying or forwarding mail
      */
     public function testReplyEmail()
     {
@@ -440,8 +441,8 @@ dGVzdAo=&#13;
         $this->assertEquals("Re: [gentoo-dev] `paludis --info' is not like `emerge --info'", $message->subject);
         $completeMessage = Felamimail_Controller_Message::getInstance()->getCompleteMessage($message);
         $this->assertContains('Sebastian
-The attached list notes all of the packages that were added or removed
-from the tree, for the week ending 2009-04-12 23h59 UTC.', $completeMessage->body, 'reply body has not been appended correctly');
+The attached list notes all of the packages that were added or removed<br />from the tree, for the week ending 2009-04-12 23h59 UTC.<br />', $completeMessage->body,
+            'reply body has not been appended correctly');
     }
     
     /**
index 469b733..5c66107 100644 (file)
@@ -606,7 +606,7 @@ class Felamimail_Controller_MessageTest extends PHPUnit_Framework_TestCase
         if (file_exists($otherFilesDir)) {
             foreach (new DirectoryIterator($otherFilesDir) as $item) {
                 $filename = $item->getFileName();
-                if ($item->isFile() && $filename !== 'README') {
+                if ($item->isFile() && preg_match('/eml$/i', $filename)) {
                     $fileName = 'other/' . $filename;
                     echo "\nchecking message: " . $fileName . "\n";
                     $cachedMessage = $this->messageTestHelper($fileName, $filename);
index 814863f..4c015ee 100644 (file)
@@ -96,7 +96,7 @@ class Felamimail_Model_MessageTest extends PHPUnit_Framework_TestCase
             "> jojo\n" .
             "jojo\n" ;
         
-        $result = Felamimail_Message::convertFromTextToHTML($plaintextMessage);
+        $result = Tinebase_Mail::convertFromTextToHTML($plaintextMessage, 'felamimail-body-blockquote');
         
         $this->assertEquals('blabla<br /><blockquote class="felamimail-body-blockquote">lalülüüla<br /><br />'
             . '<blockquote class="felamimail-body-blockquote"><blockquote class="felamimail-body-blockquote">lala<br />'
diff --git a/tests/tine20/Felamimail/files/other/.gitignore b/tests/tine20/Felamimail/files/other/.gitignore
new file mode 100644 (file)
index 0000000..5a4dc33
--- /dev/null
@@ -0,0 +1 @@
+*.eml
index a41631c..4ad71ae 100644 (file)
@@ -200,8 +200,8 @@ class Felamimail_Controller_Message extends Tinebase_Controller_Record_Abstract
     protected function _getCompleteMessageContent(Felamimail_Model_Message $_message, Felamimail_Model_Account $_account, $_partId = NULL)
     {
         $mimeType = ($_account->display_format == Felamimail_Model_Account::DISPLAY_HTML || $_account->display_format == Felamimail_Model_Account::DISPLAY_CONTENT_TYPE)
-        ? Zend_Mime::TYPE_HTML
-        : Zend_Mime::TYPE_TEXT;
+            ? Zend_Mime::TYPE_HTML
+            : Zend_Mime::TYPE_TEXT;
         
         $headers     = $this->getMessageHeaders($_message, $_partId, true);
         $body        = $this->getMessageBody($_message, $_partId, $mimeType, $_account, true);
@@ -616,7 +616,8 @@ class Felamimail_Controller_Message extends Tinebase_Controller_Record_Abstract
                 if ($_message->text_partid && $bodyCharCountAfter < $bodyCharCountBefore / 10) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
                         . ' Purify may have removed (more than 9/10) too many chars, using alternative text message part.');
-                    return $this->_getAndDecodeMessageBody($_message, $_message->text_partid , Zend_Mime::TYPE_TEXT, $_account);
+                    $result = $this->_getAndDecodeMessageBody($_message, $_message->text_partid , Zend_Mime::TYPE_TEXT, $_account);
+                    return Felamimail_Message::convertContentType(Zend_Mime::TYPE_TEXT, Zend_Mime::TYPE_HTML, $result);
                 }
             }
             
index a930890..56ab8c7 100644 (file)
@@ -358,7 +358,7 @@ class Felamimail_Frontend_Json extends Tinebase_Frontend_Json_Abstract
             
         } else if ($_record instanceof Felamimail_Model_Sieve_Vacation) {
             if (! $_record->mime) {
-                $_record->reason = Felamimail_Message::convertFromTextToHTML($_record->reason);
+                $_record->reason = Tinebase_Mail::convertFromTextToHTML($_record->reason, 'felamimail-body-blockquote');
             }
         }
         
@@ -555,7 +555,7 @@ class Felamimail_Frontend_Json extends Tinebase_Frontend_Json_Abstract
         $record->setFromJsonInUsersTimezone($vacationData);
         
         $message = Felamimail_Controller_Sieve::getInstance()->getVacationMessage($record);
-        $htmlMessage = Felamimail_Message::convertFromTextToHTML($message);
+        $htmlMessage = Tinebase_Mail::convertFromTextToHTML($message, 'felamimail-body-blockquote');
         
         return array(
             'message' => $htmlMessage
index 31f87e0..9aeee9e 100644 (file)
@@ -160,7 +160,7 @@ class Felamimail_Message extends Zend_Mail_Message
         }
         
         if ($_from == Zend_Mime::TYPE_TEXT && $_to == Zend_Mime::TYPE_HTML) {
-            $text = self::convertFromTextToHTML($_text);
+            $text = Tinebase_Mail::convertFromTextToHTML($_text, 'felamimail-body-blockquote');
             $text = self::addHtmlMarkup($text);
         } else {
             $text = self::convertFromHTMLToText($_text);
@@ -170,56 +170,6 @@ class Felamimail_Message extends Zend_Mail_Message
     }
     
     /**
-     * convert text to html
-     * - replace quotes ('>  ') with blockquotes 
-     * - does htmlspecialchars()
-     * - converts linebreaks to <br />
-     * 
-     * @param string $_text
-     * @return string
-     */
-    public static function convertFromTextToHTML($_text)
-    {
-        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Input: ' . $_text);
-        
-        $lines = preg_split('/\r\n|\n|\r/', $_text);
-        $result = array();
-        $indention = 0;
-        foreach ($lines as $line) {
-            // get indention level and remove quotes
-            if (preg_match('/^>[> ]*/', $line, $matches)) {
-                $indentionLevel = substr_count($matches[0], '>');
-                $line = str_replace($matches[0], '', $line);
-            } else {
-                $indentionLevel = 0;
-            }
-            
-            // convert html special chars
-            $line = htmlspecialchars($line, ENT_COMPAT, 'UTF-8');
-            
-            // set blockquote tags for current indentionLevel
-            while ($indention < $indentionLevel) {
-                $line = '<blockquote class="felamimail-body-blockquote">' . $line;
-                $indention++;
-            }
-            while ($indention > $indentionLevel) {
-                $line = '</blockquote>' . $line;
-                $indention--;
-            }
-            
-            $result[] = $line;
-            
-            if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Line: ' . $line);
-        }
-        
-        $result = implode('<br />', $result);
-        
-        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Result: ' . $result);
-        
-        return $result;
-    }
-    
-    /**
      * convert html to text
      * 
      * @param string $_html
index b22d221..fed5375 100644 (file)
@@ -277,7 +277,7 @@ class Felamimail_Model_Message extends Tinebase_Record_Abstract
                                      $translate->_('Received on')  . ' ' . $this->received . "\n" .
                                      $translate->_('Was read by:') . ' ' . $from->from .  ' <' . $from->email .'> ' .
                                      $translate->_('on') . ' ' . (date('Y-m-d H:i:s'));
-            $message->body         = Felamimail_Message::convertFromTextToHTML($message->body);
+            $message->body         = Tinebase_Mail::convertFromTextToHTML($message->body, 'felamimail-body-blockquote');
             Felamimail_Controller_Message_Send::getInstance()->sendMessage($message);
         }
     }
index cb42921..5ae2bbe 100644 (file)
@@ -312,7 +312,7 @@ Ext.ns('Tine.Felamimail');
                             // sometimes the height is negative, fix this here
                             height = 500;
                         }
-                            
+                        
                         body = '<textarea ' +
                             'style="width: ' + width + 'px; height: ' + height + 'px; " ' +
                             'autocomplete="off" id="' + id + '" name="body" class="x-form-textarea x-form-field x-ux-display-background-border" readonly="" >' +
index 0fe1c58..e51a5da 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Mail
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2008-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2008-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
@@ -118,7 +118,7 @@ class Tinebase_Mail extends Zend_Mail
      * appends old body to mime part
      * 
      * @param Zend_Mime_Part $mp
-     * @param string $replyBody
+     * @param string $replyBody plain/text reply body
      * @return Zend_Mime_Part
      */
     protected static function _appendReplyBody(Zend_Mime_Part $mp, $replyBody)
@@ -131,6 +131,12 @@ class Tinebase_Mail extends Zend_Mail
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " reply body: " . $replyBody);
         }
         
+        if ($type === Zend_Mime::TYPE_HTML && /* checks if $replyBody does not contains tags */ $replyBody === strip_tags($replyBody)) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
+                . " Converting plain/text reply body to HTML");
+            $replyBody = self::convertFromTextToHTML($replyBody);
+        }
+        
         if ($type === Zend_Mime::TYPE_HTML && preg_match('/(<\/body>[\s\r\n]*<\/html>)/i', $decodedContent, $matches)) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
                 . ' Appending reply body to html body.');
@@ -527,4 +533,56 @@ class Tinebase_Mail extends Zend_Mail
 
         return $addresses;
     }
+
+    /**
+     * convert text to html
+     * - replace quotes ('>  ') with blockquotes 
+     * - does htmlspecialchars()
+     * - converts linebreaks to <br />
+     * 
+     * @param string $text
+     * @param string $blockquoteClass
+     * @return string
+     */
+    public static function convertFromTextToHTML($text, $blockquoteClass = null)
+    {
+        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Input: ' . $text);
+        
+        $lines = preg_split('/\r\n|\n|\r/', $text);
+        $result = array();
+        $indention = 0;
+        foreach ($lines as $line) {
+            // get indention level and remove quotes
+            if (preg_match('/^>[> ]*/', $line, $matches)) {
+                $indentionLevel = substr_count($matches[0], '>');
+                $line = str_replace($matches[0], '', $line);
+            } else {
+                $indentionLevel = 0;
+            }
+            
+            // convert html special chars
+            $line = htmlspecialchars($line, ENT_COMPAT, 'UTF-8');
+            
+            // set blockquote tags for current indentionLevel
+            while ($indention < $indentionLevel) {
+                $class = $blockquoteClass ? 'class="' . $blockquoteClass . '"' : '';
+                $line = '<blockquote ' . $class . '>' . $line;
+                $indention++;
+            }
+            while ($indention > $indentionLevel) {
+                $line = '</blockquote>' . $line;
+                $indention--;
+            }
+            
+            $result[] = $line;
+            
+            if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Line: ' . $line);
+        }
+        
+        $result = implode('<br />', $result);
+        
+        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Result: ' . $result);
+        
+        return $result;
+    }
 }