Add ability to trim some local mail headers
When filterheaders is set to a comma-separated list of headers, OfflineIMAP removes those headers from messages before uploading them to the server. Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
This commit is contained in:
parent
844ca6b08c
commit
5391476dfb
@ -10,6 +10,8 @@ OfflineIMAP v6.5.6 (YYYY-MM-DD)
|
|||||||
|
|
||||||
* Add knob to invoke folderfilter dynamically on each sync (GitHub#73)
|
* Add knob to invoke folderfilter dynamically on each sync (GitHub#73)
|
||||||
* Add knob to apply compression to IMAP connections (Abdó Roig-Maranges)
|
* Add knob to apply compression to IMAP connections (Abdó Roig-Maranges)
|
||||||
|
* Add knob to filter some headers before uploading message
|
||||||
|
to IMAP server (Abdó Roig-Maranges)
|
||||||
|
|
||||||
|
|
||||||
OfflineIMAP v6.5.5 (2013-10-07)
|
OfflineIMAP v6.5.5 (2013-10-07)
|
||||||
|
@ -272,6 +272,17 @@ remoterepository = RemoteExample
|
|||||||
#maildir-windows-compatible = no
|
#maildir-windows-compatible = no
|
||||||
|
|
||||||
|
|
||||||
|
# OfflineIMAP can strip off some headers when your messages are propagated
|
||||||
|
# back to the IMAP server. This option carries the comma-separated list
|
||||||
|
# of headers to trim off. Header name matching is case-sensitive.
|
||||||
|
#
|
||||||
|
# This knob is respected only by IMAP-based accounts. Value of labelsheader
|
||||||
|
# for GMail-based accounts is automatically added to this list, you don't
|
||||||
|
# need to specify it explicitely.
|
||||||
|
#
|
||||||
|
#filterheaders = X-Some-Weird-Header
|
||||||
|
|
||||||
|
|
||||||
[Repository LocalExample]
|
[Repository LocalExample]
|
||||||
|
|
||||||
# Each repository requires a "type" declaration. The types supported for
|
# Each repository requires a "type" declaration. The types supported for
|
||||||
|
@ -26,6 +26,10 @@ from offlineimap import globals
|
|||||||
from offlineimap.imaplib2 import MonthNames
|
from offlineimap.imaplib2 import MonthNames
|
||||||
|
|
||||||
|
|
||||||
|
# Globals
|
||||||
|
CRLF = '\r\n'
|
||||||
|
|
||||||
|
|
||||||
class IMAPFolder(BaseFolder):
|
class IMAPFolder(BaseFolder):
|
||||||
def __init__(self, imapserver, name, repository):
|
def __init__(self, imapserver, name, repository):
|
||||||
name = imaputil.dequote(name)
|
name = imaputil.dequote(name)
|
||||||
@ -38,6 +42,10 @@ class IMAPFolder(BaseFolder):
|
|||||||
self.randomgenerator = random.Random()
|
self.randomgenerator = random.Random()
|
||||||
#self.ui is set in BaseFolder
|
#self.ui is set in BaseFolder
|
||||||
|
|
||||||
|
fh_conf = self.repository.account.getconf('filterheaders', '')
|
||||||
|
self.filterheaders = [h for h in re.split(r'\s*,\s*', fh_conf) if h]
|
||||||
|
|
||||||
|
|
||||||
def __selectro(self, imapobj, force = False):
|
def __selectro(self, imapobj, force = False):
|
||||||
"""Select this folder when we do not need write access.
|
"""Select this folder when we do not need write access.
|
||||||
|
|
||||||
@ -248,7 +256,7 @@ class IMAPFolder(BaseFolder):
|
|||||||
# data looks now e.g. [('320 (UID 17061 BODY[]
|
# data looks now e.g. [('320 (UID 17061 BODY[]
|
||||||
# {2565}','msgbody....')] we only asked for one message,
|
# {2565}','msgbody....')] we only asked for one message,
|
||||||
# and that msg is in data[0]. msbody is in [0][1]
|
# and that msg is in data[0]. msbody is in [0][1]
|
||||||
data = data[0][1].replace("\r\n", "\n")
|
data = data[0][1].replace(CRLF, "\n")
|
||||||
|
|
||||||
if len(data)>200:
|
if len(data)>200:
|
||||||
dbg_output = "%s...%s" % (str(data)[:150],
|
dbg_output = "%s...%s" % (str(data)[:150],
|
||||||
@ -300,7 +308,7 @@ class IMAPFolder(BaseFolder):
|
|||||||
self.ui.debug('imap',
|
self.ui.debug('imap',
|
||||||
'__savemessage_addheader: called to add %s: %s' % (headername,
|
'__savemessage_addheader: called to add %s: %s' % (headername,
|
||||||
headervalue))
|
headervalue))
|
||||||
insertionpoint = content.find("\r\n\r\n")
|
insertionpoint = content.find(CRLF + CRLF)
|
||||||
self.ui.debug('imap', '__savemessage_addheader: insertionpoint = %d' % insertionpoint)
|
self.ui.debug('imap', '__savemessage_addheader: insertionpoint = %d' % insertionpoint)
|
||||||
leader = content[0:insertionpoint]
|
leader = content[0:insertionpoint]
|
||||||
self.ui.debug('imap', '__savemessage_addheader: leader = %s' % repr(leader))
|
self.ui.debug('imap', '__savemessage_addheader: leader = %s' % repr(leader))
|
||||||
@ -308,7 +316,7 @@ class IMAPFolder(BaseFolder):
|
|||||||
newline = ''
|
newline = ''
|
||||||
insertionpoint = 0
|
insertionpoint = 0
|
||||||
else:
|
else:
|
||||||
newline = "\r\n"
|
newline = CRLF
|
||||||
newline += "%s: %s" % (headername, headervalue)
|
newline += "%s: %s" % (headername, headervalue)
|
||||||
self.ui.debug('imap', '__savemessage_addheader: newline = ' + repr(newline))
|
self.ui.debug('imap', '__savemessage_addheader: newline = ' + repr(newline))
|
||||||
trailer = content[insertionpoint:]
|
trailer = content[insertionpoint:]
|
||||||
@ -316,6 +324,43 @@ class IMAPFolder(BaseFolder):
|
|||||||
return leader + newline + trailer
|
return leader + newline + trailer
|
||||||
|
|
||||||
|
|
||||||
|
def __savemessage_delheaders(self, content, header_list):
|
||||||
|
"""
|
||||||
|
Deletes headers in the given list from the message content.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- content: message itself
|
||||||
|
- header_list: list of headers to be deleted or just the header name
|
||||||
|
|
||||||
|
We expect our message to have proper CRLF as line endings.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if type(header_list) != type([]):
|
||||||
|
header_list = [header_list]
|
||||||
|
self.ui.debug('imap',
|
||||||
|
'__savemessage_delheaders: called to delete %s' % (header_list))
|
||||||
|
|
||||||
|
if not len(header_list): return content
|
||||||
|
|
||||||
|
eoh = content.find(CRLF + CRLF)
|
||||||
|
if eoh == -1:
|
||||||
|
eoh = len(content)
|
||||||
|
self.ui.debug('imap', '__savemessage_delheaders: end of headers = %d' % eoh)
|
||||||
|
headers = content[0:eoh]
|
||||||
|
rest = content[eoh:]
|
||||||
|
self.ui.debug('imap', '__savemessage_delheaders: headers = %s' % repr(headers))
|
||||||
|
new_headers = []
|
||||||
|
for h in headers.split(CRLF):
|
||||||
|
keep_it = True
|
||||||
|
for trim_h in self.filterheaders:
|
||||||
|
if len(h) > len(trim_h) and h[0:len(trim_h)+1] == (trim_h + ":"):
|
||||||
|
keep_it = False
|
||||||
|
break
|
||||||
|
if keep_it: new_headers.append(h)
|
||||||
|
|
||||||
|
return (CRLF.join(new_headers) + rest)
|
||||||
|
|
||||||
|
|
||||||
def __savemessage_searchforheader(self, imapobj, headername, headervalue):
|
def __savemessage_searchforheader(self, imapobj, headername, headervalue):
|
||||||
self.ui.debug('imap', '__savemessage_searchforheader called for %s: %s' % \
|
self.ui.debug('imap', '__savemessage_searchforheader called for %s: %s' % \
|
||||||
(headername, headervalue))
|
(headername, headervalue))
|
||||||
@ -510,11 +555,13 @@ class IMAPFolder(BaseFolder):
|
|||||||
return uid
|
return uid
|
||||||
|
|
||||||
# Use proper CRLF all over the message
|
# Use proper CRLF all over the message
|
||||||
content = re.sub("(?<!\r)\n", "\r\n", content)
|
content = re.sub("(?<!\r)\n", CRLF, content)
|
||||||
|
|
||||||
# get the date of the message, so we can pass it to the server.
|
# get the date of the message, so we can pass it to the server.
|
||||||
date = self.__getmessageinternaldate(content, rtime)
|
date = self.__getmessageinternaldate(content, rtime)
|
||||||
|
|
||||||
|
content = self.__savemessage_delheaders(content, self.filterheaders)
|
||||||
|
|
||||||
retry_left = 2 # succeeded in APPENDING?
|
retry_left = 2 # succeeded in APPENDING?
|
||||||
imapobj = self.imapserver.acquireconnection()
|
imapobj = self.imapserver.acquireconnection()
|
||||||
# NB: in the finally clause for this try we will release
|
# NB: in the finally clause for this try we will release
|
||||||
|
Loading…
Reference in New Issue
Block a user