예제 #1
0
파일: mailman.py 프로젝트: bksim/mailman
def main():
    """bin/mailman"""
    # Create the basic parser and add all globally common options.
    parser = argparse.ArgumentParser(
        description=_("""\
        The GNU Mailman mailing list management system
        Copyright 1998-2012 by the Free Software Foundation, Inc.
        http://www.list.org
        """),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        '-v', '--version',
        action='version', version=MAILMAN_VERSION_FULL,
        help=_('Print this version string and exit'))
    parser.add_argument(
        '-C', '--config',
        help=_("""\
        Configuration file to use.  If not given, the environment variable
        MAILMAN_CONFIG_FILE is consulted and used if set.  If neither are
        given, a default configuration file is loaded."""))
    # Look at all modules in the mailman.bin package and if they are prepared
    # to add a subcommand, let them do so.  I'm still undecided as to whether
    # this should be pluggable or not.  If so, then we'll probably have to
    # partially parse the arguments now, then initialize the system, then find
    # the plugins.  Punt on this for now.
    subparser = parser.add_subparsers(title='Commands')
    subcommands = []
    for command_class in find_components('mailman.commands', ICLISubCommand):
        command = command_class()
        verifyObject(ICLISubCommand, command)
        subcommands.append(command)
    # --help should display the subcommands by alphabetical order, except that
    # 'mailman help' should be first.
    def sort_function(command, other):
        """Sorting helper."""
        if command.name == 'help':
            return -1
        elif other.name == 'help':
            return 1
        else:
            return cmp(command.name, other.name)
    subcommands.sort(cmp=sort_function)
    for command in subcommands:
        command_parser = subparser.add_parser(
            command.name, help=_(command.__doc__))
        command.add(parser, command_parser)
        command_parser.set_defaults(func=command.process)
    args = parser.parse_args()
    if len(args.__dict__) == 0:
        # No arguments or subcommands were given.
        parser.print_help()
        parser.exit()
    # Initialize the system.  Honor the -C flag if given.
    config_path = (None if args.config is None
                   else os.path.abspath(os.path.expanduser(args.config)))
    initialize(config_path)
    # Perform the subcommand option.
    args.func(args)
예제 #2
0
def main(ctx, config_file, verbose, list_runners, once, runner_spec):
    # XXX https://github.com/pallets/click/issues/303
    """Start a runner.

    The runner named on the command line is started, and it can either run
    through its main loop once (for those runners that support this) or
    continuously.  The latter is how the master runner starts all its
    subprocesses.

    -r is required unless -l or -h is given, and its argument must be one
    of the names displayed by the -l switch.

    Normally, this script should be started from 'mailman start'.  Running
    it separately or with -o is generally useful only for debugging.  When
    run this way, the environment variable $MAILMAN_UNDER_MASTER_CONTROL
    will be set which subtly changes some error handling behavior.
    """
    global log

    if runner_spec is None and not list_runners:
        ctx.fail(_('No runner name given.'))

    # Initialize the system.  Honor the -C flag if given.
    initialize(config_file, verbose)
    log = logging.getLogger('mailman.runner')
    if verbose:
        console = logging.StreamHandler(sys.stderr)
        formatter = logging.Formatter(config.logging.root.format,
                                      config.logging.root.datefmt)
        console.setFormatter(formatter)
        logging.getLogger().addHandler(console)
        logging.getLogger().setLevel(logging.DEBUG)

    if list_runners:
        descriptions = {}
        for section in config.runner_configs:
            ignore, dot, shortname = section.name.rpartition('.')
            ignore, dot, classname = getattr(section, 'class').rpartition('.')
            descriptions[shortname] = classname
        longest = max(len(name) for name in descriptions)
        for shortname in sorted(descriptions):
            classname = descriptions[shortname]
            spaces = longest - len(shortname)
            name = (' ' * spaces) + shortname  # noqa: F841
            print(_('$name runs $classname'))
        sys.exit(0)

    runner = make_runner(*runner_spec, once=once)
    runner.set_signals()
    # Now start up the main loop
    log.info('{} runner started.'.format(runner.name))
    runner.run()
    log.info('{} runner exiting.'.format(runner.name))
    sys.exit(runner.status)
