Example #1
0
    def email_rt_delete(self, operator, queuename):
        """ Delete RT list. """
        queue, host = self._resolve_rt_name(queuename)
        rt_dom = self._get_email_domain_from_str(host)
        self.ba.can_rt_delete(operator.get_entity_id(), domain=rt_dom)
        et = Email.EmailTarget(self.db)
        ea = Email.EmailAddress(self.db)
        epat = Email.EmailPrimaryAddressTarget(self.db)
        result = []

        for target_id in self.__get_all_related_rt_targets(queuename):
            try:
                et.clear()
                et.find(target_id)
            except Errors.NotFoundError:
                continue

            epat.clear()
            try:
                epat.find(et.entity_id)
            except Errors.NotFoundError:
                pass
            else:
                epat.delete()
            for r in et.get_addresses():
                addr = '%(local_part)s@%(domain)s' % r
                ea.clear()
                ea.find_by_address(addr)
                ea.delete()
                result.append({'address': addr})
            et.delete()

        return result
 def _create_distgroup_mailaddr(self, et):
     ea = Email.EmailAddress(self._db)
     # move this to a variable
     # no need to wash the address, group will not be created
     # if the name is not valid for Exchange
     lp = "%s%s" % (cereconf.DISTGROUP_PRIMARY_ADDR_PREFIX, self.group_name)
     dom = Email.EmailDomain(self._db)
     dom.find_by_domain(cereconf.DISTGROUP_DEFAULT_DOMAIN)
     addr_str = lp + '@' + cereconf.DISTGROUP_DEFAULT_DOMAIN
     try:
         ea.find_by_local_part_and_domain(lp, dom.entity_id)
         if ea.email_addr_target_id != et.entity_id:
             raise self._db.IntegrityError("Address %s is already taken!" %
                                           addr_str)
     except Errors.NotFoundError:
         ea.populate(lp, dom.entity_id, et.entity_id, expire=None)
     ea.write_db()
     epat = Email.EmailPrimaryAddressTarget(self._db)
     try:
         epat.find(ea.email_addr_target_id)
         epat.populate(ea.entity_id)
     except Errors.NotFoundError:
         epat.clear()
         epat.populate(ea.entity_id, parent=et)
     epat.write_db()
Example #3
0
def update_email_address(address, group):
    et, ea = get_email_target_and_address(address)
    if et:
        if et.email_target_type != co.email_target_multi:
            logger.error("Wrong existing target type for <%s>", address)
            return
        if et.email_target_entity_id == group.entity_id:
            logger.debug("Up-to-date <%s>", address)
            return
        et.email_target_entity_id = group.entity_id
        logger.info("Updating <%s>", address)
        et.write_db()
    else:
        et = Email.EmailTarget(db)
        try:
            et.find_by_target_entity(group.entity_id)
            logger.info("Added address <%s>", address)
        except Errors.NotFoundError:
            et.populate(co.email_target_multi,
                        target_entity_type=co.entity_group,
                        target_entity_id=group.entity_id)
            et.write_db()
            logger.info("Created <%s>", address)
        ed = Email.EmailDomain(db)
        lp, dom = address.split('@')
        ed.find_by_domain(dom)
        ea = Email.EmailAddress(db)
        ea.populate(lp, ed.entity_id, et.entity_id)
        ea.write_db()
Example #4
0
    def delete(self):
        """Delete the group, along with its EmailTarget."""
        et = Email.EmailTarget(self._db)
        ea = Email.EmailAddress(self._db)
        epat = Email.EmailPrimaryAddressTarget(self._db)

        # If there is not associated an EmailTarget with the group, call delete
        # from the superclass.
        try:
            et.find_by_target_entity(self.entity_id)
        except Errors.NotFoundError:
            return super(GroupUiOMixin, self).delete()

        # An EmailTarget exists, so we try to delete its primary address.
        try:
            epat.find(et.entity_id)
            epat.delete()
        except Errors.NotFoundError:
            pass

        # We remove all the EmailTargets addresses.
        try:
            for row in et.get_addresses():
                ea.clear()
                ea.find(row['address_id'])
                ea.delete()
        except Errors.NotFoundError:
            pass

        # Delete the EmailTarget
        et.delete()

        # Finally! Delete the group!
        super(GroupUiOMixin, self).delete()
Example #5
0
def process_email_srv_data(uname, account_id, email_srv):
    if email_srv in ['NOMAIL', 'NOLOCAL']:
        logger.error("Bad email server %s for %s", email_srv, uname)
        return None
    email_server = Email.EmailServer(db)
    email_server_target = Email.EmailServerTarget(db)
    email_target = Email.EmailTarget(db)
    email_server.find_by_name(email_srv)
    email_server_id = email_server.entity_id
    try:
        email_target.find_by_email_target_attrs(
            target_entity_id=int(account_id))
    except Errors.NotFoundError:
        logger.error("No email target for %s", uname)
        return None
    try:
        email_server_target.find(email_target.entity_id)
        logger.debug("Email-server is registered %s for %s", email_srv, uname)
    except Errors.NotFoundError:
        email_server_target.clear()
        email_server_target.populate(email_server_id, parent=email_target)
        email_server_target.write_db()
        logger.debug("Populated email-server %s for %s", email_srv, uname)

    email_server.clear()
    email_server_target.clear()
    email_target.clear()
