Ejemplo n.º 1
0
    def get_vcards(self):
        if not self.config.active:
            return []

        gnupg = GnuPG()
        keys = gnupg.list_keys()
        results = []
        vcards = {}
        for key in keys.values():
            vcls = [VCardLine(name="KEY",
                              value=self.VCL_KEY_FMT % key)]
            card = None
            emails = []
            for uid in key["uids"]:
                if "email" in uid and uid["email"]:
                    vcls.append(VCardLine(name="email", value=uid["email"]))
                    card = card or vcards.get(uid['email'])
                    emails.append(uid["email"])
                if "name" in uid and uid["name"]:
                    name = uid["name"]
                    vcls.append(VCardLine(name="fn", value=name))
            if card:
                card.add(*vcls)
            else:
                # This is us taking care to only create one card for each
                # set of e-mail addresses.
                card = SimpleVCard(*vcls)
                for email in emails:
                    vcards[email] = card
                results.append(card)

        return results
Ejemplo n.º 2
0
def UnwrapMimeCrypto(part, si=None, ei=None):
    """
    This method will replace encrypted and signed parts with their
    contents and set part attributes describing the security properties
    instead.
    """
    part.signature_info = si or SignatureInfo()
    part.encryption_info = ei or EncryptionInfo()
    mimetype = part.get_content_type()
    if part.is_multipart():

        # FIXME: Check the protocol. PGP? Something else?
        # FIXME: This is where we add hooks for other MIME encryption
        #        schemes, so route to callbacks by protocol.

        if mimetype == "multipart/signed":
            gpg = GnuPG()
            boundary = part.get_boundary()
            payload, signature = part.get_payload()

            # The Python get_payload() method likes to rewrite headers,
            # which breaks signature verification. So we manually parse
            # out the raw payload here.
            head, raw_payload, junk = part.as_string().replace("\r\n", "\n").split("\n--%s\n" % boundary, 2)

            part.signature_info = gpg.verify(gpg.pgpmime_normalize(raw_payload), signature.get_payload())

            # Reparent the contents up, removing the signature wrapper
            part.set_payload(payload.get_payload())
            for h in payload.keys():
                del part[h]
            for h, v in payload.items():
                part.add_header(h, v)

        elif mimetype == "multipart/encrypted":
            gpg = GnuPG()
            preamble, payload = part.get_payload()
            (part.signature_info, part.encryption_info, decrypted) = gpg.decrypt(payload.as_string())

            if part.encryption_info["status"] == "decrypted":
                newpart = email.parser.Parser().parse(StringIO.StringIO(decrypted))

                # Reparent the contents up, removing the encryption wrapper
                part.set_payload(newpart.get_payload())
                for h in newpart.keys():
                    del part[h]
                for h, v in newpart.items():
                    part.add_header(h, v)

        # If we are still multipart after the above shenanigans, recurse
        # into our subparts and unwrap them too.
        if part.is_multipart():
            for subpart in part.get_payload():
                UnwrapMimeCrypto(subpart, si=part.signature_info, ei=part.encryption_info)

    else:
        # FIXME: This is where we would handle cryptoschemes that don't
        #        appear as multipart/...
        pass
Ejemplo n.º 3
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if 'text_parts' not in tree:
            return tree

        pgpdata = []
        for part in tree['text_parts']:
            if 'crypto' not in part:
                part['crypto'] = {}

            ei = si = None
            if check_sigs:
                if part['type'] == 'pgpbeginsigned':
                    pgpdata = [part]
                elif part['type'] == 'pgpsignedtext':
                    pgpdata.append(part)
                elif part['type'] == 'pgpsignature':
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = ''.join([p['data'].encode(p['charset'])
                                           for p in pgpdata])
                        si = pgpdata[1]['crypto']['signature'
                                                  ] = gpg.verify(message)
                        pgpdata[0]['data'] = ''
                        pgpdata[2]['data'] = ''

                    except Exception, e:
                        print e

            if decrypt:
                if part['type'] in ('pgpbegin', 'pgptext'):
                    pgpdata.append(part)
                elif part['type'] == 'pgpend':
                    pgpdata.append(part)

                    gpg = GnuPG()
                    (signature_info, encryption_info, text
                     ) = gpg.decrypt(''.join([p['data'] for p in pgpdata]))

                    ei = pgpdata[1]['crypto']['encryption'] = encryption_info
                    si = pgpdata[1]['crypto']['signature'] = signature_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]['data'] = text
                        pgpdata[0]['data'] = ""
                        pgpdata[2]['data'] = ""

            # Bubbling up!
            if (si or ei) and 'crypto' not in tree:
                tree['crypto'] = {'signature': SignatureInfo(),
                                  'encryption': EncryptionInfo()}
            if si:
                tree['crypto']['signature'].mix(si)
            if ei:
                tree['crypto']['encryption'].mix(ei)