예제 #3
0
파일: mailman.py 프로젝트: aisworld/mailman
def main():
    """The `mailman` command dispatcher."""
    # Create the basic parser and add all globally common options.
    parser = argparse.ArgumentParser(
        description=_("""\
        The GNU Mailman mailing list management system
        Copyright 1998-2016 by the Free Software Foundation, Inc.
        http://www.list.org
        """),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=MAILMAN_VERSION_FULL,
                        help=_('Print this version string and exit'))
    parser.add_argument('-C',
                        '--config',
                        help=_("""\
        Configuration file to use.  If not given, the environment variable
        MAILMAN_CONFIG_FILE is consulted and used if set.  If neither are
        given, a default configuration file is loaded."""))
    # Look at all modules in the mailman.bin package and if they are prepared
    # to add a subcommand, let them do so.  I'm still undecided as to whether
    # this should be pluggable or not.  If so, then we'll probably have to
    # partially parse the arguments now, then initialize the system, then find
    # the plugins.  Punt on this for now.
    subparser = parser.add_subparsers(title='Commands')
    subcommands = []
    for command_class in find_components('mailman.commands', ICLISubCommand):
        command = command_class()
        verifyObject(ICLISubCommand, command)
        subcommands.append(command)
    subcommands.sort(key=cmp_to_key(_help_sorter))
    for command in subcommands:
        command_parser = subparser.add_parser(command.name,
                                              help=_(command.__doc__))
        command.add(parser, command_parser)
        command_parser.set_defaults(func=command.process)
    args = parser.parse_args()
    if len(args.__dict__) <= 1:
        # No arguments or subcommands were given.
        parser.print_help()
        parser.exit()
    # Initialize the system.  Honor the -C flag if given.
    config_path = (None if args.config is None else os.path.abspath(
        os.path.expanduser(args.config)))
    initialize(config_path)
    # Perform the subcommand option.
    with transaction():
        args.func(args)
예제 #4
0
    def initialize(self, propagate_logs=None):
        """Initialize the configuration system.

        After initialization of the configuration system, perform sanity
        checks.  We do it in this order because some sanity checks require the
        configuration to be initialized.

        :param propagate_logs: Optional flag specifying whether log messages
            in sub-loggers should be propagated to the master logger (and
            hence to the root logger).  If not given, propagation is taken
            from the configuration files.
        :type propagate_logs: bool or None.
        """
        # Fall back to using the environment variable if -C is not given.
        config_file = os.getenv("MAILMAN_CONFIG_FILE") if self.options.config is None else self.options.config
        initialize(config_file, propagate_logs=propagate_logs)
        self.sanity_check()
예제 #5
0
    def initialize(self, propagate_logs=None):
        """Initialize the configuration system.

        After initialization of the configuration system, perform sanity
        checks.  We do it in this order because some sanity checks require the
        configuration to be initialized.

        :param propagate_logs: Optional flag specifying whether log messages
            in sub-loggers should be propagated to the master logger (and
            hence to the root logger).  If not given, propagation is taken
            from the configuration files.
        :type propagate_logs: bool or None.
        """
        # Fall back to using the environment variable if -C is not given.
        config_file = (os.getenv('MAILMAN_CONFIG_FILE')
                       if self.options.config is None else self.options.config)
        initialize(config_file, propagate_logs=propagate_logs)
        self.sanity_check()
예제 #6
0
def run(environ, start_response):
    """Create the WSGI application.

    Use this if you want to integrate Mailman's REST server with an external
    WSGI server, such as gunicorn.  Be sure to set the $MAILMAN_CONFIG_FILE
    environment variable.
    """
    # Imports are here to evaluate them lazily, prevent circular imports, and
    # make flake8 happy.
    global _initialized
    if not _initialized:
        from mailman.core.initialize import initialize
        # First things first, initialize the system before any other imports or
        # other operations.  It must only be initialized once though.
        initialize(propagate_logs=True)
        _initialized = True
    # Hook things up to WSGI.
    from mailman.rest.wsgiapp import make_application
    app = make_application()
    return app(environ, start_response)
예제 #7
0
def main(config_file, restartable, force, runners, verbose):
    # XXX https://github.com/pallets/click/issues/303
    """Master subprocess watcher.

    Start and watch the configured runners and ensure that they stay
    alive and kicking.  Each runner is forked and exec'd in turn, with
    the master waiting on their process ids.  When it detects a child
    runner has exited, it may restart it.

    The runners respond to SIGINT, SIGTERM, SIGUSR1 and SIGHUP.  SIGINT,
    SIGTERM and SIGUSR1 all cause a runner to exit cleanly.  The master
    will restart runners that have exited due to a SIGUSR1 or some kind
    of other exit condition (say because of an uncaught exception).
    SIGHUP causes the master and the runners to close their log files,
    and reopen then upon the next printed message.

    The master also responds to SIGINT, SIGTERM, SIGUSR1 and SIGHUP,
    which it simply passes on to the runners.  Note that the master will
    close and reopen its own log files on receipt of a SIGHUP.  The
    master also leaves its own process id in the file `data/master.pid`
    but you normally don't need to use this pid directly.
    """
    initialize(config_file, verbose)
    # Acquire the master lock, exiting if we can't.  We'll let the caller
    # handle any clean up or lock breaking.  No `with` statement here because
    # Lock's constructor doesn't support a timeout.
    lock = acquire_lock(force)
    try:
        with open(config.PID_FILE, 'w') as fp:
            print(os.getpid(), file=fp)
        loop = Loop(lock, restartable, config.filename)
        loop.install_signal_handlers()
        try:
            loop.start_runners(runners)
            loop.loop()
        finally:
            loop.cleanup()
            os.remove(config.PID_FILE)
    finally:
        lock.unlock()