Example #6
0
    def _get_person_owner_attributes(self, owner):
        """Return a dict with person tidbits for LDAP.

        FIXME: THIS MUST NOT FAIL with NotFoundError.
        """
        def extract_email_from_account(account_id):
            try:
                et = Email.EmailTarget(self._db)
                et.find_by_target_entity(account_id)
                return [
                    "%s@%s" % (r['local_part'], r['domain'])
                    for r in et.get_addresses(special=False)
                ]
            except Errors.NotFoundError:
                return []

        # end extract_email_from_account

        result = dict()
        # uid
        try:
            account_id = owner.get_primary_account()
            acc = Factory.get("Account")(self._db)
            acc.find(account_id)
            result["uid"] = acc.account_name
        except Errors.NotFoundError:
            result["uid"] = None

        # ALL unames must go into 'voipSipUri'. And so must all e-mail
        # addresses.
        result["voipSipUri"] = list()
        for row in acc.search(owner_id=owner.entity_id):
            result["voipSipUri"].append(self._voipify(row["name"], None))
            for address in extract_email_from_account(row["account_id"]):
                mangled = self._voipify(address, None)
                result["voipSipUri"].append(mangled)

        # mail - primary e-mail address.
        if result['uid']:
            try:
                et = Email.EmailTarget(self._db)
                et.find_by_target_entity(acc.entity_id)
                epat = Email.EmailPrimaryAddressTarget(self._db)
                epat.find(et.entity_id)
                ea = Email.EmailAddress(self._db)
                ea.find(epat.get_address_id())
                result["mail"] = ea.get_address()
            except Errors.NotFoundError:
                result["mail"] = None

        # cn - grab system cached
        try:
            p_name = owner.get_name(
                self.const.system_cached,
                getattr(self.const, cereconf.DEFAULT_GECOS_NAME))
        except Errors.NotFoundError:
            p_name = None

        result["cn"] = p_name
        return result
Example #7
0
def get_email_server(account_id, local_db=db):
    """Return Host object for account's mail server."""
    et = Email.EmailTarget(local_db)
    et.find_by_target_entity(account_id)
    server = Email.EmailServer(local_db)
    server.find(et.email_server_id)
    return server
def get_address(address_id):
    ea = Email.EmailAddress(db)
    ea.find(address_id)
    ed = Email.EmailDomain(db)
    ed.find(ea.email_addr_domain_id)
    return "%s@%s" % (ea.email_addr_local_part,
                      ed.rewrite_special_domains(ed.email_domain_name))
Example #9
0
 def read_server(self, spread):
     mail_serv = Email.EmailServer(self._db)
     for row in mail_serv.list_email_server_ext():
         self.serv_id2server[int(
             row['server_id'])] = [row['server_type'], row['name']]
     mail_targ = Email.EmailTarget(self._db)
     for row in mail_targ.list_email_server_targets():
         self.targ2server_id[int(row['target_id'])] = int(row['server_id'])
Example #10
0
def get_email_target_and_address(address):
    ea = Email.EmailAddress(db)
    try:
        ea.find_by_address(address)
    except Errors.NotFoundError:
        return (None, None)
    et = Email.EmailTarget(db)
    et.find(ea.email_addr_target_id)
    return (et, ea)
Example #11
0
    def test_phonenumberchange_delay(self):
        """Fresh phone numbers should not be used if config says so."""
        cereconf.INDIVIDUATION_PHONE_TYPES['system_fs']['types']['contact_mobile_phone']['delay'] = 7
        cereconf.INDIVIDUATION_PHONE_TYPES['system_fs']['types']['contact_private_mobile']['delay'] = 7

        ou = Factory.get('OU')(self.db)
        co = Factory.get('Constants')(self.db)
        ou.find_stedkode(0, 0, 0, 0)
        pe = self.createPerson(first_name='Miss', last_name='Test', studnr='007')
        ac = self.createAccount(pe, 'mstest')

        pe.populate_affiliation(source_system=co.system_fs, ou_id=ou.entity_id,
                affiliation=co.affiliation_student,
                status=co.affiliation_status_student_aktiv)
        pe.write_db()
        pe.populate_contact_info(source_system=co.system_fs,
                                 type=co.contact_mobile_phone,
                                 value='98012345')
        pe.write_db()

        # Create e-mail address for user
        ed = Email.EmailDomain(self.db)
        ed.populate('example.com', 'For testing')
        ed.write_db()
        et = Email.EmailTarget(self.db)
        et.populate(co.email_target_account, ac.entity_id, co.entity_account)
        et.write_db()
        ea = Email.EmailAddress(self.db)
        ea.populate('test', ed.entity_id, et.entity_id)
        ea.write_db()
        epa = Email.EmailPrimaryAddressTarget(self.db)
        epa.populate(ea.entity_id, et)
        epa.write_db()

        self.db.commit()

        # hack the create_date in change_log
        self.db.execute("""
            UPDATE [:table schema=cerebrum name=change_log]
            SET tstamp = :tid 
            WHERE 
                subject_entity = :s_id AND
                change_type_id = :ct_id""", 
                    {'s_id': pe.entity_id,
                    'ct_id': co.person_create,
                    'tid': DateTime(2009, 10, 4),})
        self.db.commit()

        d = self.client.callRemote('generate_token',
                id_type="externalid_studentnr", ext_id='007',
                username='******', phone_no='98012345',
                browser_token='a')
        d = self.assertFailure(d, error.Error)
        # TODO: test that sendmail is called with the correct to-address
        return d
Example #12
0
    def delete_spread(self, spread):
        #
        # Pre-remove checks
        #
        spreads = [int(r['spread']) for r in self.get_spread()]
        if spread not in spreads:  # user doesn't have this spread
            return
        # All users in the 'ifi' NIS domain must also exist in the
        # 'uio' NIS domain.
        if (spread == self.const.spread_uio_nis_user
                and int(self.const.spread_ifi_nis_user) in spreads):
            raise self._db.IntegrityError, \
                  "Can't remove uio spread to an account with ifi spread."

        if (spread == self.const.spread_ifi_nis_user
                or spread == self.const.spread_uio_nis_user):
            self.clear_home(spread)

        # Remove IMAP user
        # TBD: It is currently a bit uncertain who and when we should
        # allow this.  Currently it should only be used when deleting
        # a user.
        # exchange-related-jazz
        # this code, up to and including the TBD should be removed
        # when migration to Exchange is completed as it wil no longer
        # be needed. Jazz (2013-11)
        #
        if (spread == self.const.spread_uio_imap
                and int(self.const.spread_uio_imap) in spreads):
            et = Email.EmailTarget(self._db)
            et.find_by_target_entity(self.entity_id)
            self._UiO_order_cyrus_action(self.const.bofh_email_delete,
                                         et.email_server_id)
            # TBD: should we also perform a "cascade delete" from EmailTarget?
        # exchange-relatert-jazz
        # Due to the way Exchange is updated we no longer need to
        # register a delete request in Cerebrum. Setting target_type
        # to deleted should generate an appropriate event which then
        # may be used to remove the mailbox from Exchange in the
        # agreed maner (export to .pst-file, then remove-mailbox). A
        # clean-up job should probably be implemented to remove
        # email_targets that have had status deleted for a period of
        # time. This will however remove the e-mailaddresses assigned
        # to the target and make their re-use possible. Jazz (2013-11)
        #
        if spread == self.const.spread_exchange_account:
            et = Email.EmailTarget(self._db)
            et.find_by_target_entity(self.entity_id)
            et.email_target_type = self.const.email_target_deleted
            et.write_db()
        # (Try to) perform the actual spread removal.
        ret = self.__super.delete_spread(spread)
        return ret
Example #13
0
    def _email_info_detail(self, acc):
        """ Get quotas from Cerebrum, and usage from Cyrus. """
        # NOTE: Very similar to hiof and uio

        info = []
        eq = Email.EmailQuota(self.db)

        # Get quota and usage
        try:
            eq.find_by_target_entity(acc.entity_id)
            et = Email.EmailTarget(self.db)
            et.find_by_target_entity(acc.entity_id)
            es = Email.EmailServer(self.db)
            es.find(et.email_server_id)

            if es.email_server_type == self.const.email_server_type_cyrus:
                used = 'N/A'
                limit = None
                pw = self.db._read_password(cereconf.CYRUS_HOST,
                                            cereconf.CYRUS_ADMIN)
                try:
                    cyrus = imaplib.IMAP4(es.name)
                    # IVR 2007-08-29 If the server is too busy, we do not want
                    # to lock the entire bofhd.
                    # 5 seconds should be enough
                    cyrus.socket().settimeout(5)
                    cyrus.login(cereconf.CYRUS_ADMIN, pw)
                    res, quotas = cyrus.getquota("user." + acc.account_name)
                    cyrus.socket().settimeout(None)
                    if res == "OK":
                        for line in quotas:
                            try:
                                folder, qtype, qused, qlimit = line.split()
                                if qtype == "(STORAGE":
                                    used = str(int(qused)/1024)
                                    limit = int(qlimit.rstrip(")"))/1024
                            except ValueError:
                                # line.split fails e.g. because quota isn't set
                                # on server
                                folder, junk = line.split()
                                self.logger.warning(
                                    "No IMAP quota set for '%s'" %
                                    acc.account_name)
                                used = "N/A"
                                limit = None
                except (TimeoutException, socket.error):
                    used = 'DOWN'
                except ConnectException, e:
                    used = str(e)
                except imaplib.IMAP4.error, e:
                    used = 'DOWN'
Example #14
0
 def _UiO_default_filter_settings(self, email_target):
     t_id = email_target.entity_id
     tt_str = str(Email._EmailTargetCode(email_target.email_target_type))
     # Set default filters if none found on this target
     etf = Email.EmailTargetFilter(self._db)
     if tt_str in cereconf.EMAIL_DEFAULT_FILTERS:
         for f in cereconf.EMAIL_DEFAULT_FILTERS[tt_str]:
             f_id = int(EmailConstants._EmailTargetFilterCode(f))
             try:
                 etf.clear()
                 etf.find(t_id, f_id)
             except Errors.NotFoundError:
                 etf.clear()
                 etf.populate(f_id, parent=email_target)
                 etf.write_db()
Example #15
0
 def _UiO_default_filter_settings(self, email_target):
     t_id = email_target.entity_id
     tt_str = str(Email._EmailTargetCode(email_target.email_target_type))
     # Set default filters if none found on this target
     etf = Email.EmailTargetFilter(self._db)
     if cereconf.EMAIL_DEFAULT_FILTERS.has_key(tt_str):
         for f in cereconf.EMAIL_DEFAULT_FILTERS[tt_str]:
             f_id = int(Email._EmailTargetFilterCode(f))
             try:
                 etf.clear()
                 etf.find(t_id, f_id)
             except Errors.NotFoundError:
                 etf.clear()
                 etf.populate(f_id, parent=email_target)
                 etf.write_db()
Example #16
0
    def user_create_unpersonal(self, operator,
                               account_name, group_name,
                               contact_address, account_type):
        """Bofh command: user create_unpersonal"""
        self.ba.can_create_user_unpersonal(operator.get_entity_id(),
                                           group=self._get_group(group_name))

        account_type = self._get_constant(self.const.Account, account_type,
                                          "account type")

        account_policy = AccountPolicy(self.db)
        try:
            account = account_policy.create_group_account(
                operator.get_entity_id(),
                account_name,
                self._get_group(group_name),
                contact_address,
                account_type
            )
        except InvalidAccountCreationArgument as e:
            raise CerebrumError(e)

        self._user_password(operator, account)

        # TBD: Better way of checking if email forwards are in use, by
        # checking if bofhd command is available?
        if hasattr(self, '_email_create_forward_target'):
            localaddr = '{}@{}'.format(
                account_name,
                Email.get_primary_default_email_domain())
            self._email_create_forward_target(localaddr, contact_address)

        return {'account_id': int(account.entity_id)}
