SF patch #462628 (Travers Naran) NNTPLib supports saving BODY to a file.

  I modified nntplib so the body method can accept an
  optional second parameter pointing to a filehandle or
  filename (string). This way, really long body
  articles can be stored to disk instead of kept in
  memory. The way I made the modification should make
  it easy to extend this functionality to other extended
  return methods.
diff --git a/Lib/nntplib.py b/Lib/nntplib.py
index d97813f..d5bc902 100644
--- a/Lib/nntplib.py
+++ b/Lib/nntplib.py
@@ -31,6 +31,7 @@
 # Imports
 import re
 import socket
+import types
 
 __all__ = ["NNTP","NNTPReplyError","NNTPTemporaryError",
            "NNTPPermanentError","NNTPProtocolError","NNTPDataError",
@@ -210,20 +211,35 @@
             raise NNTPProtocolError(resp)
         return resp
 
-    def getlongresp(self):
+    def getlongresp(self,fileHandle=None):
         """Internal: get a response plus following text from the server.
         Raise various errors if the response indicates an error."""
-        resp = self.getresp()
-        if resp[:3] not in LONGRESP:
-            raise NNTPReplyError(resp)
-        list = []
-        while 1:
-            line = self.getline()
-            if line == '.':
-                break
-            if line[:2] == '..':
-                line = line[1:]
-            list.append(line)
+
+        openedFile = None
+        try:
+            # If a string was passed then open a file with that name
+            if isinstance(fileHandle, types.StringType):
+                openedFile = fileHandle = open(fileHandle, "w")
+
+            resp = self.getresp()
+            if resp[:3] not in LONGRESP:
+                raise NNTPReplyError(resp)
+            list = []
+            while 1:
+                line = self.getline()
+                if line == '.':
+                    break
+                if line[:2] == '..':
+                    line = line[1:]
+                if fileHandle:
+                    fileHandle.write(line + "\n")
+                else:
+                    list.append(line)
+        finally:
+            # If this method created the file, then it must close it
+            if openedFile:
+                openedFile.close()
+
         return resp, list
 
     def shortcmd(self, line):
@@ -231,10 +247,10 @@
         self.putcmd(line)
         return self.getresp()
 
-    def longcmd(self, line):
+    def longcmd(self, line, fileHandle=None):
         """Internal: send a command and get the response plus following text."""
         self.putcmd(line)
-        return self.getlongresp()
+        return self.getlongresp(fileHandle)
 
     def newgroups(self, date, time):
         """Process a NEWGROUPS command.  Arguments:
@@ -339,9 +355,9 @@
         """Process a LAST command.  No arguments.  Return as for STAT."""
         return self.statcmd('LAST')
 
-    def artcmd(self, line):
+    def artcmd(self, line, fileHandle=None):
         """Internal: process a HEAD, BODY or ARTICLE command."""
-        resp, list = self.longcmd(line)
+        resp, list = self.longcmd(line,fileHandle)
         resp, nr, id = self.statparse(resp)
         return resp, nr, id, list
 
@@ -356,16 +372,18 @@
 
         return self.artcmd('HEAD ' + id)
 
-    def body(self, id):
+    def body(self, id, fileHandle=None):
         """Process a BODY command.  Argument:
         - id: article number or message id
+        - fileHandle: Filename string or file object to store the article in
         Returns:
         - resp: server response if successful
         - nr: article number
         - id: message id
-        - list: the lines of the article's body"""
+        - list: the lines of the article's body or an empty list
+                if fileHandle was used"""
 
-        return self.artcmd('BODY ' + id)
+        return self.artcmd('BODY ' + id, fileHandle)
 
     def article(self, id):
         """Process an ARTICLE command.  Argument: