Ejemplo n.º 1
0
def main():
    parser, opts, args = parseargs()
    config.load(opts.config)

    listnames = opts.listnames or config.list_manager.names
    includes = set(listname.lower() for listname in listnames)
    excludes = set(listname.lower() for listname in opts.excludes)
    listnames = includes - excludes

    if not listnames:
        print _('No lists to search')
        return

    cres = []
    for r in args:
        cres.append(re.compile(r, re.IGNORECASE))
    # dictionary of {address, (listname, ownerp)}
    matches = {}
    for listname in listnames:
        try:
            mlist = MailList.MailList(listname, lock=False)
        except errors.MMListError:
            print _('No such list: $listname')
            continue
        if opts.owners:
            owners = mlist.owner
        else:
            owners = []
        for cre in cres:
            for member in mlist.getMembers():
                if cre.search(member):
                    addr = mlist.getMemberCPAddress(member)
                    entries = matches.get(addr, {})
                    aswhat = entries.get(listname, 0)
                    aswhat |= AS_MEMBER
                    entries[listname] = aswhat
                    matches[addr] = entries
            for owner in owners:
                if cre.search(owner):
                    entries = matches.get(owner, {})
                    aswhat = entries.get(listname, 0)
                    aswhat |= AS_OWNER
                    entries[listname] = aswhat
                    matches[owner] = entries
    addrs = matches.keys()
    addrs.sort()
    for k in addrs:
        hits = matches[k]
        lists = hits.keys()
        print k, _('found in:')
        for name in lists:
            aswhat = hits[name]
            if aswhat & AS_MEMBER:
                print '    ', name
            if aswhat & AS_OWNER:
                print '    ', name, _('(as owner)')
Ejemplo n.º 2
0
def process_lists(glock):
    for listname in config.list_manager.names:
        glock.refresh()
        # Open the list unlocked just to check to see if it is gating news to
        # mail.  If not, we're done with the list.  Otherwise, lock the list
        # and gate the group.
        mlist = MailList.MailList(listname, lock=False)
        if not mlist.gateway_to_mail:
            continue
        # Get the list's watermark, i.e. the last article number that we gated
        # from news to mail.  None means that this list has never polled its
        # newsgroup and that we should do a catch up.
        watermark = getattr(mlist, 'usenet_watermark', None)
        # Open the newsgroup, but let most exceptions percolate up.
        try:
            conn, first, last = open_newsgroup(mlist)
        except (socket.error, nntplib.NNTPError):
            break
        log.info('%s: [%d..%d]', listname, first, last)
        try:
            try:
                if watermark is None:
                    mlist.Lock(timeout=config.LIST_LOCK_TIMEOUT)
                    # This is the first time we've tried to gate this
                    # newsgroup.  We essentially do a mass catch-up, otherwise
                    # we'd flood the mailing list.
                    mlist.usenet_watermark = last
                    log.info('%s caught up to article %d', listname, last)
                else:
                    # The list has been polled previously, so now we simply
                    # grab all the messages on the newsgroup that have not
                    # been seen by the mailing list.  The first such article
                    # is the maximum of the lowest article available in the
                    # newsgroup and the watermark.  It's possible that some
                    # articles have been expired since the last time gate_news
                    # has run.  Not much we can do about that.
                    start = max(watermark + 1, first)
                    if start > last:
                        log.info('nothing new for list %s', listname)
                    else:
                        mlist.Lock(timeout=config.LIST_LOCK_TIMEOUT)
                        log.info('gating %s articles [%d..%d]', listname,
                                 start, last)
                        # Use last+1 because poll_newsgroup() employes a for
                        # loop over range, and this will not include the last
                        # element in the list.
                        poll_newsgroup(mlist, conn, start, last + 1, glock)
            except TimeOutError:
                log.error('Could not acquire list lock: %s', listname)
        finally:
            if mlist.Locked():
                mlist.Save()
                mlist.Unlock()
        log.info('%s watermark: %d', listname, mlist.usenet_watermark)