Example #17
0
    def sympa_create_list_alias(self,
                                operator,
                                listname,
                                address,
                                yes_no_force='No'):
        """ Create a secondary name for an existing Sympa list. """
        force = self._is_yes(yes_no_force)
        # The first thing we have to do is to locate the delivery
        # host. Postmasters do NOT want to allow people to specify a different
        # delivery host for alias than for the list that is being aliased. So,
        # find the ml's ET and fish out the server_id.
        self._validate_sympa_list(listname)
        local_part, domain = self._split_email_address(listname)
        ed = self._get_email_domain_from_str(domain)
        email_address = Email.EmailAddress(self.db)
        email_address.find_by_local_part_and_domain(local_part, ed.entity_id)
        try:
            delivery_host = self._get_server_from_address(email_address)
        except CerebrumError:
            raise CerebrumError("Cannot alias list %s (missing delivery host)",
                                listname)

        # TODO: Look at perms (are now done by _register)
        self._create_sympa_list_alias(operator,
                                      listname,
                                      address,
                                      delivery_host,
                                      force_alias=force)
        return {
            'target': listname,
            'alias': address,
        }
Example #18
0
 def getdict_accid2mailaddr(self, filter_expired=True):
     ret = {}
     ed = Email.EmailDomain(self._db)
     binds = {
         'targ_type': int(self.const.email_target_account),
         'namespace': int(self.const.account_namespace),
     }
     stmt = """
       SELECT en.entity_id, ea.local_part, ed.domain
       FROM [:table schema=cerebrum name=account_info] ai
       JOIN [:table schema=cerebrum name=entity_name] en
         ON en.entity_id = ai.account_id
       JOIN [:table schema=cerebrum name=email_target] et
         ON et.target_type = :targ_type AND
            et.target_entity_id = ai.account_id
       JOIN [:table schema=cerebrum name=email_primary_address] epa
         ON epa.target_id = et.target_id
       JOIN [:table schema=cerebrum name=email_address] ea
         ON ea.address_id = epa.address_id
       JOIN [:table schema=cerebrum name=email_domain] ed
         ON ed.domain_id = ea.domain_id
       WHERE en.value_domain = :namespace
     """
     if filter_expired:
         stmt += " AND (ai.expire_date IS NULL OR ai.expire_date > [:now])"
     for row in self.query(stmt, binds):
         ret[row['entity_id']] = '@'.join(
             (row['local_part'], ed.rewrite_special_domains(row['domain'])))
     return ret
Example #19
0
    def _split_email_address(self, addr, with_checks=True):
        """Split an e-mail address into local part and domain.

        Additionally, perform certain basic checks to ensure that the address
        looks sane.

        @type addr: basestring
        @param addr:
          E-mail address to split, spelled as 'foo@domain'.

        @type with_checks: bool
        @param with_checks:
          Controls whether to perform local part checks on the
          address. Occasionally we may want to sidestep this (e.g. when
          *removing* things from the database).

        @rtype: tuple of (basestring, basestring)
        @return:
          A pair, local part and domain extracted from the L{addr}.
        """
        from Cerebrum.modules import Email
        if addr.count('@') == 0:
            raise CerebrumError("E-mail address (%s) must include domain" %
                                addr)
        lp, dom = addr.split('@')
        if addr != addr.lower() and \
           dom not in cereconf.LDAP['rewrite_email_domain']:
            raise CerebrumError(
                "E-mail address (%s) can't contain upper case letters" % addr)
        if not with_checks:
            return lp, dom
        ea = Email.EmailAddress(self.db)
        if not ea.validate_localpart(lp):
            raise CerebrumError("Invalid localpart '%s'" % lp)
        return lp, dom
Example #20
0
 def read_spam(self):
     mail_spam = Email.EmailSpamFilter(self._db)
     for row in mail_spam.list_email_spam_filters_ext():
         self.targ2spam[int(row['target_id'])] = [
             row['level'],
             self.spam_act2dig.get(row['code_str'], '0')
         ]
Example #21
0
    def _pick_email_server(self):
        # We try to spread the usage across servers, but want a
        # random component to the choice of server.  The choice is
        # weighted, although the determination of weights happens
        # externally to Cerebrum since it is a relatively
        # expensive operation (can take several seconds).
        # Typically the weight will vary with the amount of users
        # already assigned, the disk space available or similar
        # criteria.
        #
        # Servers MUST have a weight trait to be considered for
        # allocation.
        es = Email.EmailServer(self._db)
        user_weight = {}
        total_weight = 0
        for row in es.list_traits(self.const.trait_email_server_weight):
            total_weight += row['numval']
            user_weight[row['entity_id']] = row['numval']

        pick = random.randint(0, total_weight - 1)
        for svr_id in user_weight:
            pick -= user_weight[svr_id]
            if pick <= 0:
                break
        return svr_id