Ejemplo n.º 4
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if 'text_parts' not in tree:
            return tree

        pgpdata = []
        for part in tree['text_parts']:

            # Handle signed messages
            if 'signature_info' not in part:
                part['signature_info'] = SignatureInfo()

            if check_sigs:
                if part['type'] == 'pgpbeginsigned':
                    pgpdata = [part]
                elif part['type'] == 'pgpsignedtext':
                    pgpdata.append(part)
                elif part['type'] == 'pgpsignature':
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = ''.join([p['data'].encode(p['charset'])
                                           for p in pgpdata])
                        pgpdata[1]['signature_info'] = gpg.verify(message)
                        pgpdata[0]['data'] = ''
                        pgpdata[2]['data'] = ''
                    except Exception, e:
                        print e

            if "encryption_info" not in part:
                part['encryption_info'] = EncryptionInfo()

            if decrypt:
                if part['type'] in ('pgpbegin', 'pgptext'):
                    pgpdata.append(part)
                elif part['type'] == 'pgpend':
                    pgpdata.append(part)
                    message = ''.join([p['data'] for p in pgpdata])
                    gpg = GnuPG()
                    encryption_info, text = gpg.decrypt(message)
                    pgpdata[1]['encryption_info'] = encryption_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]['data'] = text
                        pgpdata[0]['data'] = ""
                        pgpdata[2]['data'] = ""
Ejemplo n.º 5
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if "text_parts" not in tree:
            return tree

        pgpdata = []
        for part in tree["text_parts"]:

            # Handle signed messages
            if "signature_info" not in part:
                part["signature_info"] = SignatureInfo()

            if check_sigs:
                if part["type"] == "pgpbeginsigned":
                    pgpdata = [part]
                elif part["type"] == "pgpsignedtext":
                    pgpdata.append(part)
                elif part["type"] == "pgpsignature":
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = "".join([p["data"].encode(p["charset"]) for p in pgpdata])
                        pgpdata[1]["signature_info"] = gpg.verify(message)
                        pgpdata[0]["data"] = ""
                        pgpdata[2]["data"] = ""
                    except Exception, e:
                        print e

            if "encryption_info" not in part:
                part["encryption_info"] = EncryptionInfo()

            if decrypt:
                if part["type"] in ("pgpbegin", "pgptext"):
                    pgpdata.append(part)
                elif part["type"] == "pgpend":
                    pgpdata.append(part)
                    message = "".join([p["data"] for p in pgpdata])
                    gpg = GnuPG()
                    si, encryption_info, text = gpg.decrypt(message)
                    pgpdata[1]["encryption_info"] = encryption_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]["data"] = text
                        pgpdata[0]["data"] = ""
                        pgpdata[2]["data"] = ""
