def fetch_forward_info(self): """ Fetch forward info for all users with both AD and exchange spread. """ # from Cerebrum.modules.Email import EmailDomain from Cerebrum.modules.Email import EmailTarget from Cerebrum.modules.Email import EmailForward etarget = EmailTarget(self.db) # rewrite = EmailDomain(self.db).rewrite_special_domains eforward = EmailForward(self.db) # We need a email target -> entity_id mapping target_id2target_entity_id = {} for row in etarget.list_email_targets_ext(): if row['target_entity_id']: te_id = int(row['target_entity_id']) target_id2target_entity_id[int(row['target_id'])] = te_id # Check all email forwards for row in eforward.list_email_forwards(): te_id = target_id2target_entity_id.get(int(row['target_id'])) acc = self.get_account(account_id=te_id) # We're only interested in those with AD and exchange spread if acc.to_exchange: acc.add_forward(row['forward_to'])
def get_entities_with_primary_addr(db): """ Get the target entity_id of primary email addresses. """ et = EmailTarget(db) for r in et.list_email_target_primary_addresses(): if r['target_entity_id'] is None: # Some targets don't have a target entity (sympa, rt, pipes, ...) continue yield int(r['target_entity_id'])
def get_accounts(db, spread, include_expired=False, exclude_groups=None): """Fetch a list of all accounts with a entity_person owner and IMAP-spread. @param spread_name: Name of spread to filter user search by. @type spread_name: String @param expired: If True, include expired accounts. Defaults to False. @type expired: bool @param exclude: List of group name strings to exclude. Accounts that are members of this group are excluded from the report. Defaults to None. @type exclude: List of strings @return List of account names that is missing a primary email address. """ # Database-setup co = Factory.get('Constants')(db) ac = Factory.get('Account')(db) et = EmailTarget(db) search_args = {'owner_type': co.entity_person} if include_expired: search_args['expire_start'] = None logger.debug('looking up excluded groups...') excluded = ExcludeLookup(db, exclude_groups) logger.debug('caching accounts spreads...') account_spreads = SpreadLookup(db, co.entity_account) # for account in accounts: for account in ac.search(**search_args): if account['account_id'] not in account_spreads: # is_deleted() or is_reserved() continue if int(spread) in account_spreads[account['account_id']]: continue if account['account_id'] in excluded: logger.debug('Ignoring %s (%d), member of excluded group', account['name']) continue # Find EmailTarget for account et.clear() try: et.find_by_target_entity(account['account_id']) except Errors.NotFoundError: logger.info('No email targets for account with id %d', account['account_id']) continue if et.email_target_type == co.email_target_account: yield account['name']
def handle_person(database, source_system, affiliations, send_notifications, email_config, data): pe = Factory.get('Person')(database) ac = Factory.get('Account')(database) et = EmailTarget(database) ef = EmailForward(database) ed = EmailDomain(database) if (data.get('resourceType') == 'persons' and 'affiliation' in data.get( 'urn:ietf:params:event:SCIM:modify', {}).get( 'attributes', [])): ident = int(data.get('sub').split('/')[-1]) if not pe.list_affiliations( person_id=ident, source_system=source_system, affiliation=affiliations): return pe.clear() pe.find(ident) removed_forwards = defaultdict(list) for account_id in map(lambda x: x['account_id'], pe.get_accounts( filter_expired=False)): try: et.clear() et.find_by_target_entity(account_id) except Errors.NotFoundError: continue ef.clear() ef.find(et.entity_id) for forward in map(lambda x: x['forward_to'], ef.get_forward()): try: ed.clear() ed.find_by_domain(forward.split('@')[-1]) except Errors.NotFoundError: ac.clear() ac.find(account_id) ef.delete_forward(forward) removed_forwards[ac.get_primary_mailaddress() ].append(forward) logger.info( 'Deleted forward {} from {}'.format( forward, ac.account_name)) if send_notifications: for k, v in removed_forwards.items(): sendmail( toaddr=k, fromaddr=email_config.sender, subject=email_config.subject, body=email_config.body_template.format('\n'.join(v))) database.commit()
def init_account_mail(self, use_mail_module): u""" Cache account mail addresses. This method adds to the general to fill the primary email attribute This is done to prepare for changing the normal email attribute :param bool use_mail_module: If True, Cerebrum.modules.Email will be used to populate this cache; otherwise the `self.account_mail` dict will be None. """ super(OrgLDIFUiOMixin, self).init_account_mail(use_mail_module) if use_mail_module: timer = make_timer( self.logger, "Doing UiO specific changes to account e-mail addresses...") self.account_primary_mail = self.account_mail.copy() # We don't want to import this if mod_email isn't present. from Cerebrum.modules.Email import EmailTarget targets = EmailTarget(self.db).list_email_target_addresses mail = {} for row in targets(target_type=self.const.email_target_account, domain='uio.no', uname_local=True): # Can only return [email protected] so no need for any checks mail[int(row['target_entity_id'])] = "@".join( (row['local_part'], row['domain'])) self.account_mail.update(mail) timer("...UiO specfic account e-mail addresses done.")
def init_account_mail(self, use_mail_module): u""" Cache account mail addresses. This method builds a dict cache that maps account_id -> primary email address, and assigns the `dict.get` method to `self.account_mail`. NOTE: The LDAP_PERSON['mail_target_types'] setting decides which email target types are considered. :param bool use_mail_module: If True, Cerebrum.modules.Email will be used to populate this cache; otherwise the `self.account_mail` method will be None (not implemented). """ # Set self.account_mail = None if not use_mail_module, otherwise # function: account_id -> ('address' or None). if use_mail_module: timer = make_timer(self.logger, "Fetching account e-mail addresses...") # Get target types from config mail_target_types = [] for value in ldapconf('PERSON', 'mail_target_types', []): code = self.const.human2constant(value, self.const.EmailTarget) if code is None: self.logger.warn("Unknown EmailTarget %r in setting %s", value, "LDAP_PERSON['mail_target_types']") else: mail_target_types.append(code) # We don't want to import this if mod_email isn't present. from Cerebrum.modules.Email import EmailDomain, EmailTarget targets = EmailTarget(self.db).list_email_target_primary_addresses rewrite = EmailDomain(self.db).rewrite_special_domains # Look up target addrs. Note that the reversed order causes the # lesser prioritized target types to be overwritten by targets with # higher priority. mail = {} for code in reversed(mail_target_types): target_timer = make_timer(self.logger) for row in targets(target_type=code): try: mail[int(row['target_entity_id'])] = "@".join( (row['local_part'], rewrite(row['domain']))) except TypeError: continue target_timer("...target_type '{!s}' done".format(code)) self.account_mail = mail.get timer("...account e-mail addresses done.") else: self.account_mail = None
def _fetch_primary_mail_addresses(self, user_dict): """ Fetch primary email addresses for users in user_dict. Add key, value pair 'mail', <primary address> if found. @param user_dict: account_id -> account info mapping @type user_dict: dict """ from Cerebrum.modules.Email import EmailDomain, EmailTarget etarget = EmailTarget(self.db) rewrite = EmailDomain(self.db).rewrite_special_domains for row in etarget.list_email_target_primary_addresses( target_type=self.co.email_target_account): v = user_dict.get(int(row['target_entity_id'])) if not v: continue try: v['mail'] = "@".join( (row['local_part'], rewrite(row['domain']))) except TypeError: pass # Silently ignore
def handle_person(database, source_system, affiliations, send_notifications, email_config, data): pe = Factory.get('Person')(database) ac = Factory.get('Account')(database) et = EmailTarget(database) ef = EmailForward(database) ed = EmailDomain(database) if (data.get('resourceType') == 'persons' and 'affiliation' in data.get( 'urn:ietf:params:event:SCIM:modify', {}).get('attributes', [])): ident = int(data.get('sub').split('/')[-1]) if not pe.list_affiliations(person_id=ident, source_system=source_system, affiliation=affiliations): return pe.clear() pe.find(ident) removed_forwards = defaultdict(list) for account_id in map(lambda x: x['account_id'], pe.get_accounts(filter_expired=False)): try: et.clear() et.find_by_target_entity(account_id) except Errors.NotFoundError: continue ef.clear() ef.find(et.entity_id) for forward in map(lambda x: x['forward_to'], ef.get_forward()): try: ed.clear() ed.find_by_domain(forward.split('@')[-1]) except Errors.NotFoundError: ac.clear() ac.find(account_id) ef.delete_forward(forward) removed_forwards[ac.get_primary_mailaddress()].append( forward) logger.info('Deleted forward {} from {}'.format( forward, ac.account_name)) if send_notifications: for k, v in removed_forwards.items(): sendmail(toaddr=k, fromaddr=email_config.sender, subject=email_config.subject, body=email_config.body_template.format('\n'.join(v))) database.commit()
def get_accs_with_missing_mail_spread(logger, spread_name, expired, exclude): """Fetch a list of all accounts with a entity_person owner and IMAP-spread. @param logger: Logger to use. @type logger: CerebrumLogger @param spread_name: Name of spread to filter user search by. @type spread_name: String @param expired: If True, include expired accounts. Defaults to False. @type expired: bool @param exclude: List of group name strings to exclude. Accounts that are members of this group are excluded from the report. Defaults to None. @type exclude: List of strings @return List of account names that is missing a primary email address. """ # Database-setup db = Factory.get('Database')() co = Factory.get('Constants')(db) ac = Factory.get('Account')(db) gr = Factory.get('Group')(db) et = EmailTarget(db) try: spread = getattr(co, spread_name) except AttributeError: logger.error('Spread not found, exiting..') sys.exit(2) users_wo_mail_spread = [] # List to contain results group_ids = group_names_to_gids(logger, gr, exclude) # Fetch account list if expired: accounts = ac.search(owner_type=co.entity_person, expire_start=None) else: accounts = ac.search(owner_type=co.entity_person) for account in accounts: ac.clear() try: ac.find(account['account_id']) except Errors.NotFoundError, e: logger.error('Can\'t find account with id \'%d\'' % account['account_id']) continue # Ignore if account is deleted or reserved if ac.is_deleted() or ac.is_reserved(): continue # Ignore if account has imap spread if spread in [row['spread'] for row in ac.get_spread()]: continue # Check for group membership gr.clear() is_member = False for group_id in group_ids: try: gr.find(group_id) if gr.has_member(ac.entity_id): is_member = True logger.debug('Ignoring %(account)s, member of %(group)s' % {"account":ac.account_name, "group":gr.group_name}) break except Errors.NotFoundError, e: logger.error('Can\'t find group with id %d' % group_id) continue