def TransformOutgoing(self, sender, rcpts, msg, **kwargs): matched = False keydata = mutual = sender_keyid = key_binary = None gnupg = GnuPG(self.config, event=GetThreadEvent()) profile = self._get_sender_profile(sender, kwargs) vcard = profile['vcard'] if vcard is not None: crypto_format = vcard.crypto_format sender_keyid = vcard.pgp_key if sender_keyid and 'autocrypt' in crypto_format: key_binary = gnupg.get_minimal_key(key_id=sender_keyid, user_id=sender) if key_binary: mutual = 'E' in crypto_format.split('+')[0].split(':')[-1] msg["Autocrypt"] = make_autocrypt_header( sender, key_binary, prefer_encrypt_mutual=mutual) if 'encrypt' in msg.get('Encryption', '').lower(): gossip_list = [] for rcpt in rcpts: # FIXME: Check if any of the recipients are in the BCC # header; omit their keys if so? try: # This *should* always succeed: if we are encrypting, # then the key we encrypt to should already be in # the keychain. if '#' in rcpt: rcpt, rcpt_keyid = rcpt.split('#') else: # This happens when composing in the CLI. rcpt_keyid = rcpt if (rcpt != sender) and rcpt_keyid: kb = gnupg.get_minimal_key(key_id=rcpt_keyid, user_id=rcpt) if kb: gossip_list.append( make_autocrypt_header( rcpt, kb, prefix='Autocrypt-Gossip')) except (ValueError, IndexError): pass if len(gossip_list) > 1: # No point gossiping peoples keys back to them alone. for hdr in gossip_list: msg.add_header('Autocrypt-Gossip', hdr) matched = True return sender, rcpts, msg, matched, True
def get_vcards(self, selectors=None, public=True, secret=True, vcards=None, event=None): if not self.config.active: return [] # Event magic event = event or GetThreadEvent() # Generate all the nice new cards! new_cards = self.gnupg_keys_as_vcards(GnuPG(self.session.config, event=event), selectors=selectors, public=public, secret=secret) # Generate tombstones for keys which are gone from the keyring. if vcards: deleted = set() deleted_names = {} search = ';%s/' % self.config.guid for cardid, vcard in (vcards or {}).iteritems(): for vcl in vcard.get_all('clientpidmap'): if search in vcl.value: key_id = vcl.value.split(';')[1] deleted.add(key_id) deleted_names[key_id] = vcard.fn if selectors: deleted = set([ guid for guid in deleted if guid.split('/')[-1] in selectors ]) deleted -= set([self.get_guid(card) for card in new_cards]) for guid in deleted: mrgid = guid.split('/')[-1] fn = deleted_names[guid] new_cards.append( MailpileVCard(VCardLine(name='fn', value=fn), VCardLine(name='x-gpg-mrgid', value=mrgid))) return new_cards
def TransformOutgoing(self, sender, rcpts, msg, **kwargs): matched = False gnupg = None sender_keyid = None # Prefer to just get everything from the profile VCard, in the # common case... profile = self.config.vcards.get_vcard(sender) if profile: sender_keyid = profile.pgp_key crypto_format = profile.crypto_format or 'none' else: crypto_format = 'none' # Parse the openpgp_header data from the crypto_format openpgp_header = [ p.split(':')[-1] for p in crypto_format.split('+') if p.startswith('openpgp_header:') ] if not openpgp_header: openpgp_header = self.config.prefs.openpgp_header and ['CFG'] if openpgp_header[0] != 'N' and not sender_keyid: # This is a fallback: this shouldn't happen much in normal use try: gnupg = gnupg or GnuPG(self.config, event=GetThreadEvent()) seckeys = dict([ (uid["email"], fp) for fp, key in gnupg.list_secret_keys().iteritems() if key["capabilities_map"].get("encrypt") and key["capabilities_map"].get("sign") for uid in key["uids"] ]) sender_keyid = seckeys.get(sender) except (KeyError, TypeError, IndexError, ValueError): traceback.print_exc() if sender_keyid and openpgp_header: preference = { 'ES': 'signencrypt', 'SE': 'signencrypt', 'E': 'encrypt', 'S': 'sign', 'N': 'unprotected', 'CFG': self.config.prefs.openpgp_header }[openpgp_header[0].upper()] msg["OpenPGP"] = ("id=%s; preference=%s" % (sender_keyid, preference)) if ('attach-pgp-pubkey' in msg and msg['attach-pgp-pubkey'][:3].lower() in ('yes', 'tru')): gnupg = gnupg or GnuPG(self.config, event=GetThreadEvent()) if sender_keyid: keys = gnupg.list_keys(selectors=[sender_keyid]) else: keys = gnupg.address_to_keys(ExtractEmails(sender)[0]) key_count = 0 for fp, key in keys.iteritems(): if not any(key["capabilities_map"].values()): continue # We should never really hit this more than once. But if we # do, should still be fine. keyid = key["keyid"] data = gnupg.get_pubkey(keyid) try: from_name = key["uids"][0]["name"] filename = _('Encryption key for %s.asc') % from_name except: filename = _('My encryption key.asc') att = MIMEBase('application', 'pgp-keys') att.set_payload(data) encoders.encode_base64(att) del att['MIME-Version'] att.add_header('Content-Id', MakeContentID()) att.add_header('Content-Disposition', 'attachment', filename=filename) att.signature_info = SignatureInfo(parent=msg.signature_info) att.encryption_info = EncryptionInfo( parent=msg.encryption_info) msg.attach(att) key_count += 1 if key_count > 0: msg['x-mp-internal-pubkeys-attached'] = "Yes" return sender, rcpts, msg, matched, True