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