示例#1
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--smtp-ip',
                        default='127.0.0.1',
                        metavar='IP',
                        help='SMTP ip (default: 127.0.0.1)')
    parser.add_argument('--smtp-port',
                        default=1025,
                        type=int,
                        metavar='PORT',
                        help='SMTP port (deault: 1025)')
    parser.add_argument('--http-ip',
                        default='127.0.0.1',
                        metavar='IP',
                        help='HTTP ip (default: 127.0.0.1)')
    parser.add_argument('--http-port',
                        default=1080,
                        type=int,
                        metavar='PORT',
                        help='HTTP port (deault: 1080)')
    parser.add_argument('--db',
                        metavar='PATH',
                        help='SQLite database - in-memory if missing')
    parser.add_argument('--htpasswd',
                        metavar='HTPASSWD',
                        help='Apache-style htpasswd file')
    parser.add_argument('-v',
                        '--version',
                        help='Display the version and exit',
                        action='store_true')
    parser.add_argument(
        '-f',
        '--foreground',
        help='Run in the foreground (default if no pid file is specified)',
        action='store_true')
    parser.add_argument('-d',
                        '--debug',
                        help='Run the web app in debug mode',
                        action='store_true')
    parser.add_argument('-a',
                        '--autobuild-assets',
                        help='Automatically rebuild assets if necessary',
                        action='store_true')
    parser.add_argument(
        '-n',
        '--no-quit',
        help='Do not allow clients to terminate the application',
        action='store_true')
    parser.add_argument('-p', '--pidfile', help='Use a PID file')
    parser.add_argument(
        '--stop',
        help='Sends SIGTERM to the running daemon (needs --pidfile)',
        action='store_true')
    args = parser.parse_args()

    if args.version:
        from maildump.util import get_version
        print('MailDump {0}'.format(get_version()))
        sys.exit(0)

    # Do we just want to stop a runnign daemon?
    if args.stop:
        if not args.pidfile or not os.path.exists(args.pidfile):
            print('PID file not specified or not found')
            sys.exit(1)
        try:
            pid = read_pidfile(args.pidfile)
        except ValueError as e:
            print('Could not read PID file: {0}'.format(e))
            sys.exit(1)
        try:
            os.kill(pid, signal.SIGTERM)
        except OSError as e:
            print('Could not send SIGTERM: {0}'.format(e))
            sys.exit(1)
        sys.exit(0)

    # Default to foreground mode if no pid file is specified
    if not args.pidfile and not args.foreground:
        print('No PID file specified; runnning in foreground')
        args.foreground = True

    # Warn about relative paths and absolutize them
    if args.db and not os.path.isabs(args.db):
        args.db = os.path.abspath(args.db)
        print('Database path is relative, using {0}'.format(args.db))
    if args.htpasswd and not os.path.isabs(args.htpasswd):
        args.htpasswd = os.path.abspath(args.htpasswd)
        print('Htpasswd path is relative, using {0}'.format(args.htpasswd))

    # Check if the password file is valid
    if args.htpasswd and not os.path.isfile(args.htpasswd):
        print('Htpasswd file does not exist')
        sys.exit(1)

    # Check if the static folder is writable
    asset_folder = os.path.join(
        pkgutil.get_loader('maildump').filename, 'static')
    if args.autobuild_assets and not os.access(asset_folder, os.W_OK):
        print('Autobuilding assets requires write access to {0}'.format(
            asset_folder))
        sys.exit(1)

    daemon_kw = {
        'monkey_greenlet_report': False,
        'signal_map': {
            signal.SIGTERM: terminate_server,
            signal.SIGINT: terminate_server
        }
    }

    if args.foreground:
        # Do not detach and keep std streams open
        daemon_kw.update({
            'detach_process': False,
            'stdin': sys.stdin,
            'stdout': sys.stdout,
            'stderr': sys.stderr
        })

    pidfile = None
    if args.pidfile:
        pidfile = os.path.abspath(
            args.pidfile) if not os.path.isabs(args.pidfile) else args.pidfile
        if os.path.exists(pidfile):
            pid = read_pidfile(pidfile)
            if not os.path.exists(os.path.join('/proc', str(pid))):
                print(
                    'Deleting obsolete PID file (process {0} does not exist)'.
                    format(pid))
                os.unlink(pidfile)
        daemon_kw['pidfile'] = TimeoutPIDLockFile(pidfile, 5)

    # Unload threading module to avoid error on exit (it's loaded by lockfile)
    if 'threading' in sys.modules:
        del sys.modules['threading']

    context = GeventDaemonContext(**daemon_kw)
    try:
        context.open()
    except lockfile.LockTimeout:
        print('Could not acquire lock on pid file {0}'.format(pidfile))
        print('Check if the daemon is already running.')
        sys.exit(1)
    except KeyboardInterrupt:
        print()
        sys.exit(1)

    with context:
        # Imports are here to avoid importing anything before monkeypatching
        from maildump import app, start
        from maildump.web import assets

        assets.debug = app.debug = args.debug
        assets.auto_build = args.autobuild_assets
        app.config['MAILDUMP_HTPASSWD'] = HtpasswdFile(
            args.htpasswd) if args.htpasswd else None
        app.config['MAILDUMP_NO_QUIT'] = args.no_quit

        level = logbook.DEBUG if args.debug else logbook.INFO
        format_string = (
            u'[{record.time:%Y-%m-%d %H:%M:%S}]  {record.level_name:<8}  {record.channel}: {record.message}'
        )
        stderr_handler = ColorizedStderrHandler(level=level,
                                                format_string=format_string)
        with NullHandler().applicationbound():
            with stderr_handler.applicationbound():
                start(args.http_ip, args.http_port, args.smtp_ip,
                      args.smtp_port, args.db)