예제 #8
0
def initialize_config(ctx, param, value):
    if not ctx.resilient_parsing:
        initialize(value)
예제 #9
0
def main():
    global log

    parser = argparse.ArgumentParser(
        description=_("""\
        Start a runner

        The runner named on the command line is started, and it can either run
        through its main loop once (for those runners that support this) or
        continuously.  The latter is how the master runner starts all its
        subprocesses.

        -r is required unless -l or -h is given, and its argument must be one
        of the names displayed by the -l switch.

        Normally, this script should be started from 'mailman start'.  Running
        it separately or with -o is generally useful only for debugging.  When
        run this way, the environment variable $MAILMAN_UNDER_MASTER_CONTROL
        will be set which subtly changes some error handling behavior.
        """))
    parser.add_argument(
        '--version',
        action='version', version=MAILMAN_VERSION_FULL,
        help=_('Print this version string and exit'))
    parser.add_argument(
        '-C', '--config',
        help=_("""\
        Configuration file to use.  If not given, the environment variable
        MAILMAN_CONFIG_FILE is consulted and used if set.  If neither are
        given, a default configuration file is loaded."""))
    parser.add_argument(
        '-r', '--runner',
        metavar='runner[:slice:range]', dest='runner',
        action=ROptionAction, default=None,
        help=_("""\
        Start the named runner, which must be one of the strings
        returned by the -l option.

        For runners that manage a queue directory, optional
        `slice:range` if given is used to assign multiple runner
        processes to that queue.  range is the total number of runners
        for the queue while slice is the number of this runner from
        [0..range).  For runners that do not manage a queue, slice and
        range are ignored.

        When using the `slice:range` form, you must ensure that each
        runner for the queue is given the same range value.  If
        `slice:runner` is not given, then 1:1 is used.
        """))
    parser.add_argument(
        '-o', '--once',
        default=False, action='store_true', help=_("""\
        Run the named runner exactly once through its main loop.
        Otherwise, the runner runs indefinitely until the process
        receives a signal.  This is not compatible with runners that
        cannot be run once."""))
    parser.add_argument(
        '-l', '--list',
        default=False, action='store_true',
        help=_('List the available runner names and exit.'))
    parser.add_argument(
        '-v', '--verbose',
        default=None, action='store_true', help=_("""\
        Display more debugging information to the log file."""))

    args = parser.parse_args()
    if args.runner is None and not args.list:
        parser.error(_('No runner name given.'))

    # Initialize the system.  Honor the -C flag if given.
    config_path = (None if args.config is None
                   else os.path.abspath(os.path.expanduser(args.config)))
    initialize(config_path, args.verbose)
    log = logging.getLogger('mailman.runner')
    if args.verbose:
        console = logging.StreamHandler(sys.stderr)
        formatter = logging.Formatter(config.logging.root.format,
                                      config.logging.root.datefmt)
        console.setFormatter(formatter)
        logging.getLogger().addHandler(console)
        logging.getLogger().setLevel(logging.DEBUG)

    if args.list:
        descriptions = {}
        for section in config.runner_configs:
            ignore, dot, shortname = section.name.rpartition('.')
            ignore, dot, classname = getattr(section, 'class').rpartition('.')
            descriptions[shortname] = classname
        longest = max(len(name) for name in descriptions)
        for shortname in sorted(descriptions):
            classname = descriptions[shortname]
            spaces = longest - len(shortname)
            name = (' ' * spaces) + shortname       # noqa: F841
            print(_('$name runs $classname'))
        sys.exit(0)

    runner = make_runner(*args.runner, once=args.once)
    runner.set_signals()
    # Now start up the main loop
    log.info('%s runner started.', runner.name)
    runner.run()
    log.info('%s runner exiting.', runner.name)
    sys.exit(runner.status)