Ejemplo n.º 3
0
def main():
    opts, args, parser = parseargs()
    initialize(opts.config)

    for name in config.list_manager.names:
        # The list must be locked in order to open the requests database
        mlist = MailList.MailList(name)
        try:
            count = IListRequests(mlist).count
            # While we're at it, let's evict yesterday's autoresponse data
            midnight_today = midnight()
            evictions = []
            for sender in mlist.hold_and_cmd_autoresponses.keys():
                date, respcount = mlist.hold_and_cmd_autoresponses[sender]
                if midnight(date) < midnight_today:
                    evictions.append(sender)
            if evictions:
                for sender in evictions:
                    del mlist.hold_and_cmd_autoresponses[sender]
                # This is the only place we've changed the list's database
                mlist.Save()
            if count:
                # Set the default language the the list's preferred language.
                _.default = mlist.preferred_language
                realname = mlist.real_name
                discarded = auto_discard(mlist)
                if discarded:
                    count = count - discarded
                    text = _('Notice: $discarded old request(s) '
                             'automatically expired.\n\n')
                else:
                    text = ''
                if count:
                    text += Utils.maketext(
                        'checkdbs.txt', {
                            'count': count,
                            'mail_host': mlist.mail_host,
                            'adminDB': mlist.GetScriptURL('admindb',
                                                          absolute=1),
                            'real_name': realname,
                        },
                        mlist=mlist)
                    text += '\n' + pending_requests(mlist)
                    subject = _('$count $realname moderator '
                                'request(s) waiting')
                else:
                    subject = _('$realname moderator request check result')
                msg = UserNotification(mlist.GetOwnerEmail(),
                                       mlist.GetBouncesEmail(), subject, text,
                                       mlist.preferred_language)
                msg.send(mlist, **{'tomoderators': True})
        finally:
            mlist.Unlock()
Ejemplo n.º 4
0
def main():
    opts, args, parser = parseargs()
    config.load(opts.config)

    listnames = set(args or config.list_manager.names)
    if not listnames:
        print(_('Nothing to do.'))
        sys.exit(0)

    for listname in listnames:
        try:
            # Be sure the list is locked
            mlist = MailList.MailList(listname)
        except errors.MMListError:
            parser.print_help()
            print(_('No such list: $listname'), file=sys.stderr)
            sys.exit(1)
        try:
            mlist.bump_digest_volume()
        finally:
            mlist.Save()
            mlist.Unlock()
Ejemplo n.º 5
0
def do_output(listname, outfile, parser):
    closep = False
    try:
        if outfile == '-':
            outfp = sys.stdout
        else:
            outfp = open(outfile, 'w')
            closep = True
        # Open the specified list unlocked, since we're only reading it.
        try:
            mlist = MailList.MailList(listname, lock=False)
        except errors.MMListError:
            parser.error(_('No such list: $listname'))
        # Preamble for the config info. PEP 263 charset and capture time.
        charset = mlist.preferred_language.charset
        # Set the system's default language.
        _.default = mlist.preferred_language.code
        if not charset:
            charset = 'us-ascii'
        when = time.ctime(time.time())
        print >> outfp, _('''\
# -*- python -*-
# -*- coding: $charset -*-
## "$listname" mailing list configuration settings
## captured on $when
''')
        # Get all the list config info.  All this stuff is accessible via the
        # web interface.
        for k in config.ADMIN_CATEGORIES:
            subcats = mlist.GetConfigSubCategories(k)
            if subcats is None:
                do_list_categories(mlist, k, None, outfp)
            else:
                for subcat in [t[0] for t in subcats]:
                    do_list_categories(mlist, k, subcat, outfp)
    finally:
        if closep:
            outfp.close()
Ejemplo n.º 6
0
def main():
    opts, args, parser = parseargs()
    initialize(opts.config)

    for listname in set(opts.listnames or config.list_manager.names):
        mlist = MailList.MailList(listname, lock=False)
        if mlist.digest_send_periodic:
            mlist.Lock()
            try:
                try:
                    mlist.send_digest_now()
                    mlist.Save()
                # We are unable to predict what exception may occur in digest
                # processing and we don't want to lose the other digests, so
                # we catch everything.
                except Exception as errmsg:
                    print >> sys.stderr, \
                      'List: %s: problem processing %s:\n%s' % \
                        (listname,
                         os.path.join(mlist.data_path, 'digest.mbox'),
                         errmsg)
            finally:
                mlist.Unlock()
