Example #1
0
    def distribute(self, transport, recipients, event):
        found = False
        for supported_transport in self.transports():
            if supported_transport == transport:
                found = True
        if not self.enabled or not found:
            self.log.debug("EmailDistributer email_enabled set to false")
            return
        fmtdict = self.formats(transport, event.realm)
        if not fmtdict:
            self.log.error("EmailDistributer No formats found for %s %s" %
                           (transport, event.realm))
            return
        msgdict = {}
        msgdict_encrypt = {}
        msg_pubkey_ids = []
        # compile pattern before use for better performance
        RCPT_ALLOW_RE = re.compile(self.rcpt_allow_regexp)
        RCPT_LOCAL_RE = re.compile(self.rcpt_local_regexp)

        if self.crypto != '':
            self.log.debug("EmailDistributor attempts crypto operation.")
            self.enigma = CryptoTxt(self.gpg_binary, self.gpg_home)

        for name, authed, addr in recipients:
            fmt = name and \
                self._get_preferred_format(event.realm, name, authed) or \
                self._get_default_format()
            if fmt not in fmtdict:
                self.log.debug(("EmailDistributer format %s not available " +
                                "for %s %s, looking for an alternative") %
                               (fmt, transport, event.realm))
                # If the fmt is not available for this realm, then try to find
                # an alternative
                oldfmt = fmt
                fmt = None
                for f in fmtdict.values():
                    fmt = f.alternative_style_for(transport, event.realm,
                                                  oldfmt)
                    if fmt: break
            if not fmt:
                self.log.error(
                    "EmailDistributer was unable to find a formatter " +
                    "for format %s" % k)
                continue
            rslvr = None
            if name and not addr:
                # figure out what the addr should be if it's not defined
                for rslvr in self.resolvers:
                    addr = rslvr.get_address_for_name(name, authed)
                    if addr: break
            if addr:
                self.log.debug("EmailDistributor found the " \
                        "address '%s' for '%s (%s)' via: %s"%(
                        addr, name, authed and \
                        'authenticated' or 'not authenticated',
                        rslvr.__class__.__name__))

                # ok, we found an addr, add the message
                # but wait, check for allowed rcpt first, if set
                if RCPT_ALLOW_RE.search(addr) is not None:
                    # check for local recipients now
                    local_match = RCPT_LOCAL_RE.search(addr)
                    if self.crypto in ['encrypt', 'sign,encrypt'] and \
                            local_match is None:
                        # search available public keys for matching UID
                        pubkey_ids = self.enigma.get_pubkey_ids(addr)
                        if len(pubkey_ids) > 0:
                            msgdict_encrypt.setdefault(fmt, set()).add(
                                (name, authed, addr))
                            msg_pubkey_ids[len(msg_pubkey_ids):] = pubkey_ids
                            self.log.debug("EmailDistributor got pubkeys " \
                                "for %s: %s" % (addr, pubkey_ids))
                        else:
                            self.log.debug("EmailDistributor dropped %s " \
                                "after missing pubkey with corresponding " \
                                "address %s in any UID" % (name, addr))
                    else:
                        msgdict.setdefault(fmt, set()).add(
                            (name, authed, addr))
                        if local_match is not None:
                            self.log.debug("EmailDistributor expected " \
                                "local delivery for %s to: %s" % (name, addr))
                else:
                    self.log.debug("EmailDistributor dropped %s for " \
                        "not matching allowed recipient pattern %s" % \
                        (addr, self.rcpt_allow_regexp))
            else:
                self.log.debug("EmailDistributor was unable to find an " \
                        "address for: %s (%s)"%(name, authed and \
                        'authenticated' or 'not authenticated'))
        for k, v in msgdict.items():
            if not v or not fmtdict.get(k):
                continue
            self.log.debug("EmailDistributor is sending event as '%s' to: %s" %
                           (fmt, ', '.join(x[2] for x in v)))
            self._do_send(transport, event, k, v, fmtdict[k])
        for k, v in msgdict_encrypt.items():
            if not v or not fmtdict.get(k):
                continue
            self.log.debug(
                "EmailDistributor is sending encrypted info on event " \
                "as '%s' to: %s"%(fmt, ', '.join(x[2] for x in v)))
            self._do_send(transport, event, k, v, fmtdict[k], msg_pubkey_ids)