Example #22
0
def main():
    global db, co, ac, p, ou, et, logger

    logger = Factory.get_logger("cronjob")

    db = Factory.get('Database')()
    co = Factory.get('Constants')(db)
    ac = Factory.get('Account')(db)
    p = Factory.get('Person')(db)
    ou = Factory.get('OU')(db)
    et = Email.EmailTarget(db)

    txt_path = "/cerebrum/var/cache/txt"

    options, rest = getopt.getopt(sys.argv[1:], "t:", [
        "txt-path=",
    ])
    for option, value in options:
        if option in ("-t", "--txt-path"):
            txt_path = value

    # Load dicts with misc info.
    get_account_info()
    get_person_contact()

    # Dump OFK info
    f = SimilarSizeWriter("%s/ofk.txt" % txt_path, "w")
    f.max_pct_change = 10
    users = process_txt_file(f)
    f.close()
    def __init__(self, db):
        """ Cache data for this iterable object. """
        co = Factory.get('Constants')(db)
        ac = Factory.get('Account')(db)
        pe = Factory.get('Person')(db)
        ou = Factory.get('OU')(db)
        et = Email.EmailTarget(db)

        self.db = db

        logger.debug("caching spreads ...")
        self.account_spreads = set(
            (row['entity_id']
             for row in ac.list_all_with_spread(co.spread_oid_acc)))
        self.ou_spreads = set(
            (row['entity_id']
             for row in ou.list_all_with_spread(co.spread_oid_ou)))

        logger.debug("... email addresses ...")
        self.account_id_to_email = dict(
            (int(row['target_entity_id']), format_email(row))
            for row in et.list_email_target_primary_addresses())

        logger.debug("... names ...")
        self.person_id_to_name = pe.getdict_persons_names(
            source_system=co.system_cached,
            name_types=(co.name_first, co.name_last))

        logger.debug("... external ids ...")
        self.person_id_to_extid = dict(
            (int(row['entity_id']), row['external_id'])
            for row in pe.search_external_ids(id_type=co.externalid_fodselsnr,
                                              fetchall=False))

        logger.debug("... auth data ...")
        self.account_id_to_auth = dict()
        for row in ac.list_account_authentication(
                auth_type=(co.auth_type_md4_nt, co.auth_type_plaintext)):
            account_id = int(row['account_id'])
            if row['method'] is None:
                continue
            if account_id not in self.account_id_to_auth:
                self.account_id_to_auth[account_id] = [
                    row['entity_name'], dict()
                ]
            self.account_id_to_auth[account_id][1].setdefault(
                int(row['method']), row['auth_data'])

        logger.debug("... account data ...")
        self.person_id_to_account_id = dict(
            (int(row['person_id']), int(row['account_id']))
            for row in ac.list_accounts_by_type(primary_only=True))

        logger.debug("... ou data ...")
        self.ou_id_to_name = dict((r["entity_id"], r["name"])
                                  for r in ou.search_name_with_language(
                                      entity_type=co.entity_ou,
                                      name_variant=co.ou_name_acronym,
                                      name_language=co.language_nb))
        logger.debug("... done caching data")
Example #24
0
    def delete_spread(self, spread):
        #
        # Pre-remove checks
        #
        spreads = [int(r['spread']) for r in self.get_spread()]
        if not spread in spreads:  # user doesn't have this spread
            return

        # (Try to) perform the actual spread removal.
        ret = self.__super.delete_spread(spread)
        # Post-removal clean up
        if spread == self.const.spread_exchange_account:
            try:
                self.delete_trait(self.const.trait_exchange_mdb)
                self.write_db()
            except Errors.NotFoundError:
                pass
            try:
                et = Email.EmailTarget(self._db)
                et.find_by_target_entity(self.entity_id)
                et.email_target_type = self.const.email_target_deleted
                et.write_db()
            except Errors.NotFoundError:
                pass
        return ret
Example #25
0
def register_email_server(email_srv_type, email_srv_name, description):
    email_server = Email.EmailServer(db)

    try:
        email_srv_type = const.EmailServerType(email_srv_type)
        int(email_srv_type)
    except Errors.NotFoundError:
        logger.error("Unknown email server type: %s. Entry skipped",
                     email_srv_type)
        return

    try:
        email_server.find_by_name(email_srv_name)
        email_server.email_server_type=email_srv_type
        email_server.description=description
    except Errors.NotFoundError:
        try:
            host = Factory.get('Host')(db)
            host.find_by_name(email_srv_name)
            email_server.populate(email_srv_type, parent=host.entity_id)
        except Errors.NotFoundError:
            email_server.populate(email_srv_type, name=email_srv_name, description=description)
    try:
        email_server.write_db()
        logger.debug("Registered email server %s", email_srv_name)
    except Errors.DatabaseException:
        logger.error("Could not write to the Cerebrum-database")
        sys.exit(3)
Example #26
0
    def update_email_addresses(self):
        # Overriding default update_email_addresses as NIH does not require
        # email_server, Jazz, 2011-05-22
        # Find, create or update a proper EmailTarget for this
        # account.
        et = Email.EmailTarget(self._db)
        target_type = self.const.email_target_account
        if self.is_expired() or self.is_reserved():
            target_type = self.const.email_target_deleted
        changed = False
        try:
            et.find_by_email_target_attrs(target_entity_id=self.entity_id)
            if et.email_target_type != target_type:
                changed = True
                et.email_target_type = target_type
        except Errors.NotFoundError:
            # We don't want to create e-mail targets for reserved or
            # deleted accounts, but we do convert the type of existing
            # e-mail targets above.
            if target_type == self.const.email_target_deleted:
                return
            et.populate(target_type, self.entity_id, self.const.entity_account)
        et.write_db()
        # For deleted/reserved users, set expire_date for all of the
        # user's addresses, and don't allocate any new addresses.
        ea = Email.EmailAddress(self._db)
        if changed and cereconf.EMAIL_EXPIRE_ADDRESSES is not False:
            if target_type == self.const.email_target_deleted:
                seconds = cereconf.EMAIL_EXPIRE_ADDRESSES * 86400
                expire_date = self._db.DateFromTicks(time.time() + seconds)
            else:
                expire_date = None
            for row in et.get_addresses():
                ea.clear()
                ea.find(row['address_id'])
                ea.email_addr_expire_date = expire_date
                ea.write_db()
        # Active accounts shouldn't have an alias value (it is used
        # for failure messages)
        if changed and target_type == self.const.email_target_account:
            if et.email_target_alias is not None:
                et.email_target_alias = None
                et.write_db()

        if target_type == self.const.email_target_deleted:
            return
        self._update_email_address_domains(et)
Example #27
0
def get_email_hardquota(user_id, local_db=db):
    eq = Email.EmailQuota(local_db)
    try:
        eq.find_by_target_entity(user_id)
    except Errors.NotFoundError:
        # unlimited/no quota
        return 0
    return eq.email_quota_hard
Example #28
0
 def validate_new_uname(self, domain, uname):
     """Check that the requested username is legal and free"""
     # TBD: will domain ever be anything else?
     if domain == self.const.account_namespace:
         ea = Email.EmailAddress(self._db)
         for row in ea.search(local_part=uname, filter_expired=False):
             return False
     return self.__super.validate_new_uname(domain, uname)
