diff options
author | Michael Stapelberg <michael@stapelberg.de> | 2012-05-04 18:55:33 +0200 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2012-05-04 18:59:27 +0200 |
commit | 98efb9cdc02ab5c77da3638c5aad25d5b75159e5 (patch) | |
tree | 01a9d159c31f0a2b1ceb6c2872601f9429963dcb /alot | |
parent | dcb33c04d1e15b96b080bc3867ed5ef52c89e956 (diff) |
Make togglesign accept an optional keyid (like 4AC8EE1D) which will be used for signing
Diffstat (limited to 'alot')
-rw-r--r-- | alot/buffers.py | 6 | ||||
-rw-r--r-- | alot/commands/envelope.py | 21 | ||||
-rw-r--r-- | alot/crypto.py | 25 | ||||
-rw-r--r-- | alot/db/envelope.py | 6 |
4 files changed, 53 insertions, 5 deletions
diff --git a/alot/buffers.py b/alot/buffers.py index 266b3e11..199bb6b2 100644 --- a/alot/buffers.py +++ b/alot/buffers.py @@ -123,7 +123,11 @@ class EnvelopeBuffer(Buffer): # sign/encrypt lines if self.envelope.sign: - self.crypto_wgt = widgets.HeadersList([ ('sign', 'yes') ]) + description = 'yes' + sign_key = self.envelope.sign_key + if sign_key is not None and len(sign_key.subkeys) > 0: + description += ', with key ' + sign_key.subkeys[0].keyid + self.crypto_wgt = widgets.HeadersList([ ('sign', description) ]) displayed_widgets.append(self.crypto_wgt) #display attachments diff --git a/alot/commands/envelope.py b/alot/commands/envelope.py index 7d3caceb..26271148 100644 --- a/alot/commands/envelope.py +++ b/alot/commands/envelope.py @@ -1,3 +1,4 @@ +import argparse import os import re import glob @@ -11,6 +12,7 @@ from alot.account import SendingMailFailed from alot.db.errors import GPGProblem from alot import buffers from alot import commands +from alot import crypto from alot.commands import Command, registerCommand from alot.commands import globals from alot.helper import string_decode @@ -330,9 +332,26 @@ class ToggleHeaderCommand(Command): ui.current_buffer.toggle_all_headers() -@registerCommand(MODE, 'togglesign') +@registerCommand(MODE, 'togglesign', arguments=[ + (['keyid'], {'nargs':argparse.REMAINDER, 'help':'which key id to use'})]) class ToggleSignCommand(Command): """toggle signing this email""" + def __init__(self, keyid, **kwargs): + """ + :param keyid: which key id to use + :type keyid: str + """ + self.keyid = keyid + Command.__init__(self, **kwargs) + def apply(self, ui): + if len(self.keyid) > 0: + keyid = str(' '.join(self.keyid)) + try: + key = crypto.CryptoContext().get_key(keyid) + except GPGProblem, e: + ui.notify(e.message, priority='error') + return + ui.current_buffer.envelope.sign_key = key ui.current_buffer.envelope.sign = not ui.current_buffer.envelope.sign ui.current_buffer.rebuild() diff --git a/alot/crypto.py b/alot/crypto.py index 2e417060..b9196590 100644 --- a/alot/crypto.py +++ b/alot/crypto.py @@ -81,7 +81,26 @@ class CryptoContext(pyme.core.Context): self.set_engine_info(pyme.constants.PROTOCOL_OpenPGP, gpg_path) self.set_armor(1) - def detached_signature_for(self, plaintext_str): + def get_key(self, keyid): + """ + Gets a key from the keyring by filtering for the specified keyid, but + only if the given keyid is specific enough (if it matches multiple + keys, an exception will be thrown). + + :param keyid: filter term for the keyring (usually a key ID) + :rtype: pyme.pygpgme._gpgme_key + """ + result = self.op_keylist_start(keyid, 0) + key = self.op_keylist_next() + if self.op_keylist_next() is not None: + # Deferred import to avoid a circular import dependency + from alot.db.errors import GPGProblem + raise GPGProblem(("More than one key found matching this filter." + " Please be more specific (use a key ID like 4AC8EE1D).")) + self.op_keylist_end() + return key + + def detached_signature_for(self, plaintext_str, key=None): """ Signs the given plaintext string and returns the detached signature. @@ -101,8 +120,12 @@ class CryptoContext(pyme.core.Context): return :param plaintext_str: text to sign + :param key: gpgme_key_t object representing the key to use :rtype: tuple of pyme.pygpgme._gpgme_op_sign_result and str """ + if key is not None: + self.signers_clear() + self.signers_add(key) plaintext_data = pyme.core.Data(plaintext_str) signature_data = pyme.core.Data() self.op_sign(plaintext_data, signature_data, diff --git a/alot/db/envelope.py b/alot/db/envelope.py index a2a17117..9d8e2599 100644 --- a/alot/db/envelope.py +++ b/alot/db/envelope.py @@ -26,7 +26,7 @@ from utils import encode_header class Envelope(object): """a message that is not yet sent and still editable""" def __init__(self, template=None, bodytext=u'', headers={}, attachments=[], - sign=False, encrypt=False): + sign=False, sign_key=None, encrypt=False): """ :param template: if not None, the envelope will be initialised by :meth:`parsing <parse_template>` this string before @@ -52,6 +52,7 @@ class Envelope(object): self.headers.update(headers) self.attachments = list(attachments) self.sign = sign + self.sign_key = sign_key self.encrypt = encrypt self.sent_time = None self.modified_since_sent = False @@ -164,7 +165,8 @@ class Envelope(object): logging.info('signing plaintext: ' + plaintext) try: - result, signature_str = context.detached_signature_for(plaintext) + result, signature_str = context.detached_signature_for( + plaintext, self.sign_key) if len(result.signatures) != 1: raise GPGProblem(("Could not sign message " "(GPGME did not return a signature)")) |