Example #2
0
    def distribute(self, transport, recipients, event):
        found = False
        for supported_transport in self.transports():
            if supported_transport == transport:
                found = True
        if not self.enabled or not found:
            self.log.debug("EmailDistributor email_enabled set to false")
            return
        formats = self.formats(transport, event.realm)
        if not formats:
            self.log.error("EmailDistributor No formats found for %s %s",
                           transport, event.realm)
            return
        msgdict = {}
        msgdict_encrypt = {}
        msg_pubkey_ids = []
        # compile pattern before use for better performance
        rcpt_allow_re = re.compile(self.rcpt_allow_regexp)
        rcpt_local_re = re.compile(self.rcpt_local_regexp)

        if self.crypto != '':
            self.log.debug("EmailDistributor attempts crypto operation.")
            self.enigma = CryptoTxt(self.gpg_binary, self.gpg_home)

        for name, authed, address in recipients:
            fmt = name and \
                  self._get_preferred_format(event.realm, name, authed) or \
                  self._get_default_format()
            old_fmt = fmt
            if fmt not in formats:
                self.log.debug("EmailDistributor format %s not available "
                               "for %s %s, looking for an alternative",
                               fmt, transport, event.realm)
                # If the fmt is not available for this realm, then try to find
                # an alternative
                fmt = None
                for f in formats.values():
                    fmt = f.alternative_style_for(
                        transport, event.realm, old_fmt)
                    if fmt:
                        break
            if not fmt:
                self.log.error("EmailDistributor was unable to find a "
                               "formatter for format %s", old_fmt)
                continue
            resolver = None
            if name and not address:
                # figure out what the addr should be if it's not defined
                for resolver in self.resolvers:
                    address = resolver.get_address_for_session(name, authed)
                    if address:
                        break
            if address:
                self.log.debug("EmailDistributor found the address '%s' "
                               "for '%s (%s)' via: %s", address, name,
                               authed and 'authenticated' or
                               'not authenticated',
                               resolver.__class__.__name__)

                # ok, we found an addr, add the message
                # but wait, check for allowed rcpt first, if set
                if rcpt_allow_re.search(address) is not None:
                    # check for local recipients now
                    local_match = rcpt_local_re.search(address)
                    if self.crypto in ['encrypt', 'sign,encrypt'] and \
                            local_match is None:
                        # search available public keys for matching UID
                        pubkey_ids = self.enigma.get_pubkey_ids(address)
                        if pubkey_ids > 0:
                            msgdict_encrypt.setdefault(fmt, set())\
                                .add((name, authed, address))
                            msg_pubkey_ids[len(msg_pubkey_ids):] = pubkey_ids
                            self.log.debug("EmailDistributor got pubkeys "
                                           "for %s: %s", address, pubkey_ids)
                        else:
                            self.log.debug("EmailDistributor dropped %s "
                                           "after missing pubkey with "
                                           "corresponding address %s in any "
                                           "UID", name, address)
                    else:
                        msgdict.setdefault(fmt, set())\
                            .add((name, authed, address))
                        if local_match is not None:
                            self.log.debug("EmailDistributor expected local "
                                           "delivery for %s to: %s", name,
                                           address)
                else:
                    self.log.debug("EmailDistributor dropped %s for not "
                                   "matching allowed recipient pattern %s",
                                   address, self.rcpt_allow_regexp)
            else:
                self.log.debug("EmailDistributor was unable to find an "
                               "address for: %s (%s)", name, authed and
                               'authenticated' or 'not authenticated')
        for k, v in msgdict.items():
            if not v or not formats.get(k):
                continue
            fmt = formats[k]
            self.log.debug("EmailDistributor is sending event as '%s' to: "
                           "%s", fmt, ', '.join(x[2] for x in v))
            self._do_send(transport, event, k, v, fmt)
        for k, v in msgdict_encrypt.items():
            if not v or not formats.get(k):
                continue
            fmt = formats[k]
            self.log.debug("EmailDistributor is sending encrypted info on "
                           "event as '%s' to: %s", fmt,
                           ', '.join(x[2] for x in v))
            self._do_send(transport, event, k, v, formats[k], msg_pubkey_ids)