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 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 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()