예제 #10
0
def main():
    global log

    parser = argparse.ArgumentParser(
        description=_("""\
        Start a runner

        The runner named on the command line is started, and it can either run
        through its main loop once (for those runners that support this) or
        continuously.  The latter is how the master runner starts all its
        subprocesses.

        -r is required unless -l or -h is given, and its argument must be one
        of the names displayed by the -l switch.

        Normally, this script should be started from 'mailman start'.  Running
        it separately or with -o is generally useful only for debugging.  When
        run this way, the environment variable $MAILMAN_UNDER_MASTER_CONTROL
        will be set which subtly changes some error handling behavior.
        """))
    parser.add_argument(
        '--version',
        action='version', version=MAILMAN_VERSION_FULL,
        help=_('Print this version string and exit'))
    parser.add_argument(
        '-C', '--config',
        help=_("""\
        Configuration file to use.  If not given, the environment variable
        MAILMAN_CONFIG_FILE is consulted and used if set.  If neither are
        given, a default configuration file is loaded."""))
    parser.add_argument(
        '-r', '--runner',
        metavar='runner[:slice:range]', dest='runner',
        action=ROptionAction, default=None,
        help=_("""\
        Start the named runner, which must be one of the strings
        returned by the -l option.

        For runners that manage a queue directory, optional
        `slice:range` if given is used to assign multiple runner
        processes to that queue.  range is the total number of runners
        for the queue while slice is the number of this runner from
        [0..range).  For runners that do not manage a queue, slice and
        range are ignored.

        When using the `slice:range` form, you must ensure that each
        runner for the queue is given the same range value.  If
        `slice:runner` is not given, then 1:1 is used.
        """))
    parser.add_argument(
        '-o', '--once',
        default=False, action='store_true', help=_("""\
        Run the named runner exactly once through its main loop.
        Otherwise, the runner runs indefinitely until the process
        receives a signal.  This is not compatible with runners that
        cannot be run once."""))
    parser.add_argument(
        '-l', '--list',
        default=False, action='store_true',
        help=_('List the available runner names and exit.'))
    parser.add_argument(
        '-v', '--verbose',
        default=None, action='store_true', help=_("""\
        Display more debugging information to the log file."""))

    args = parser.parse_args()
    if args.runner is None and not args.list:
        parser.error(_('No runner name given.'))

    # Initialize the system.  Honor the -C flag if given.
    config_path = (None if args.config is None
                   else os.path.abspath(os.path.expanduser(args.config)))
    initialize(config_path, args.verbose)
    log = logging.getLogger('mailman.runner')
    if args.verbose:
        console = logging.StreamHandler(sys.stderr)
        formatter = logging.Formatter(config.logging.root.format,
                                      config.logging.root.datefmt)
        console.setFormatter(formatter)
        logging.getLogger().addHandler(console)
        logging.getLogger().setLevel(logging.DEBUG)

    if args.list:
        descriptions = {}
        for section in config.runner_configs:
            ignore, dot, shortname = section.name.rpartition('.')
            ignore, dot, classname = getattr(section, 'class').rpartition('.')
            descriptions[shortname] = classname
        longest = max(len(name) for name in descriptions)
        for shortname in sorted(descriptions):
            classname = descriptions[shortname]
            name = (' ' * (longest - len(shortname))) + shortname
            print(_('$name runs $classname'))
        sys.exit(0)

    runner = make_runner(*args.runner, once=args.once)
    runner.set_signals()
    # Now start up the main loop
    log.info('%s runner started.', runner.name)
    runner.run()
    log.info('%s runner exiting.', runner.name)
    sys.exit(runner.status)
예제 #11
0
def main():
    cfg = os.environ.get('MAILMANCONFIG', 'mailman.cfg')
    initialize(cfg, True)
    config.db.engine.execute(SQL)
    config.db.commit()
예제 #12
0
#!/usr/bin/python3

import os
import sys

from mailman.core.initialize import initialize
from mailman.config import config
from mailman.interfaces.pending import IPendings
from mailman.interfaces.requests import IListRequests, RequestType
from zope.component import getUtility


def clean_pended():
    getUtility(IPendings).evict()


if __name__ == '__main__':
    if os.getuid() == 0:
        print("This script must be run as the mailman user", file=sys.stderr)
        sys.exit(1)
    initialize(config_path="/etc/mailman.cfg")
    clean_pended()
    config.db.commit()
예제 #13
0
#!/usr/bin/python3
"""Wrapper script to work around mailman cli limitations in debian buster."""

# pylint: disable=import-error
from mailman.app.membership import add_member, delete_member
from mailman.core.initialize import initialize
from mailman.database.transaction import transactional
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.member import DeliveryMode
from mailman.interfaces.subscriptions import RequestRecord
from zope.component import getUtility

# initialize on import
initialize()


class ListManager:
    """Helper class to manage a mailman3 mailinglist."""
    def __init__(self, mailinglist):
        self.list = getUtility(IListManager).get(mailinglist)

    @transactional
    def add(self, email):
        """Add email to mailinglist."""
        add_member(
            self.list,
            RequestRecord(email, '', DeliveryMode.regular,
                          self.list.preferred_language.code))

    @transactional
    def delete(self, email):