Ejemplo n.º 6
0
def PrepareMail(config, mailobj, sender=None, rcpts=None):
    if not sender or not rcpts:
        tree = mailobj.get_message_tree()
        sender = sender or tree['headers_lc']['from']
        if not rcpts:
            rcpts = ExtractEmails(tree['headers_lc'].get('to', ''))
            rcpts += ExtractEmails(tree['headers_lc'].get('cc', ''))
            rcpts += ExtractEmails(tree['headers_lc'].get('bcc', ''))
            if not rcpts:
                raise NoRecipientError()
            rcpts += [sender]

    # Cleanup...
    sender = ExtractEmails(sender)[0]
    sender_keyid = None
    if config.prefs.openpgp_header:
        try:
            gnupg = GnuPG()
            seckeys = dict([(x["email"], y["fingerprint"])
                            for y in gnupg.list_secret_keys().values()
                            for x in y["uids"]])
            sender_keyid = seckeys[sender]
        except:
            pass

    rcpts, rr = [sender], rcpts
    for r in rr:
        for e in ExtractEmails(r):
            if e not in rcpts:
                rcpts.append(e)

    msg = copy.deepcopy(mailobj.get_msg())

    # Remove headers we don't want to expose
    for bcc in ('bcc', 'Bcc', 'BCc', 'BCC'):
        if bcc in msg:
            del msg[bcc]

    if 'date' not in msg:
        msg['Date'] = email.utils.formatdate()

    if sender_keyid and config.prefs.openpgp_header:
        msg["OpenPGP"] = "id=%s; preference=%s" % (sender_keyid,
                                                   config.prefs.openpgp_header)

    # Sign and encrypt
    signatureopt = bool(int(tree['headers_lc'].get('do_sign', 0)))
    encryptopt = bool(int(tree['headers_lc'].get('do_encrypt', 0)))
    gnupg = GnuPG()
    if signatureopt:
        signingstring = MessageAsString(msg)
        signature = gnupg.sign(signingstring, fromkey=sender, armor=True)

        # FIXME: Create attachment, attach signature.
        if signature[0] == 0:
            # sigblock = MIMEMultipart(_subtype="signed",
            #                          protocol="application/pgp-signature")
            # sigblock.attach(msg)
            msg.set_type("multipart/signed")
            msg.set_param("micalg", "pgp-sha1")  # need to find this!
            msg.set_param("protocol", "application/pgp-signature")
            sigblock = MIMEText(str(signature[1]), _charset=None)
            sigblock.set_type("application/pgp-signature")
            sigblock.set_param("name", "signature.asc")
            sigblock.add_header("Content-Description",
                                "OpenPGP digital signature")
            sigblock.add_header("Content-Disposition",
                                "attachment; filename=\"signature.asc\"")
            msg.attach(sigblock)
        else:
            # Raise stink about signing having failed.
            pass
        #print signature

    #if encryptopt:
    #    encrypt_to = tree['headers_lc'].get('encrypt_to')
    #    newmsg = gnupg.encrypt(msg.as_string(), encrypt_to)
    #    # TODO: Replace unencrypted message

    # When a mail has been signed or encrypted, it should be saved as such.

    del(msg["do_sign"])
    del(msg["do_encrypt"])
    del(msg["encrypt_to"])

    return (sender, set(rcpts), msg)
Ejemplo n.º 7
0
    def command(self):
        session = self.session

        # Create local mailboxes
        session.config.open_local_mailbox(session)

        # Create standard tags and filters
        created = []
        for t in self.TAGS:
            if not session.config.get_tag_id(t):
                AddTag(session, arg=[t]).run()
                created.append(t)
            session.config.get_tag(t).update(self.TAGS[t])
        if 'New' in created:
            Filter(session,
                   arg=['new', '+Inbox', '+New', 'New Mail filter']).run()
            session.ui.notify(_('Created default tags'))

        # Import all the basic plugins
        for plugin in PLUGINS:
            if plugin not in session.config.sys.plugins:
                session.config.sys.plugins.append(plugin)
        try:
            # If spambayes is not installed, this will fail
            import mailpile.plugins.autotag_sb
            if 'autotag_sb' not in session.config.sys.plugins:
                session.config.sys.plugins.append('autotag_sb')
                session.ui.notify(_('Enabling spambayes autotagger'))
        except ImportError:
            session.ui.warning(_('Please install spambayes '
                                 'for super awesome spam filtering'))
        session.config.save()
        session.config.load(session)

        vcard_importers = session.config.prefs.vcard.importers
        if not vcard_importers.gravatar:
            vcard_importers.gravatar.append({'active': True})
            session.ui.notify(_('Enabling gravatar image importer'))

        gpg_home = os.path.expanduser('~/.gnupg')
        if os.path.exists(gpg_home) and not vcard_importers.gpg:
            vcard_importers.gpg.append({'active': True,
                                        'gpg_home': gpg_home})
            session.ui.notify(_('Importing contacts from GPG keyring'))

        if ('autotag_sb' in session.config.sys.plugins and
                len(session.config.prefs.autotag) == 0):
            session.config.prefs.autotag.append({
                'match_tag': 'spam',
                'unsure_tag': 'maybespam',
                'tagger': 'spambayes',
                'trainer': 'spambayes'
            })
            session.config.prefs.autotag[0].exclude_tags[0] = 'ham'

        # Assumption: If you already have secret keys, you want to
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        gnupg = GnuPG()
        if gnupg.is_available():
            keys = gnupg.list_secret_keys()
            if len(keys) == 0:
                # FIXME: Start background process generating a key once a user
                #        has supplied a name and e-mail address.
                pass
            else:
                for key, details in keys.iteritems():
                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [x["email"]
                                            for x in session.config.profiles]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
                    if not session.config.prefs.gpg_recipient:
                        session.config.prefs.gpg_recipient = key
                        session.ui.notify(_('Encrypting config to %s') % key)
        else:
            session.ui.warning(_('Oh no, PGP/GPG support is unavailable!'))

        if (session.config.prefs.gpg_recipient
                and not (self._idx() and self._idx().INDEX)
                and not session.config.prefs.obfuscate_index):
            randcrap = sha512b64(open('/dev/urandom').read(1024),
                                 session.config.prefs.gpg_recipient,
                                 '%s' % time.time())
            session.config.prefs.obfuscate_index = randcrap
            session.config.prefs.index_encrypted = True
            session.ui.notify(_('Obfuscating search index and enabling '
                                'indexing of encrypted e-mail. '))

        session.config.save()
        return True