Ejemplo n.º 7
0
def do_input(listname, infile, checkonly, verbose, parser):
    fakedoc = FakeDoc()
    # Open the specified list locked, unless checkonly is set
    try:
        mlist = MailList.MailList(listname, lock=not checkonly)
    except errors.MMListError as error:
        parser.error(_('No such list "$listname"\n$error'))
    savelist = False
    guibyprop = getPropertyMap(mlist)
    try:
        globals = {'mlist': mlist}
        # Any exception that occurs in execfile() will cause the list to not
        # be saved, but any other problems are not save-fatal.
        execfile(infile, globals)
        savelist = True
        for k, v in globals.items():
            if k in ('mlist', '__builtins__'):
                continue
            if not hasattr(mlist, k):
                print >> sys.stderr, _('attribute "$k" ignored')
                continue
            if verbose:
                print >> sys.stderr, _('attribute "$k" changed')
            missing = []
            gui, wtype = guibyprop.get(k, (missing, missing))
            if gui is missing:
                # This isn't an official property of the list, but that's
                # okay, we'll just restore it the old fashioned way
                print >> sys.stderr, _('Non-standard property restored: $k')
                setattr(mlist, k, v)
            else:
                # BAW: This uses non-public methods.  This logic taken from
                # the guts of GUIBase.handleForm().
                try:
                    validval = gui._getValidValue(mlist, k, wtype, v)
                except ValueError:
                    print >> sys.stderr, _('Invalid value for property: $k')
                except errors.EmailAddressError:
                    print >> sys.stderr, _(
                        'Bad email address for option $k: $v')
                else:
                    # BAW: Horrible hack, but then this is special cased
                    # everywhere anyway. :(  Privacy._setValue() knows that
                    # when ALLOW_OPEN_SUBSCRIBE is false, the web values are
                    # 0, 1, 2 but these really should be 1, 2, 3, so it adds
                    # one.  But we really do provide [0..3] so we need to undo
                    # the hack that _setValue adds. :( :(
                    if k == 'subscribe_policy' and \
                           not config.ALLOW_OPEN_SUBSCRIBE:
                        validval -= 1
                    # BAW: Another horrible hack.  This one is just too hard
                    # to fix in a principled way in Mailman 2.1
                    elif k == 'new_member_options':
                        # Because this is a Checkbox, _getValidValue()
                        # transforms the value into a list of one item.
                        validval = validval[0]
                        validval = [
                            bitfield
                            for bitfield, bitval in config.OPTINFO.items()
                            if validval & bitval
                        ]
                    gui._setValue(mlist, k, validval, fakedoc)
            # BAW: when to do gui._postValidate()???
    finally:
        if savelist and not checkonly:
            mlist.Save()
        mlist.Unlock()
Ejemplo n.º 8
0
def main():
    opts, args, parser = parseargs()
    config.load(opts.config)

    loginit.initialize(propagate=True)
    elog = logging.getLogger('mailman.error')
    blog = logging.getLogger('mailman.bounce')

    listnames = set(opts.listnames or config.list_manager.names)
    who = tuple(opts.who)

    msg = _('[disabled by periodic sweep and cull, no message available]')
    today = time.mktime(time.localtime()[:3] + (0,) * 6)
    for listname in listnames:
        # List of members to notify
        notify = []
        mlist = MailList.MailList(listname)
        try:
            interval = mlist.bounce_you_are_disabled_warnings_interval
            # Find all the members who are currently bouncing and see if
            # they've reached the disable threshold but haven't yet been
            # disabled.  This is a sweep through the membership catching
            # situations where they've bounced a bunch, then the list admin
            # lowered the threshold, but we haven't (yet) seen more bounces
            # from the member.  Note: we won't worry about stale information
            # or anything else since the normal bounce processing code will
            # handle that.
            disables = []
            for member in mlist.getBouncingMembers():
                if mlist.getDeliveryStatus(member) <> MemberAdaptor.ENABLED:
                    continue
                info = mlist.getBounceInfo(member)
                if info.score >= mlist.bounce_score_threshold:
                    disables.append((member, info))
            if disables:
                for member, info in disables:
                    mlist.disableBouncingMember(member, info, msg)
            # Go through all the members who have delivery disabled, and find
            # those that are due to have another notification.  If they are
            # disabled for another reason than bouncing, and we're processing
            # them (because of the command line switch) then they won't have a
            # bounce info record.  We can piggyback on that for all disable
            # purposes.
            members = mlist.getDeliveryStatusMembers(who)
            for member in members:
                info = mlist.getBounceInfo(member)
                if not info:
                    # See if they are bounce disabled, or disabled for some
                    # other reason.
                    status = mlist.getDeliveryStatus(member)
                    if status == MemberAdaptor.BYBOUNCE:
                        elog.error(
                            '%s disabled BYBOUNCE lacks bounce info, list: %s',
                            member, mlist.internal_name())
                        continue
                    info = _BounceInfo(
                        member, 0, today,
                        mlist.bounce_you_are_disabled_warnings,
                        mlist.pend_new(Pending.RE_ENABLE,
                                       mlist.internal_name(),
                                       member))
                    mlist.setBounceInfo(member, info)
                lastnotice = time.mktime(info.lastnotice + (0,) * 6)
                if opts.force or today >= lastnotice + interval:
                    notify.append(member)
            # Now, send notifications to anyone who is due
            for member in notify:
                blog.info('Notifying disabled member %s for list: %s',
                          member, mlist.internal_name())
                try:
                    mlist.sendNextNotification(member)
                except NotAMemberError:
                    # There must have been some problem with the data we have
                    # on this member.  Most likely it's that they don't have a
                    # password assigned.  Log this and delete the member.
                    blog.info(
                        'Cannot send disable notice to non-member: %s',
                        member)
                    mlist.ApprovedDeleteMember(member, 'cron/disabled')
            mlist.Save()
        finally:
            mlist.Unlock()