Example #29
0
 def _UiO_default_spam_settings(self, email_target):
     t_id = email_target.entity_id
     tt_str = str(Email._EmailTargetCode(email_target.email_target_type))
     # Set default spam settings if none found on this target
     esf = Email.EmailSpamFilter(self._db)
     if cereconf.EMAIL_DEFAULT_SPAM_SETTINGS.has_key(tt_str):
         if not len(cereconf.EMAIL_DEFAULT_SPAM_SETTINGS[tt_str]) == 2:
             raise Errors.CerebrumError, "Error in " + "cereconf.EMAIL_DEFAULT_SPAM_SETTINGS. Expected 'key': " + "('val', 'val')"
         l, a = cereconf.EMAIL_DEFAULT_SPAM_SETTINGS[tt_str]
         lvl = int(Email._EmailSpamLevelCode(l))
         act = int(Email._EmailSpamActionCode(a))
         try:
             esf.find(t_id)
         except Errors.NotFoundError:
             esf.clear()
             esf.populate(lvl, act, parent=email_target)
             esf.write_db()
Example #30
0
 def _update_email_server(self, server_name):
     es = Email.EmailServer(self._db)
     et = Email.EmailTarget(self._db)
     es.find_by_name(server_name)
     try:
         et.find_by_email_target_attrs(target_entity_id = self.entity_id)
     except Errors.NotFoundError:
         # Not really sure about this. it is done at UiO, but maybe it is not
         # right to make en email_target if one is not found??
         et.clear()
         et.populate(self.const.email_target_account,
                     self.entity_id,
                     self.const.entity_account)
         et.write_db()
     et.email_server_id = es.entity_id
     et.write_db()
     return et
Example #31
0
def proc_email_create(r):
    hq = get_email_hardquota(r['entity_id'])
    es = None
    if r['destination_id']:
        es = Email.EmailServer(db)
        es.find(r['destination_id'])
    return (cyrus_create(r['entity_id'], host=es) and
            cyrus_set_quota(r['entity_id'], hq, host=es))
def connect_domain_ou(ou_id, dom_id, c_aff):
    ee_dom = Email.EntityEmailDomain(db)
    ee_dom.clear()
    try:
        ee_dom.find(ou_id, c_aff)
    except Errors.NotFoundError:
        ee_dom.populate_email_domain(dom_id, c_aff)
        ee_dom.write_db()
Example #33
0
 def get_primary_maildomain(self):
     """Return correct `domain_id' for account's primary address."""
     dom = Email.EmailDomain(self._db)
     dom.find_by_domain(Email.get_primary_default_email_domain())
     entdom = Email.EntityEmailDomain(self._db)
     # Find OU and affiliation for this user's best-priority
     # account_type entry.
     for row in self.get_account_types():
         ou, aff = row['ou_id'], row['affiliation']
         # If a maildomain is associated with this (ou, aff)
         # combination, then that is the user's default maildomain.
         entdom.clear()
         try:
             entdom.find(ou, affiliation=aff)
             #
             # This if-test assumes that the cereconf.EMAIL_DEFAULT_DOMAIN
             # cannot be considered as a primary domain if another
             # valid domain is found for an account. The behaviour is wrong
             # for ØFK as quite av few of the accounts should have primary
             # addresses in default domain while they have other domains
             # Jazz
             #
             # If the default domain is specified, ignore this
             # affiliation.
             #     if entdom.entity_email_domain_id == dom.entity_id:
             #         continue
             return entdom.entity_email_domain_id
         except Errors.NotFoundError:
             pass
         # Otherwise, try falling back to tha maildomain associated
         # with (ou, None).
         entdom.clear()
         try:
             entdom.find(ou)
             if entdom.entity_email_domain_id == dom.entity_id:
                 continue
             return entdom.entity_email_domain_id
         except Errors.NotFoundError:
             pass
     # Still no proper maildomain association has been found; fall
     # back to default maildomain.
     return dom.entity_id
Example #34
0
    def update_email_addresses(self):
        # Find, create or update a proper EmailTarget for this
        # account.
        et = Email.EmailTarget(self._db)
        target_type = self.const.email_target_account
        if self.is_expired():
            target_type = self.const.email_target_deleted
        changed = False
        try:
            et.find_by_email_target_attrs(target_entity_id=self.entity_id)
            if et.email_target_type != target_type:
                changed = True
                et.email_target_type = target_type
        except Errors.NotFoundError:
            # We don't want to create e-mail targets for reserved or
            # deleted accounts, but we do convert the type of existing
            # e-mail targets above.
            if target_type == self.const.email_target_deleted:
                return
            et.populate(target_type, self.entity_id, self.const.entity_account)
        et.write_db()
        # For deleted/reserved users, set expire_date for all of the
        # user's addresses, and don't allocate any new addresses.
        ea = Email.EmailAddress(self._db)
        if changed and cereconf.EMAIL_EXPIRE_ADDRESSES is not False:
            if target_type == self.const.email_target_deleted:
                seconds = cereconf.EMAIL_EXPIRE_ADDRESSES * 86400
                expire_date = self._db.DateFromTicks(time.time() + seconds)
            else:
                expire_date = None
            for row in et.get_addresses():
                ea.clear()
                ea.find(row['address_id'])
                ea.email_addr_expire_date = expire_date
                ea.write_db()
        # Active accounts shouldn't have an alias value (it is used
        # for failure messages)
        if changed and target_type == self.const.email_target_account:
            if et.email_target_alias is not None:
                et.email_target_alias = None
                et.write_db()

        if target_type == self.const.email_target_deleted:
            return
        # Figure out which domain(s) the user should have addresses
        # in.  Primary domain should be at the front of the resulting
        # list.
        ed = Email.EmailDomain(self._db)
        ed.find(self.get_primary_maildomain())
        domains = [ed.email_domain_name]

        # Add the default domains if missing
        for domain in Email.get_default_email_domains():
            if domain not in domains:
                domains.append(domain)

        # Iterate over the available domains, testing various
        # local_parts for availability.  Set user's primary address to
        # the first one found to be available.
        primary_set = False
        epat = Email.EmailPrimaryAddressTarget(self._db)
        for domain in domains:
            if ed.email_domain_name != domain:
                ed.clear()
                ed.find_by_domain(domain)
            # Check for 'uidaddr' category before 'cnaddr', to prefer
            # 'uidaddr'-style primary addresses for users in
            # maildomains that have both categories.
            ctgs = [int(r['category']) for r in ed.get_categories()]
            local_parts = []
            if int(self.const.email_domain_category_uidaddr) in ctgs:
                local_parts.append(self.account_name)
            elif int(self.const.email_domain_category_cnaddr) in ctgs:
                local_parts.append(self.get_email_cn_local_part())
                local_parts.append(self.account_name)
            for lp in local_parts:
                lp = self.wash_email_local_part(lp)
                # Is the address taken?
                ea.clear()
                try:
                    ea.find_by_local_part_and_domain(lp, ed.entity_id)
                    if ea.email_addr_target_id != et.entity_id:
                        # Address already exists, and points to a
                        # target not owned by this Account.
                        #
                        # TODO: An expired address gets removed by a
                        # database cleaning job, and when it's gone,
                        # the address will eventually be recreated
                        # connected to this target.
                        continue
                except Errors.NotFoundError:
                    # Address doesn't exist; create it.
                    ea.populate(lp, ed.entity_id, et.entity_id,
                                expire=None)
                ea.write_db()
                if not primary_set:
                    epat.clear()
                    try:
                        epat.find(ea.email_addr_target_id)
                        epat.populate(ea.entity_id)
                    except Errors.NotFoundError:
                        epat.clear()
                        epat.populate(ea.entity_id, parent=et)
                    epat.write_db()
                    primary_set = True
