summaryrefslogtreecommitdiff
path: root/alot
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2012-05-04 18:55:33 +0200
committerMichael Stapelberg <michael@stapelberg.de>2012-05-04 18:59:27 +0200
commit98efb9cdc02ab5c77da3638c5aad25d5b75159e5 (patch)
tree01a9d159c31f0a2b1ceb6c2872601f9429963dcb /alot
parentdcb33c04d1e15b96b080bc3867ed5ef52c89e956 (diff)
Make togglesign accept an optional keyid (like 4AC8EE1D) which will be used for signing
Diffstat (limited to 'alot')
-rw-r--r--alot/buffers.py6
-rw-r--r--alot/commands/envelope.py21
-rw-r--r--alot/crypto.py25
-rw-r--r--alot/db/envelope.py6
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)"))