Ejemplo n.º 8
0
    def command(self):
        session = self.session

        # Create local mailboxes
        session.config.open_local_mailbox(session)

        # Create standard tags and filters
        created = []
        for t in self.TAGS:
            if not session.config.get_tag_id(t):
                AddTag(session, arg=[t]).run()
                created.append(t)
            session.config.get_tag(t).update(self.TAGS[t])
        if 'New' in created:
            Filter(session,
                   arg=['new', '+Inbox', '+New', 'New Mail filter']).run()

        # Import all the basic plugins
        for plugin in PLUGINS:
            if plugin not in session.config.sys.plugins:
                session.config.sys.plugins.append(plugin)
        try:
            # If spambayes is not installed, this will fail
            import mailpile.plugins.autotag_sb
            if 'autotag_sb' not in session.config.sys.plugins:
                session.config.sys.plugins.append('autotag_sb')
        except ImportError:
            session.ui.warning(_('Please install spambayes '
                                 'for super awesome spam filtering'))
        session.config.save()
        session.config.load(session)

        vcard_importers = session.config.prefs.vcard.importers
        if not vcard_importers.gravatar:
            vcard_importers.gravatar.append({'active': True})

        gpg_home = os.path.expanduser('~/.gnupg')
        if os.path.exists(gpg_home) and not vcard_importers.gpg:
            vcard_importers.gpg.append({'active': True,
                                        'gpg_home': gpg_home})

        # Assumption: If you already have secret keys, you want to 
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        gnupg = GnuPG()
        if gnupg.is_available():
            keys = gnupg.list_secret_keys()
            if len(keys) == 0:
                # FIXME: Start background process generating a key once a user
                #        has supplied a name and e-mail address.
                pass
            else:
                for key, details in keys.iteritems():
                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [x["email"] 
                                            for x in session.config.profiles]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
        else:
            # FIXME: Alert the user to the fact that PGP was not discovered
            pass

        if ('autotag_sb' in session.config.sys.plugins and
                len(session.config.prefs.autotag) == 0):
            session.config.prefs.autotag.append({
                'match_tag': 'spam',
                'unsure_tag': 'maybespam',
                'tagger': 'spambayes',
                'trainer': 'spambayes'
            })
            session.config.prefs.autotag[0].exclude_tags[0] = 'ham'

        session.config.save()
        return True
