diff --git a/product/ERP5Type/patches/python.py b/product/ERP5Type/patches/python.py
index d86ce91d69612fb3cfb45688a95af79e7d8c2cb8..e18e9c1a5faf165fa723baee3eb4599c05d3eada 100644
--- a/product/ERP5Type/patches/python.py
+++ b/product/ERP5Type/patches/python.py
@@ -113,6 +113,62 @@ if sys.version_info < (2, 7):
   collections.OrderedDict = OrderedDict
 
 
+if 1:
+    # Speed up email parsing (see also http://bugs.python.org/issue1243730)
+    from email import Parser as parser, FeedParser as feedparser # BBB
+
+    NLCRE_crack_split = feedparser.NLCRE_crack.split
+    def push(self, data):
+        """Push some new data into this object."""
+        # <patch>
+        if self._partial[-1:] == '\r':
+            parts = NLCRE_crack_split('\r' + data)
+            parts[0] = self._partial[:-1]
+        else:
+            parts = NLCRE_crack_split(data)
+            parts[0] = self._partial + parts[0]
+        # </patch>
+        # The *ahem* interesting behaviour of re.split when supplied grouping
+        # parentheses is that the last element of the resulting list is the
+        # data after the final RE.  In the case of a NL/CR terminated string,
+        # this is the empty string.
+        self._partial = parts.pop()
+        #GAN 29Mar09  bugs 1555570, 1721862  Confusion at 8K boundary ending with \r:
+        # is there a \n to follow later?
+        if not self._partial and parts and parts[-1].endswith('\r'):
+            self._partial = parts.pop(-2)+parts.pop()
+        # parts is a list of strings, alternating between the line contents
+        # and the eol character(s).  Gather up a list of lines after
+        # re-attaching the newlines.
+        lines = []
+        for i in range(len(parts) // 2):
+            lines.append(parts[i*2] + parts[i*2+1])
+        self.pushlines(lines)
+    feedparser.BufferedSubFile.push = push
+
+    FeedParser = feedparser.FeedParser
+    def parse(self, fp, headersonly=False):
+        """Create a message structure from the data in a file.
+
+        Reads all the data from the file and returns the root of the message
+        structure.  Optional headersonly is a flag specifying whether to stop
+        parsing after reading the headers or not.  The default is False,
+        meaning it parses the entire contents of the file.
+        """
+        feedparser = FeedParser(self._class)
+        if headersonly:
+            feedparser._set_headersonly()
+        while True:
+            # <patch>
+            data = fp.read(65536)
+            # </patch>
+            if not data:
+                break
+            feedparser.feed(data)
+        return feedparser.close()
+    parser.Parser.parse = parse
+
+
 # Workaround bad use of getcwd() in docutils.
 # Required by PortalTransforms.transforms.rest
 from docutils import utils