1# Copyright (C) 2011-2018 Patrick Totzke <patricktotzke@gmail.com> 2# This file is released under the GNU GPL, version 3 or a later revision. 3# For further details see the COPYING file 4import urwid 5import os 6 7from .buffer import Buffer 8from ..settings.const import settings 9from ..widgets.globals import HeadersList 10from ..widgets.globals import AttachmentWidget 11from ..helper import shorten_author_string 12from ..helper import string_sanitize 13from ..db.utils import render_part 14from email.mime.text import MIMEText 15 16 17class EnvelopeBuffer(Buffer): 18 """message composition mode""" 19 20 modename = 'envelope' 21 22 def __init__(self, ui, envelope): 23 self.ui = ui 24 self.envelope = envelope 25 self.all_headers = False 26 self.displaypart = "plaintext" 27 self.rebuild() 28 Buffer.__init__(self, ui, self.body) 29 30 def __str__(self): 31 to = self.envelope.get('To', fallback='unset') 32 return '[envelope] to: %s' % (shorten_author_string(to, 400)) 33 34 def get_info(self): 35 info = {} 36 info['to'] = self.envelope.get('To', fallback='unset') 37 info['displaypart'] = self.displaypart 38 return info 39 40 def cleanup(self): 41 if self.envelope.tmpfile: 42 os.unlink(self.envelope.tmpfile.name) 43 44 def rebuild(self): 45 displayed_widgets = [] 46 hidden = settings.get('envelope_headers_blacklist') 47 # build lines 48 lines = [] 49 for (k, vlist) in self.envelope.headers.items(): 50 if (k not in hidden) or self.all_headers: 51 for value in vlist: 52 lines.append((k, value)) 53 54 # sign/encrypt lines 55 if self.envelope.sign: 56 description = 'Yes' 57 sign_key = self.envelope.sign_key 58 if sign_key is not None and len(sign_key.subkeys) > 0: 59 description += ', with key ' + sign_key.uids[0].uid 60 lines.append(('GPG sign', description)) 61 62 if self.envelope.encrypt: 63 description = 'Yes' 64 encrypt_keys = self.envelope.encrypt_keys.values() 65 if len(encrypt_keys) == 1: 66 description += ', with key ' 67 elif len(encrypt_keys) > 1: 68 description += ', with keys ' 69 key_ids = [] 70 for key in encrypt_keys: 71 if key is not None and key.subkeys: 72 key_ids.append(key.uids[0].uid) 73 description += ', '.join(key_ids) 74 lines.append(('GPG encrypt', description)) 75 76 if self.envelope.tags: 77 lines.append(('Tags', ','.join(self.envelope.tags))) 78 79 # add header list widget iff header values exists 80 if lines: 81 key_att = settings.get_theming_attribute('envelope', 'header_key') 82 value_att = settings.get_theming_attribute('envelope', 83 'header_value') 84 gaps_att = settings.get_theming_attribute('envelope', 'header') 85 self.header_wgt = HeadersList(lines, key_att, value_att, gaps_att) 86 displayed_widgets.append(self.header_wgt) 87 88 # display attachments 89 lines = [] 90 for a in self.envelope.attachments: 91 lines.append(AttachmentWidget(a, selectable=False)) 92 if lines: 93 self.attachment_wgt = urwid.Pile(lines) 94 displayed_widgets.append(self.attachment_wgt) 95 96 # message body 97 txt = self._find_body_text() 98 self.body_wgt = urwid.Text(string_sanitize(txt)) 99 displayed_widgets.append(self.body_wgt) 100 self.body = urwid.ListBox(displayed_widgets) 101 102 def toggle_all_headers(self): 103 """Toggle visibility of all envelope headers.""" 104 self.all_headers = not self.all_headers 105 self.rebuild() 106 107 def _find_body_text(self): 108 txt = "no such part!" 109 if self.displaypart == "html": 110 htmlpart = MIMEText(self.envelope.body_html, 'html', 'utf-8') 111 txt = render_part(htmlpart) 112 elif self.displaypart == "src": 113 txt = self.envelope.body_html 114 elif self.displaypart == "plaintext": 115 txt = self.envelope.body_txt 116 return txt 117 118 def set_displaypart(self, part): 119 """Update the view to display body part (plaintext, html, src). 120 121 ..note:: This assumes that selv.envelope.body_html exists in case 122 the requested part is 'html' or 'src'! 123 """ 124 self.displaypart = part 125 txt = self._find_body_text() 126 self.body_wgt.set_text(txt) 127