Ejemplo n.º 9
0
    def command(self):
        session = self.session

        # Create local mailboxes
        session.config.open_local_mailbox(session)

        # Create standard tags and filters
        created = []
        for t in ('New', 'Inbox', 'Outbox', 'Spam', 'Drafts', 'Blank',
                  'Sent', 'Trash'):
            if not session.config.get_tag_id(t):
                AddTag(session, arg=[t]).run()
                created.append(t)
        session.config.get_tag('New').update({
            'type': 'unread',
            'label': False,
            'display': 'invisible'
        })
        session.config.get_tag('Blank').update({
            'type': 'blank',
            'flag_editable': True,
            'display': 'invisible'
        })
        session.config.get_tag('Drafts').update({
            'type': 'drafts',
            'flag_editable': True,
            'display': 'priority',
            'display_order': 1,
        })
        session.config.get_tag('Inbox').update({
            'display': 'priority',
            'display_order': 2,
        })
        session.config.get_tag('Outbox').update({
            'type': 'outbox',
            'display': 'priority',
            'display_order': 3,
        })
        session.config.get_tag('Sent').update({
            'type': 'sent',
            'display': 'priority',
            'display_order': 4,
        })
        session.config.get_tag('Spam').update({
            'type': 'spam',
            'flag_hides': True,
            'display': 'priority',
            'display_order': 5,
        })
        session.config.get_tag('Trash').update({
            'type': 'trash',
            'flag_hides': True,
            'display': 'priority',
            'display_order': 6,
        })
        if 'New' in created:
            Filter(session,
                   arg=['new', '+Inbox', '+New', 'New Mail filter']).run()
            Filter(session,
                   arg=['read', '-New', 'Read Mail filter']).run()

        for old in ('invisible_tags', 'writable_tags'):
            if old in  session.config.sys:
                del session.config.sys[old]

        vcard_importers = session.config.prefs.vcard.importers

        if not vcard_importers.gravatar:
            vcard_importers.gravatar.append({'active': True})

        gpg_home = os.path.expanduser('~/.gnupg')
        if os.path.exists(gpg_home) and not vcard_importers.gpg:
            vcard_importers.gpg.append({'active': True,
                                        'gpg_home': gpg_home})

        # Assumption: If you already have secret keys, you want to 
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        gnupg = GnuPG()
        if gnupg.is_available():
            keys = gnupg.list_secret_keys()
            if len(keys) == 0:
                # FIXME: Start background process generating a key once a user
                #        has supplied a name and e-mail address.
                pass
            else:
                for key, details in keys.iteritems():
                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [x["email"] 
                                            for x in session.config.profiles]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
        else:
            # FIXME: Alert the user to the fact that PGP was not discovered
            pass

        session.config.save()
        return True
Ejemplo n.º 10
0
def PrepareMail(mailobj, sender=None, rcpts=None):
    if not sender or not rcpts:
        tree = mailobj.get_message_tree()
        sender = sender or tree['headers_lc']['from']
        if not rcpts:
            rcpts = ExtractEmails(tree['headers_lc'].get('to', ''))
            rcpts += ExtractEmails(tree['headers_lc'].get('cc', ''))
            rcpts += ExtractEmails(tree['headers_lc'].get('bcc', ''))
            if not rcpts:
                raise NoRecipientError()
            rcpts += [sender]

    # Cleanup...
    sender = ExtractEmails(sender)[0]
    rcpts, rr = [sender], rcpts
    for r in rr:
        for e in ExtractEmails(r):
            if e not in rcpts:
                rcpts.append(e)

    msg = copy.deepcopy(mailobj.get_msg())

    # Remove headers we don't want to expose
    for bcc in ('bcc', 'Bcc', 'BCc', 'BCC'):
        if bcc in msg:
            del msg[bcc]

    if 'date' not in msg:
        msg['Date'] = email.utils.formatdate()

    # Sign and encrypt
    signatureopt = bool(int(tree['headers_lc'].get('do_sign', 0)))
    encryptopt = bool(int(tree['headers_lc'].get('do_encrypt', 0)))
    gnupg = GnuPG()
    if signatureopt:
        signingstring = re.sub("[\r]{1}[\n]{0}", "\r\n", msg.get_payload()[0].as_string())
        # print ">>>%s<<<" % signingstring.replace("\r", "<CR>").replace("\n", "<LF>")

        signature = gnupg.sign(signingstring, fromkey=sender, armor=True)
        # TODO: Create attachment, attach signature.
        if signature[0] == 0:
            # sigblock = MIMEMultipart(_subtype="signed", protocol="application/pgp-signature")
            # sigblock.attach(msg)
            msg.set_type("multipart/signed")
            msg.set_param("micalg", "pgp-sha1") # need to find this!
            msg.set_param("protocol", "application/pgp-signature")
            sigblock = MIMEText(str(signature[1]), _charset=None)
            sigblock.set_type("application/pgp-signature")
            sigblock.set_param("name", "signature.asc")
            sigblock.add_header("Content-Description", "OpenPGP digital signature")
            sigblock.add_header("Content-Disposition", "attachment; filename=\"signature.asc\"")
            msg.attach(sigblock)
        else:
            # Raise stink about signing having failed.
            pass
        #print signature

    #if encryptopt:
    #    encrypt_to = tree['headers_lc'].get('encrypt_to')
    #    newmsg = gnupg.encrypt(msg.as_string(), encrypt_to)
    #    # TODO: Replace unencrypted message

    # When a mail has been signed or encrypted, it should be saved as such.

    del(msg["do_sign"])
    del(msg["do_encrypt"])
    del(msg["encrypt_to"])

    return (sender, set(rcpts), msg)