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()
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()
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()
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()
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
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))
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'])
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)
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
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
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'
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()
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()
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)}
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, }
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
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
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') ]
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
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")
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
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)
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)
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
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)
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()
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
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()
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
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
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
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()