示例#2
0
    if args.pidfile:
        pidfile = os.path.abspath(
            args.pidfile) if not os.path.isabs(args.pidfile) else args.pidfile
        if os.path.exists(pidfile):
            pid = read_pidfile(pidfile)
            if not os.path.exists(os.path.join('/proc', str(pid))):
                print 'Deleting obsolete PID file (process {0} does not exist)'.format(
                    pid)
                os.unlink(pidfile)
        daemon_kw['pidfile'] = TimeoutPIDLockFile(pidfile, 5)

    # Unload threading module to avoid error on exit (it's loaded by lockfile)
    if 'threading' in sys.modules:
        del sys.modules['threading']

    context = GeventDaemonContext(**daemon_kw)
    try:
        context.open()
    except lockfile.LockTimeout:
        print 'Could not acquire lock on pid file {0}'.format(pidfile)
        print 'Check if the daemon is already running.'
        sys.exit(1)
    except KeyboardInterrupt:
        print
        sys.exit(1)

    with context:
        # Imports are here to avoid importing anything before monkeypatching
        from maildump import app, start
        from maildump.web import assets
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--smtp-ip', default='127.0.0.1', metavar='IP', help='SMTP ip (default: 127.0.0.1)')
    parser.add_argument('--smtp-port', default=1025, type=int, metavar='PORT', help='SMTP port (deault: 1025)')
    parser.add_argument('--http-ip', default='127.0.0.1', metavar='IP', help='HTTP ip (default: 127.0.0.1)')
    parser.add_argument('--http-port', default=1080, type=int, metavar='PORT', help='HTTP port (deault: 1080)')
    parser.add_argument('--db', metavar='PATH', help='SQLite database - in-memory if missing')
    parser.add_argument('--htpasswd', metavar='HTPASSWD', help='Apache-style htpasswd file')
    parser.add_argument('-v', '--version', help='Display the version and exit', action='store_true')
    parser.add_argument('-f', '--foreground', help='Run in the foreground (default if no pid file is specified)',
                        action='store_true')
    parser.add_argument('-d', '--debug', help='Run the web app in debug mode', action='store_true')
    parser.add_argument('-a', '--autobuild-assets', help='Automatically rebuild assets if necessary',
                        action='store_true')
    parser.add_argument('-n', '--no-quit', help='Do not allow clients to terminate the application',
                        action='store_true')
    parser.add_argument('-p', '--pidfile', help='Use a PID file')
    parser.add_argument('--stop', help='Sends SIGTERM to the running daemon (needs --pidfile)', action='store_true')
    args = parser.parse_args()

    if args.version:
        from maildump.util import get_version
        print('MailDump {0}'.format(get_version()))
        sys.exit(0)

    # Do we just want to stop a runnign daemon?
    if args.stop:
        if not args.pidfile or not os.path.exists(args.pidfile):
            print('PID file not specified or not found')
            sys.exit(1)
        try:
            pid = read_pidfile(args.pidfile)
        except ValueError as e:
            print('Could not read PID file: {0}'.format(e))
            sys.exit(1)
        try:
            os.kill(pid, signal.SIGTERM)
        except OSError as e:
            print('Could not send SIGTERM: {0}'.format(e))
            sys.exit(1)
        sys.exit(0)

    # Default to foreground mode if no pid file is specified
    if not args.pidfile and not args.foreground:
        print('No PID file specified; runnning in foreground')
        args.foreground = True

    # Warn about relative paths and absolutize them
    if args.db and not os.path.isabs(args.db):
        args.db = os.path.abspath(args.db)
        print('Database path is relative, using {0}'.format(args.db))
    if args.htpasswd and not os.path.isabs(args.htpasswd):
        args.htpasswd = os.path.abspath(args.htpasswd)
        print('Htpasswd path is relative, using {0}'.format(args.htpasswd))

    # Check if the password file is valid
    if args.htpasswd and not os.path.isfile(args.htpasswd):
        print('Htpasswd file does not exist')
        sys.exit(1)

    # Check if the static folder is writable
    asset_folder = os.path.join(pkgutil.get_loader('maildump').filename, 'static')
    if args.autobuild_assets and not os.access(asset_folder, os.W_OK):
        print('Autobuilding assets requires write access to {0}'.format(asset_folder))
        sys.exit(1)

    daemon_kw = {'monkey_greenlet_report': False,
                 'signal_map': {signal.SIGTERM: terminate_server,
                                signal.SIGINT: terminate_server}}

    if args.foreground:
        # Do not detach and keep std streams open
        daemon_kw.update({'detach_process': False,
                          'stdin': sys.stdin,
                          'stdout': sys.stdout,
                          'stderr': sys.stderr})

    pidfile = None
    if args.pidfile:
        pidfile = os.path.abspath(args.pidfile) if not os.path.isabs(args.pidfile) else args.pidfile
        if os.path.exists(pidfile):
            pid = read_pidfile(pidfile)
            if not os.path.exists(os.path.join('/proc', str(pid))):
                print('Deleting obsolete PID file (process {0} does not exist)'.format(pid))
                os.unlink(pidfile)
        daemon_kw['pidfile'] = TimeoutPIDLockFile(pidfile, 5)

    # Unload threading module to avoid error on exit (it's loaded by lockfile)
    if 'threading' in sys.modules:
        del sys.modules['threading']

    context = GeventDaemonContext(**daemon_kw)
    try:
        context.open()
    except lockfile.LockTimeout:
        print('Could not acquire lock on pid file {0}'.format(pidfile))
        print('Check if the daemon is already running.')
        sys.exit(1)
    except KeyboardInterrupt:
        print()
        sys.exit(1)

    with context:
        # Imports are here to avoid importing anything before monkeypatching
        from maildump import app, start
        from maildump.web import assets

        assets.debug = app.debug = args.debug
        assets.auto_build = args.autobuild_assets
        app.config['MAILDUMP_HTPASSWD'] = HtpasswdFile(args.htpasswd) if args.htpasswd else None
        app.config['MAILDUMP_NO_QUIT'] = args.no_quit

        level = logbook.DEBUG if args.debug else logbook.INFO
        format_string = (
            u'[{record.time:%Y-%m-%d %H:%M:%S}]  {record.level_name:<8}  {record.channel}: {record.message}'
        )
        stderr_handler = ColorizedStderrHandler(level=level, format_string=format_string)
        with NullHandler().applicationbound():
            with stderr_handler.applicationbound():
                start(args.http_ip, args.http_port, args.smtp_ip, args.smtp_port, args.db)