summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2011-10-21 23:57:24 +0100
committerPatrick Totzke <patricktotzke@gmail.com>2011-10-21 23:57:24 +0100
commit55b494c56dae620ec55bfade80dff724d08cd9bb (patch)
treed1556d818ceed66f69f8c1e5292836d883acfd7d
parentf75891da914f824cd23bbad897304e2221986f43 (diff)
parent3cdc77d09226ae2fc954644e5321457fb0aee486 (diff)
Merge branch 'master' into print_decode
Conflicts: alot/message.py
-rw-r--r--alot/completion.py4
-rw-r--r--alot/db.py12
-rw-r--r--alot/defaults/alot.rc3
-rw-r--r--alot/message.py40
-rw-r--r--alot/widgets.py40
5 files changed, 62 insertions, 37 deletions
diff --git a/alot/completion.py b/alot/completion.py
index c29ed978..2f2d3d52 100644
--- a/alot/completion.py
+++ b/alot/completion.py
@@ -61,11 +61,11 @@ class QueryCompleter(Completer):
def complete(self, original, pos):
mypart, start, end, mypos = self.relevant_part(original, pos)
myprefix = mypart[:mypos]
- m = re.search('(tag|is|to):(\w*)', myprefix)
+ m = re.search('(tag|is|to|from):(\w*)', myprefix)
if m:
cmd, params = m.groups()
cmdlen = len(cmd) + 1 # length of the keyword part incld colon
- if cmd == 'to':
+ if cmd in ['to', 'from']:
localres = self._contactscompleter.complete(mypart[cmdlen:],
mypos - cmdlen)
else:
diff --git a/alot/db.py b/alot/db.py
index 621789ae..d904c3be 100644
--- a/alot/db.py
+++ b/alot/db.py
@@ -204,8 +204,16 @@ class Thread(object):
self._authors = thread.get_authors()
self._subject = thread.get_subject()
ts = thread.get_oldest_date()
- self._oldest_date = datetime.fromtimestamp(ts)
- self._newest_date = datetime.fromtimestamp(thread.get_newest_date())
+
+ try:
+ self._oldest_date = datetime.fromtimestamp(ts)
+ except ValueError: # year is out of range
+ self._oldest_date = None
+ try:
+ self._newest_date = datetime.fromtimestamp(thread.get_newest_date())
+ except ValueError: # year is out of range
+ self._newest_date = None
+
self._tags = set([t for t in thread.get_tags()])
self._messages = {} # this maps messages to its children
self._toplevel_messages = []
diff --git a/alot/defaults/alot.rc b/alot/defaults/alot.rc
index 9ed75928..9c5a81f2 100644
--- a/alot/defaults/alot.rc
+++ b/alot/defaults/alot.rc
@@ -12,6 +12,9 @@ bufferclose_focus_offset=-1
# number of colours your terminal supports
colourmode = 256
+# number of spaces used to replace tab characters
+tabwidth = 8
+
# fill threadline with message content
display_content_in_threadline = False
diff --git a/alot/message.py b/alot/message.py
index 02f3f803..a5778d42 100644
--- a/alot/message.py
+++ b/alot/message.py
@@ -43,7 +43,10 @@ class Message(object):
self._id = msg.get_message_id()
self._thread_id = msg.get_thread_id()
self._thread = thread
- self._datetime = datetime.fromtimestamp(msg.get_date())
+ try:
+ self._datetime = datetime.fromtimestamp(msg.get_date())
+ except ValueError: # year is out of range
+ self._datetime = None
self._filename = msg.get_filename()
self._from = msg.get_header('From')
self._email = None # will be read upon first use
@@ -117,6 +120,8 @@ class Message(object):
def get_datestring(self):
"""returns formated datestring"""
+ if self._datetime == None:
+ return None
formatstring = config.get('general', 'timestamp_format')
if formatstring:
res = self._datetime.strftime(formatstring)
@@ -190,8 +195,17 @@ def extract_headers(mail, headers=None):
return headertext
+def urwid_sanitize(string):
+ tab_width = config.getint('general', 'tabwidth')
+ string = string.strip()
+ string = string.replace('\t', ' ' * tab_width)
+ string = string.replace('\r', '')
+ return string
+
+
def extract_body(mail):
body_parts = []
+ tab_width = config.getint('general', 'tabwidth')
for part in mail.walk():
ctype = part.get_content_type()
enc = part.get_content_charset() or 'ascii'
@@ -199,7 +213,7 @@ def extract_body(mail):
if part.get_content_maintype() == 'text':
raw_payload = unicode(raw_payload, enc, errors='replace')
if ctype == 'text/plain':
- body_parts.append(raw_payload)
+ body_parts.append(urwid_sanitize(raw_payload))
else:
#get mime handler
handler = get_mime_handler(ctype, key='view',
@@ -220,9 +234,9 @@ def extract_body(mail):
#remove tempfile
os.unlink(tmpfile.name)
if rendered_payload: # handler had output
- body_parts.append(rendered_payload.strip())
+ body_parts.append(urwid_sanitize(rendered_payload))
elif part.get_content_maintype() == 'text':
- body_parts.append(raw_payload)
+ body_parts.append(urwid_sanitize(raw_payload))
# else drop
return '\n\n'.join(body_parts)
@@ -251,11 +265,11 @@ def decode_header(header):
valuelist = email.header.decode_header(header)
decoded_list = []
+ tab_width = config.getint('general', 'tabwidth')
for v, enc in valuelist:
if enc:
- decoded_list.append(v.decode(enc))
- else:
- decoded_list.append(v)
+ v = v.decode(enc, errors='replace')
+ decoded_list.append(urwid_sanitize(v))
return u' '.join(decoded_list)
@@ -272,18 +286,16 @@ def encode_header(key, value):
rawentries = value.split(',')
encodedentries = []
for entry in rawentries:
- m = re.search('\s*(.*)\s+<(.*\@.*\.\w*)>$', entry)
+ m = re.search('\s*(.*)\s+<(.*\@.*\.\w*)>\s*$', entry)
if m: # If a realname part is contained
name, address = m.groups()
# try to encode as ascii, if that fails, revert to utf-8
# name must be a unicode string here
- header = Header(name)
+ namepart = Header(name)
# append address part encoded as ascii
- header.append('<%s>' % address, charset='ascii')
- encodedentries.append(header.encode())
- else: # pure email address
- encodedentries.append(entry)
- value = Header(','.join(encodedentries))
+ entry = '%s <%s>' % (namepart.encode(), address)
+ encodedentries.append(entry)
+ value = Header(', '.join(encodedentries))
else:
value = Header(value)
return value
diff --git a/alot/widgets.py b/alot/widgets.py
index b6e6563f..393c9198 100644
--- a/alot/widgets.py
+++ b/alot/widgets.py
@@ -83,12 +83,15 @@ class ThreadlineWidget(urwid.AttrMap):
def rebuild(self):
cols = []
- formatstring = config.get('general', 'timestamp_format')
newest = self.thread.get_newest_date()
- if formatstring:
- datestring = newest.strftime(formatstring)
+ if newest == None:
+ datestring = u' ' * 10
else:
- datestring = pretty_datetime(newest).rjust(10)
+ formatstring = config.get('general', 'timestamp_format')
+ if formatstring:
+ datestring = newest.strftime(formatstring)
+ else:
+ datestring = pretty_datetime(newest).rjust(10)
self.date_w = urwid.AttrMap(urwid.Text(datestring), 'threadline_date')
cols.append(('fixed', len(datestring), self.date_w))
@@ -470,7 +473,13 @@ class MessageSummaryWidget(urwid.WidgetWrap):
urwid.WidgetWrap.__init__(self, txt)
def __str__(self):
- return self.message.__str__()
+ author, address = self.message.get_author()
+ date = self.message.get_datestring()
+ if date == None:
+ rep = author
+ else:
+ rep = '%s (%s)' % (author, date)
+ return rep
def selectable(self):
return True
@@ -519,23 +528,16 @@ class MessageHeaderWidget(urwid.AttrMap):
displayed = self.eml.keys()
if hidden:
displayed = filter(lambda x: x not in hidden, displayed)
+ #calc max length of key-string
for key in displayed:
if key in self.eml:
if len(key) > max_key_len:
max_key_len = len(key)
- for key in displayed:
+ for key, value in self.eml.items():
#todo: parse from,cc,bcc seperately into name-addr-widgets
- if key in self.eml:
- valuelist = email.header.decode_header(self.eml[key])
- value = ''
- for v, enc in valuelist:
- if enc:
- value = value + v.decode(enc)
- else:
- value = value + v
- #sanitize it a bit:
- value = value.replace('\t', ' ')
- value = ' '.join([line.strip() for line in value.splitlines()])
+ # TODO: check indexed keys for None and highlight as invalid
+ if key in displayed:
+ value = message.decode_header(value)
keyw = ('fixed', max_key_len + 1,
urwid.Text(('message_header_key', key)))
valuew = urwid.Text(('message_header_value', value))
@@ -547,8 +549,8 @@ class MessageHeaderWidget(urwid.AttrMap):
class MessageBodyWidget(urwid.AttrMap):
"""displays printable parts of an email"""
- def __init__(self, msg, tab_width=8):
- bodytxt = message.extract_body(msg).replace('\t', ' ' * tab_width)
+ def __init__(self, msg):
+ bodytxt = message.extract_body(msg)
urwid.AttrMap.__init__(self, urwid.Text(bodytxt), 'message_body')