Example #35
0
    def update_email_addresses(self):
        # Find, create or update a proper EmailTarget for this
        # account.
        et = Email.EmailTarget(self._db)
        old_server = None
        target_type = self.const.email_target_account
        if self.is_deleted() or self.is_reserved():
            target_type = self.const.email_target_deleted
        try:
            et.find_by_email_target_attrs(target_entity_id=self.entity_id)
            et.email_target_type = target_type
        except Errors.NotFoundError:
            # We don't want to create e-mail targets for reserved or
            # deleted accounts, but we do convert the type of existing
            # e-mail targets above.
            if target_type == self.const.email_target_deleted:
                return
            et.populate(target_type, self.entity_id, self.const.entity_account)
        et.write_db()
        # For deleted/reserved users, set expire_date for all of the
        # user's addresses, and don't allocate any new addresses.
        ea = Email.EmailAddress(self._db)
        if target_type == self.const.email_target_deleted:
            expire_date = self._db.DateFromTicks(time.time() +
                                                 60 * 60 * 24 * 180)
            for row in et.get_addresses():
                ea.clear()
                ea.find(row['address_id'])
                if ea.email_addr_expire_date is None:
                    ea.email_addr_expire_date = expire_date
                ea.write_db()
            return
        # if an account without email_server_target is found assign
        # the appropriate server
        old_server = et.email_server_id
        acc_types = self.get_account_types()
        entity = Factory.get("Entity")(self._db)
        try:
            entity.clear()
            entity.find(self.owner_id)
        except Errors.NotFoundError:
            pass

        if not old_server:
            # if self.is_fag_employee():
            #    self._update_email_server('mail.f*g.hiof.no')
            # elif self.is_adm_employee():
            #    self._update_email_server('mail.adm.hiof.no')
            #
            # This updates email servers for employees and students
            if entity.entity_type != self.const.entity_group:
                self._update_email_server('epost.hiof.no')

        # Figure out which domain(s) the user should have addresses
        # in.  Primary domain should be at the front of the resulting
        # list.
        # if the only address found is in EMAIL_DEFAULT_DOMAINS
        # don't set default address. This is done in order to prevent
        # adresses in default domain being sat as primary
        # TODO: account_types affiliated to OU's  without connected
        # email domain don't get a default address
        primary_set = False
        ed = Email.EmailDomain(self._db)
        ed.find(self.get_primary_maildomain())
        domains = [ed.email_domain_name]

        # Add the default domains if missing
        for domain in Email.get_default_email_domains():
            if domain not in domains:
                domains.append(domain)

        # Iterate over the available domains, testing various
        # local_parts for availability.  Set user's primary address to
        # the first one found to be available.
        try:
            self.get_primary_mailaddress()
        except Errors.NotFoundError:
            pass
        epat = Email.EmailPrimaryAddressTarget(self._db)
        for domain in domains:
            if ed.email_domain_name != domain:
                ed.clear()
                ed.find_by_domain(domain)
            # Check for 'cnaddr' category before 'uidaddr', to prefer
            # 'cnaddr'-style primary addresses for users in
            # maildomains that have both categories.
            ctgs = [int(r['category']) for r in ed.get_categories()]
            local_parts = []
            if int(self.const.email_domain_category_cnaddr) in ctgs:
                local_parts.append(self.get_email_cn_local_part(
                    given_names=1, max_initials=1))
                local_parts.append(self.account_name)
            elif int(self.const.email_domain_category_uidaddr) in ctgs:
                local_parts.append(self.account_name)
            for lp in local_parts:
                lp = self.wash_email_local_part(lp)
                # Is the address taken?
                ea.clear()
                try:
                    ea.find_by_local_part_and_domain(lp, ed.entity_id)
                    if ea.email_addr_target_id != et.entity_id:
                        # Address already exists, and points to a
                        # target not owned by this Account.
                        continue
                    # Address belongs to this account; make sure
                    # there's no expire_date set on it.
                    ea.email_addr_expire_date = None
                except Errors.NotFoundError:
                    # Address doesn't exist; create it.
                    ea.populate(lp, ed.entity_id, et.entity_id, expire=None)
                ea.write_db()
                # HiØ do not want the primary adress to change automatically
                if not primary_set:
                    epat.clear()
                    try:
                        epat.find(ea.email_addr_target_id)
                    except Errors.NotFoundError:
                        epat.clear()
                        epat.populate(ea.entity_id, parent=et)
                        epat.write_db()
                    primary_set = True
