Error proof IMAP.APPEND against dropped connections
Make sure that when a connection is dropped during append, we really discard the broken connection and get a new one, retrying. We retry indefinitely on the specific abort() Exception, as this is what imaplib2 suggests us to do. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
		 Sebastian Spaeth
					Sebastian Spaeth
				
			
				
					committed by
					
						 Nicolas Sebrecht
						Nicolas Sebrecht
					
				
			
			
				
	
			
			
			 Nicolas Sebrecht
						Nicolas Sebrecht
					
				
			
						parent
						
							9c678c9d6b
						
					
				
				
					commit
					2cf6155282
				
			| @@ -21,6 +21,7 @@ import random | |||||||
| import binascii | import binascii | ||||||
| import re | import re | ||||||
| import time | import time | ||||||
|  | from sys import exc_info | ||||||
| from copy import copy | from copy import copy | ||||||
| from Base import BaseFolder | from Base import BaseFolder | ||||||
| from offlineimap import imaputil, imaplibutil, OfflineImapError | from offlineimap import imaputil, imaplibutil, OfflineImapError | ||||||
| @@ -500,45 +501,54 @@ class IMAPFolder(BaseFolder): | |||||||
|             self.savemessageflags(uid, flags) |             self.savemessageflags(uid, flags) | ||||||
|             return uid |             return uid | ||||||
|  |  | ||||||
|         try: |  | ||||||
|         imapobj = self.imapserver.acquireconnection() |         imapobj = self.imapserver.acquireconnection() | ||||||
|  |         try: | ||||||
|  |             success = False # succeeded in APPENDING? | ||||||
|  |             while not success: | ||||||
|  |  | ||||||
|  |                 # UIDPLUS extension provides us with an APPENDUID response. | ||||||
|  |                 use_uidplus = 'UIDPLUS' in imapobj.capabilities | ||||||
|  |  | ||||||
|  |                 # get the date of the message, so we can pass it to the server. | ||||||
|  |                 date = self.getmessageinternaldate(content, rtime) | ||||||
|  |                 content = re.sub("(?<!\r)\n", "\r\n", content) | ||||||
|  |  | ||||||
|  |                 if not use_uidplus: | ||||||
|  |                     # insert a random unique header that we can fetch later | ||||||
|  |                     (headername, headervalue) = self.generate_randomheader( | ||||||
|  |                                                     content) | ||||||
|  |                     self.ui.debug('imap', 'savemessage: header is: %s: %s' %\ | ||||||
|  |                                       (headername, headervalue)) | ||||||
|  |                     content = self.savemessage_addheader(content, headername, | ||||||
|  |                                                          headervalue)     | ||||||
|  |                 if len(content)>200: | ||||||
|  |                     dbg_output = "%s...%s" % (content[:150], content[-50:]) | ||||||
|  |                 else: | ||||||
|  |                     dbg_output = content | ||||||
|  |                 self.ui.debug('imap', "savemessage: date: %s, content: '%s'" % | ||||||
|  |                              (date, dbg_output)) | ||||||
|  |  | ||||||
|                 try: |                 try: | ||||||
|                 imapobj.select(self.getfullname()) # Needed for search and making the box READ-WRITE |                     # Select folder for append and make the box READ-WRITE | ||||||
|  |                     imapobj.select(self.getfullname()) | ||||||
|                 except imapobj.readonly: |                 except imapobj.readonly: | ||||||
|                     # readonly exception. Return original uid to notify that |                     # readonly exception. Return original uid to notify that | ||||||
|                     # we did not save the message. (see savemessage in Base.py) |                     # we did not save the message. (see savemessage in Base.py) | ||||||
|                     self.ui.msgtoreadonly(self, uid, content, flags) |                     self.ui.msgtoreadonly(self, uid, content, flags) | ||||||
|                     return uid |                     return uid | ||||||
|  |  | ||||||
|             # UIDPLUS extension provides us with an APPENDUID response to our append() |  | ||||||
|             use_uidplus = 'UIDPLUS' in imapobj.capabilities |  | ||||||
|  |  | ||||||
|             # get the date of the message file, so we can pass it to the server. |  | ||||||
|             date = self.getmessageinternaldate(content, rtime) |  | ||||||
|             content = re.sub("(?<!\r)\n", "\r\n", content) |  | ||||||
|  |  | ||||||
|             if not use_uidplus: |  | ||||||
|                 # insert a random unique header that we can fetch later |  | ||||||
|                 (headername, headervalue) = self.generate_randomheader(content) |  | ||||||
|                 self.ui.debug('imap', 'savemessage: new header is: %s: %s' % \ |  | ||||||
|                              (headername, headervalue)) |  | ||||||
|                 content = self.savemessage_addheader(content, headername, |  | ||||||
|                                                      headervalue)     |  | ||||||
|             if len(content)>200: |  | ||||||
|                 dbg_output = "%s...%s" % (content[:150], |  | ||||||
|                                           content[-50:]) |  | ||||||
|             else: |  | ||||||
|                 dbg_output = content |  | ||||||
|             self.ui.debug('imap', "savemessage: date: %s, content: '%s'" % |  | ||||||
|                           (date, dbg_output)) |  | ||||||
|  |  | ||||||
|                 #Do the APPEND |                 #Do the APPEND | ||||||
|                 try: |                 try: | ||||||
|                     (typ, dat) = imapobj.append(self.getfullname(), |                     (typ, dat) = imapobj.append(self.getfullname(), | ||||||
|                                        imaputil.flagsmaildir2imap(flags), |                                        imaputil.flagsmaildir2imap(flags), | ||||||
|                                        date, content) |                                        date, content) | ||||||
|             except Exception, e: |                     success = True | ||||||
|  |                 except imapobj.abort, e: | ||||||
|  |                     # connection has been reset, release connection and retry. | ||||||
|  |                     self.ui.error(e, exc_info()[2]) | ||||||
|  |                     self.imapserver.releaseconnection(imapobj, True) | ||||||
|  |                     imapobj = self.imapserver.acquireconnection() | ||||||
|  |                 except imapobj.error, e: | ||||||
|                     # If the server responds with 'BAD', append() raise()s directly. |                     # If the server responds with 'BAD', append() raise()s directly. | ||||||
|                     # So we need to prepare a response ourselves. |                     # So we need to prepare a response ourselves. | ||||||
|                     typ, dat = 'BAD', str(e) |                     typ, dat = 'BAD', str(e) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user