Example #36
0
    def update_email_addresses(self, set_primary=False):
        # check if an e-mail spread is registered yet, if not don't
        # update
        email_spreads = (self.const.spread_exchange_account,
                         self.const.spread_exchange_acc_old,
                         self.const.spread_hia_email,
                         self.const.spread_uia_office_365,
                         self.const.spread_uia_forward)
        if not any([self.has_spread(spread) for spread in email_spreads]):
            # CRB-742: If spread_uia_office_365 is removed
            #  MailTarget targettype should be set as "deleted"
            try:
                et = Email.EmailTarget(self._db)
                et.find_by_email_target_attrs(target_entity_id=self.entity_id)
                if et.email_target_type != self.const.email_target_deleted:
                    et.email_target_type = self.const.email_target_deleted
                    et.write_db()
            except Errors.NotFoundError:
                pass
            return
        # Find, create or update a proper EmailTarget for this
        # account.
        et = Email.EmailTarget(self._db)
        target_type = self.const.email_target_account
        if self.has_spread(self.const.spread_uia_forward):
            target_type = self.const.email_target_forward
        if self.is_deleted() or self.is_reserved():
            target_type = self.const.email_target_deleted
        try:
            et.find_by_email_target_attrs(target_entity_id=self.entity_id)
            et.email_target_type = target_type
        except Errors.NotFoundError:
            # We don't want to create e-mail targets for reserved or
            # deleted accounts, but we do convert the type of existing
            # e-mail targets above.
            if target_type == self.const.email_target_deleted:
                return
            et.populate(target_type, self.entity_id, self.const.entity_account)
        et.write_db()
        # For deleted/reserved users, set expire_date for all of the
        # user's addresses, and don't allocate any new addresses.
        ea = Email.EmailAddress(self._db)
        if target_type == self.const.email_target_deleted:
            expire_date = self._db.DateFromTicks(time.time() +
                                                 60 * 60 * 24 * 1)
            for row in et.get_addresses():
                ea.clear()
                ea.find(row['address_id'])
                if ea.email_addr_expire_date is None:
                    ea.email_addr_expire_date = expire_date
                ea.write_db()
            return
        # if an account email_target without email_server is found assign
        # the appropriate server based on spread and account_type
        spread = None
        if not et.email_server_id:
            if self.get_account_types() or \
               self.owner_type == self.const.entity_group:
                for s in self.get_spread():
                    if s['spread'] in (int(self.const.spread_exchange_account),
                                       int(self.const.spread_exchange_acc_old),
                                       int(self.const.spread_hia_email)):
                        spread = s['spread']
                et = self._update_email_server(spread)
            else:
                # do not set email_server_target
                # until account_type is registered
                return
        # Figure out which domain(s) the user should have addresses
        # in.  Primary domain should be at the front of the resulting
        # list.
        # if the only address found is in EMAIL_DEFAULT_DOMAIN
        # don't set default address. This is done in order to prevent
        # adresses in default domain being sat as primary
        # TODO: account_types affiliated to OU's  without connected
        # email domain don't get a default address
        primary_set = False
        ed = Email.EmailDomain(self._db)
        ed.find(self.get_primary_maildomain())
        domains = [ed.email_domain_name]

        if ed.email_domain_name == Email.get_primary_default_email_domain():
            if not self.owner_type == self.const.entity_group:
                primary_set = True

        # Add the default domains if missing
        for domain in Email.get_default_email_domains():
            if domain not in domains:
                domains.append(domain)

        # Iterate over the available domains, testing various
        # local_parts for availability.  Set user's primary address to
        # the first one found to be available.
        # Never change any existing email addresses
        try:
            self.get_primary_mailaddress()
            primary_set = True
        except Errors.NotFoundError:
            pass
        epat = Email.EmailPrimaryAddressTarget(self._db)
        for domain in domains:
            if ed.email_domain_name != domain:
                ed.clear()
                ed.find_by_domain(domain)
            # Check for 'cnaddr' category before 'uidaddr', to prefer
            # 'cnaddr'-style primary addresses for users in
            # maildomains that have both categories.
            ctgs = [int(r['category']) for r in ed.get_categories()]
            local_parts = []
            if int(self.const.email_domain_category_cnaddr) in ctgs:
                local_parts.append(
                    self.get_email_cn_local_part(
                        given_names=1,
                        max_initials=1
                    )
                )
                local_parts.append(self.account_name)
            elif int(self.const.email_domain_category_uidaddr) in ctgs:
                local_parts.append(self.account_name)
            for lp in local_parts:
                lp = self.wash_email_local_part(lp)
                # Is the address taken?
                ea.clear()
                try:
                    ea.find_by_local_part_and_domain(lp, ed.entity_id)
                    if ea.email_addr_target_id != et.entity_id:
                        # Address already exists, and points to a
                        # target not owned by this Account.
                        continue
                    # Address belongs to this account; make sure
                    # there's no expire_date set on it.
                    ea.email_addr_expire_date = None
                except Errors.NotFoundError:
                    # Address doesn't exist; create it.
                    ea.populate(lp, ed.entity_id, et.entity_id,
                                expire=None)
                ea.write_db()
                if not primary_set:
                    epat.clear()
                    try:
                        epat.find(ea.email_addr_target_id)
                        epat.populate(ea.entity_id)
                    except Errors.NotFoundError:
                        epat.clear()
                        epat.populate(ea.entity_id, parent=et)
                    epat.write_db()
                    primary_set = True
                self.update_email_quota()