示例#1
0
def parse_args():
  parser = argparse.ArgumentParser()
  parser.add_argument('host_and_port', help='The IMAP4 host name and '
    'port number in the format <host>:<port>. If the :<port> part is '
    'omitted, the default port of 993 is used.')
  parser.add_argument('user', help='The username to log in with.')
  parser.add_argument('passwd', nargs='?', help='The password for '
    'login. If omitted, the password is requested via the terminal.')
  parser.add_argument('--mailbox', default='INBOX', help='Select the name '
    'of the mailbox to read the mails from. Default is INBOX.')
  parser.add_argument('--sender', help='Only accept emails from the '
    'specified email address. Otherwise, all mails will be accepted.')
  parser.add_argument('--filter-title', help='IMAP subject filter string.')
  parser.add_argument('--interval', type=int, default=5, help='The interval '
    'to check for new mail in seconds. Defaults to 5.')
  parser.add_argument('--list-mailboxes', action='store_true',
    help='List the mailboxes and exit.')
  parser.add_argument('--scale-pdf', type=float, default=1.0,
    help='The anmount by which PDF files should be scaled. Defaults to 1.')
  args = parser.parse_args()
  args.host, args.port = args.host_and_port.partition(':')[::2]
  if args.port:
    try:
      args.port = int(args.port)
    except ValueError:
      parser.error('invalid port')
  if args.interval < 1:
    parser.error('interval must be >= 1')
  return args
示例#2
0
def parse_arguments():
    from optparse import OptionParser
    parser = OptionParser('usage: %prog [options] db-file')
    parser.add_option("-v", "--verbose", dest="verbose",
            default=False, help="verbose")
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error('db-file argument is required')

    return {'file': args[0], 'verbose':options.verbose}
示例#3
0
def parse_arguments():
    from optparse import OptionParser
    import getpass
    parser = OptionParser('usage: %prog [options] gmail-username')
    parser.add_option("-f", "--file", dest="file", default="emails.sql",
            help="destination database file [default: %default]")
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error('email argument is required')
    password = getpass.getpass('Password: '******'email':args[0], 'password':password, 'file':options.file}
示例#4
0
def main(argv):
    parser = OptionParser()
    parser.add_option("-b",
                      "--base",
                      dest="base_url",
                      help="specify base Fossil URL",
                      metavar="URL")
    parser.add_option("-R",
                      "--repository",
                      dest="repo",
                      help="Fossil repository to add ticket to",
                      metavar="FILE")

    global options, args
    (options, args) = parser.parse_args()

    if not options.base_url:
        parser.error("Base URL not given.")
    elif not options.repo:
        parser.error("Repository path not given.")

    if len(argv) < 2:
        print("Usage: {0} repository".format(argv[0]))
        return False

    msg = parse_message(sys.stdin.read())

    if not msg:
        print("Unable to parse message.", file=sys.stderr)
        return False
    elif not msg["id"]:
        print("No Message-Id, ignoring.", file=sys.stderr)
        return False

    cache = Cache()
    if msg["id"] in cache:
        print("Message {0} already was processed.".format(msg["id"]),
              file=sys.stderr)
        return True

    uuid = handle_message(msg)

    cache[msg["id"]] = uuid
    cache.save()

    return True
示例#5
0
def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--config-file', default='~/.imapautofiler.yml')
    parser.add_argument(
        '--list-mailboxes',
        default=False,
        action='store_true',
        help='instead of processing rules, print a list of mailboxes')
    args = parser.parse_args()

    try:
        cfg = config.get_config(args.config_file)
        conn = imapclient.IMAPClient(
            cfg['server']['hostname'],
            use_uid=True,
            ssl=True,
        )
        username = cfg['server']['username']
        password = cfg['server'].get('password')
        if not password:
            password = getpass.getpass('Password for {}:'.format(username))
        conn.login(username, password)
        try:
            if args.list_mailboxes:
                list_mailboxes(cfg, args.debug, conn)
            else:
                process_rules(cfg, args.debug, conn)
        finally:
            try:
                conn.close()
            except:
                pass
            conn.logout()
    except Exception as err:
        if args.debug:
            raise
        parser.error(err)
    return 0
示例#6
0
def py_nipubdir():
    """
    @brief Command line program to perform a NetInf 'publish' operation using http
    @brief convergence layer.
    
    Uses NIproc global instance of NI operations class

    Run:
    
    >  nipub.py --help

    to see usage and options.

    Exit code is 0 for success, 1 if HTTP returned something except 200,
    and negative for local errors.
    """
    

    # Options parsing and verification stuff
    usage = "%%prog -d <pathname of content directory> -n <FQDN of netinf node> [-a <hash alg>] [-m NN] [-c count]"

    parser = OptionParser(usage)
    
    parser.add_option("-d", "--dir", dest="dir_name",
                      type="string",
                      help="Pathname for directory to be published.")
    parser.add_option("-a", "--alg", dest="hash_alg", default="sha-256",
                      type="string",
                      help="Hash algorithm to be used for NI URIs. Defaults to sha-256.")
    parser.add_option("-n", "--node", dest="host",
                      type="string",
                      help="The FQDN where I'll send PUBLISH messages.")
    parser.add_option("-m", "--multiprocess", dest="mprocs", default=1,
                      type="int",
                      help="The number of client processes to use in a pool (default 1)")
    parser.add_option("-c", "--count", dest="count", default=0,
                      type="int",
                      help="The number of files to publish (default: all)")

    (options, args) = parser.parse_args()

    # Check command line options:
    # Arguments -h is optional, all others needed


    # Specifying more than one of -w, -p, -j and -v is inappropriate.
    if len(args) != 0:
        parser.error("Unrecognized arguments %s supplied." % str(args))
        sys.exit(-1)
    if options.dir_name == None:
        parser.error("You must supply a directory name with -d")
        sys.exit(-1)
    if options.host == None: 
        parser.error("You must supply a host name with -n")
        sys.exit(-1)

    nilog("Starting nipubdir,dir,%s,to,%s,alg,%s,processes,%d,count,%d" 
            % (options.dir_name,options.host,options.hash_alg,options.mprocs,options.count))

    # loop over all files below directory and putone() for each we find
    count,goodlist,badlist=pubdirs(options.dir_name,options.hash_alg,options.host,options.mprocs,options.count)

    # print goodlist
    # print badlist

    nilog("Finished nipubdir,dir,%s,to,%s,alg,%s,processes,%d,count,%d" 
        % (options.dir_name,options.host,options.hash_alg,options.mprocs,count))

    sys.exit(0)
示例#7
0
def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-v', '--verbose',
        action='store_true',
        default=False,
        help='report more details about what is happening',
    )
    parser.add_argument(
        '--debug',
        action='store_true',
        default=False,
        help='turn on imaplib debugging output',
    )
    parser.add_argument(
        '-c', '--config-file',
        default='~/.imapautofiler.yml',
    )
    parser.add_argument(
        '--list-mailboxes',
        default=False,
        action='store_true',
        help='instead of processing rules, print a list of mailboxes',
    )
    args = parser.parse_args()

    if args.debug:
        imaplib.Debug = 4

    if args.verbose or args.debug:
        log_level = logging.DEBUG
    else:
        log_level = logging.INFO

    logging.basicConfig(
        level=log_level,
        format='%(name)s: %(message)s',
    )
    logging.debug('starting')

    try:
        cfg = config.get_config(args.config_file)
        conn = imapclient.IMAPClient(
            cfg['server']['hostname'],
            use_uid=True,
            ssl=True,
        )
        conn.login(cfg['server']['username'], cfg['server']['password'])
        try:
            if args.list_mailboxes:
                list_mailboxes(cfg, args.debug, conn)
            else:
                process_rules(cfg, args.debug, conn)
        finally:
            try:
                conn.close()
            except:
                pass
            conn.logout()
    except Exception as err:
        if args.debug:
            raise
        parser.error(err)
    return 0
示例#8
0
def main():
    parser = OptionParser()
    parser.add_option(
        '-c', '--config', dest='configfile', metavar='FILE',
        help='JSON configuration file to load')
    parser.add_option(
        '-d', '--daemonize', action='store_const', const=True, dest='daemonize', default=None,
        help='Run mockmail in the background. Overwrites configuration')
    parser.add_option(
        '-i', '--interactive', action='store_const', const=True, dest='daemonize', default=None,
        help='Run mockmail in the foreground. Overwrites configuration')
    parser.add_option(
        '--resourcedir', dest='resourcedir', metavar='DIR',
        help='Load resources and templates from this directrory')
    parser.add_option(
        '--pidfile', dest='pidfile', default=None,
        help='Set pidfile to use. Overwrites configuration')
    parser.add_option(
        '--ctl-status', action='store_const', dest='ctl', const='status', default=None,
        help='Check whether mockmail service is running.')
    parser.add_option(
        '--ctl-start',  action='store_const', dest='ctl', const='start',  default=None,
        help='Start mockmail service.')
    parser.add_option(
        '--ctl-stop',   action='store_const', dest='ctl', const='stop',   default=None,
        help='Stop mockmail  service.')
    parser.add_option(
        '--quiet-ctl', action='store_true', dest='quiet_ctl', default=False,
        help='Do not print announcement in --ctl-* operations.')
    parser.add_option(
        '--dumpconfig', action='store_true', dest='dumpconfig',
        help='Do not run mockmail, but dump the effective configuration')
    parser.add_option(
        '--version', action='store_true', dest='dumpversion',
        help='Do not run mockmail, but output the version')
    parser.add_option(
        '--check-resourcedir', action='store_true', dest='check_resourcedir',
        help='Do not run mockmail, but check that the resource directory is set correctly')
    opts, args = parser.parse_args()

    if len(args) != 0:
        parser.error('Did not expect any arguments. Use -c to specify a configuration file.')

    if opts.dumpversion:
        print(__version__)
        return

    config = {
        'smtpaddr': '',     # IP address to bind the SMTP port on. The default allows anyone to send you emails.
        'smtpport': 2525,     # SMTP port number. On unixoid systems, you will need superuser privileges to bind to a port < 1024
        'httpaddr': '',       # IP address to bind the web interface on. The default allows anyone to see your mail.
        'httpport': 2580,     # Port to bind the web interface on. You may want to configure your webserver on port 80 to proxy the connection.
        'chroot': None,       # Specify the directory to chroot into.
        'chroot_mkdir': False,  # Automatically create the chroot directory if it doesn't exist, and chroot is set.
        'dropuser': None,     # User account (name or uid) to drop to, None to not drop privileges
        'dropgroup': None,    # User group (name or gid) to drop into. By default, this is the primary group of the user.
        'static_dev': False,  # Read static files on demand. Good for development (a reload will update the file), but should not be set in production
        'daemonize': False,   # Whether mockmail should go into the background after having started
        'pidfile': None,      # File to write the process ID of mockmail to (relative to the chroot)
        'resourcedir': None,  # Directory to load templates and resources
        'workarounds': True,  # Work around platform bugs
        'static_cache_secs': 0,  # Cache duration for static files
        'smtp_grace_period': None,  # Set to a number to wait that long to open a port
    }
    if opts.configfile:
        with open(opts.configfile, 'r') as cfgf:
            config.update(json.load(cfgf))
    if opts.daemonize is not None:
        config['daemonize'] = opts.daemonize
    if opts.pidfile is not None:
        config['pidfile'] = opts.pidfile
    if opts.resourcedir is not None:
        config['resourcedir'] = opts.resourcedir

    if opts.dumpconfig:
        json.dump(config, sys.stdout, indent=4)
        sys.stdout.write('\n')
        return

    if config['resourcedir'] is None:
        config['resourcedir'] = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'share', 'mockmail'))

    if opts.check_resourcedir:
        print('Loading resources from ' + os.path.abspath(config['resourcedir']) + ' ...')

        _readIds(
            _TEMPLATES,
            lambda fid: os.path.join(config['resourcedir'], 'templates', fid + '.mustache'),
            mapContent=lambda content: content.decode('UTF-8'),
            ondemand=False)
        _readIds(
            _STATIC_FILES,
            lambda fid: os.path.join(config['resourcedir'], 'static', fid),
            ondemand=False)
        sys.exit(0)

    ctl_print = (lambda s: 0) if opts.quiet_ctl else sys.stdout.write
    if opts.ctl == 'status':
        pid = _getPid(_effectivePidfile(config))
        if pid:
            ctl_print('mockmail is running.\n')
            sys.exit(0)
        else:
            ctl_print('mockmail is NOT running.\n')
            sys.exit(3)
    elif opts.ctl == 'start':
        pid = _getPid(_effectivePidfile(config))
        ctl_print('Starting Test MTA: mockmail')
        if pid:
            sys.stdout.write(' (pid ' + str(pid) + ') already running.\n')
            sys.exit(0)
        else:
            config['daemonize'] = True
            mockmail(config)
            ctl_print('.\n')
            return
    elif opts.ctl == 'stop':
        pidfn = _effectivePidfile(config)
        pid = _getPid(pidfn)
        ctl_print('Stopping Test MTA: mockmail ...')
        if pid:
            os.kill(pid, signal.SIGTERM)
            try:
                os.unlink(pidfn)
            except OSError:
                pass
        ctl_print('.\n')
        sys.exit(0)

    if config['pidfile']:
        pid = _getPid(_effectivePidfile(config))
        if pid:
            raise Exception(
                'mockmail is already running (pid %s), read from %s' %
                (pid, _effectivePidfile(config)))

    mockmail(config)
示例#9
0
def py_niget():
    """
    @brief Command line program to perform a NetInf 'get' operation using http
    @brief convergence layer.
    
    Uses NIproc global instance of NI operations class

    Run:
    
    >  niget.py --help

    to see usage and options.

    Exit code is 0 for success, 1 if HTTP returned something except 200,
    and negative for local errors.
    """
    
    # Options parsing and verification stuff
    usage = "%prog [-q] [-l] [-d] [-m|-v] [-f <pathname of content file>] <ni name>\n" + \
            "<ni name> must include location (netloc) from which to retrieve object."
    parser = OptionParser(usage)
    
    parser.add_option("-f", "--file", dest="file_name",
                      type="string",
                      help="File to hold retrieved content. Defaults to hash code in current directory if not present")
    parser.add_option("-q", "--quiet", default=False,
                      action="store_true", dest="quiet",
                      help="Suppress textual output")
    parser.add_option("-s", "--server", dest="server",
                      type="string",
                      help="hostname:port of server to send the NetInf GET to")
    parser.add_option("-l", "--lax", default=False,
                      action="store_true", dest="lax",
                      help="Store returned content even if digest doesn't validate")
    parser.add_option("-m", "--metadata", default=False,
                      action="store_true", dest="metadata",
                      help="Output returned metadata as JSON string")
    parser.add_option("-v", "--view", default=False,
                      action="store_true", dest="view",
                      help="Pretty print returned metadata.")
    parser.add_option("-d", "--dump", default=False,
                      action="store_true", dest="dump",
                      help="Dump raw HTTP response to stdout.")

    (options, args) = parser.parse_args()

    # Check command line options - -q, -f, -l, -m, -v and -d are optional, <ni name> is mandatory
    if len(args) != 1:
        parser.error("URL <ni name> not specified.")
        sys.exit(-1)
    verbose = not options.quiet

    # Create NIname instance for supplied URL and validate it
    ni_url = NIname(args[0])

    # Must be a complete ni: URL with non-empty params field
    rv = ni_url.validate_ni_url(has_params = True)
    if (rv != ni_errs.niSUCCESS):
        if verbose:
            print("Error: %s is not a complete, valid ni scheme URL: %s" % (ni_url.get_url(), ni_errs_txt[rv]))
        sys.exit(-2)

    # Generate file name for output if not specified
    if (options.file_name == None):
        options.file_name = ni_url.get_digest()
        
    # Generate NetInf form access URL
    if (options.server != None):
        server = options.server
    else:
        server = ni_url.get_netloc()

    http_url = "http://%s/netinfproto/get" % server
    """
    if (http_url == None):
        if verbose:
            print("Error: Unable to generate http: transformed URL for ni URL %s" % ni_urlparse.get_url())
        sys.exit(-3)
    """
    
    # Set up HTTP form data for get request
    form_data = urllib.urlencode({ "URI":   ni_url.get_url(),
                                   "msgid": random.randint(1, 32000),
                                   "ext":   "" })

    # Send POST request to destination server
    try:
        http_object = urllib2.urlopen(http_url, form_data)
    except Exception, e:
        if verbose:
            print("Error: Unable to access http URL %s: %s" % (http_url, str(e)))
        sys.exit(-4)
示例#10
0
def py_nigetalt():
    """
    @brief Command line program to perform a NetInf 'get' operation using http
    @brief convergence layer.
    
    Uses NIproc global instance of NI operations class

    Run:
    
    >  nigetalt.py --help

    to see usage and options.

    Exit code is 0 for success, 1 if HTTP returned something except 200,
    and negative for local errors.
    """
    
    # Options parsing and verification stuff
    usage = "%prog [-q] [-l] [-d] [-m|-v] [-f <pathname of content file>] [-w <locator>] <ni name>\n" + \
            "Either <ni name> must include location (netloc) from which to retrieve object, or\n" + \
            "a locator must be given with the -w/--whence option.\n" + \
            "The locator may be prefixed with an HTTP ('http://')or DTN ('dtn://') URI scheme identifier.\n" + \
            "If no scheme identifier is given then HTTP is assumed.  The DTN scheme does not accept ports."
    parser = OptionParser(usage)
    
    parser.add_option("-f", "--file", dest="file_name",
                      type="string",
                      help="File to hold retrieved content. Defaults to hash code in current directory if not present")
    parser.add_option("-w", "--whence", dest="loc",
                      type="string", default=None,
                      help="Locator to which to send NetInf GET request.  May be prefixed with http:// or dtn://")
    parser.add_option("-q", "--quiet", default=False,
                      action="store_true", dest="quiet",
                      help="Suppress textual output")
    parser.add_option("-l", "--lax", default=False,
                      action="store_true", dest="lax",
                      help="Store returned content even if digest doesn't validate")
    parser.add_option("-m", "--metadata", default=False,
                      action="store_true", dest="metadata",
                      help="Output returned metadata as JSON string")
    parser.add_option("-v", "--view", default=False,
                      action="store_true", dest="view",
                      help="Pretty print returned metadata.")

    (options, args) = parser.parse_args()

    # Check command line options - -q, -f, -l, -m, and -v are optional,
    # <ni name> is mandatory
    # -w is optional if <ni name> contains a netloc
    if len(args) != 1:
        parser.error("URL <ni name> not specified.")
        sys.exit(-1)
    verbose = not options.quiet

    # Create NIname instance for supplied URL and validate it
    ni_url = NIname(args[0])

    # Must be a complete ni: URL with non-empty params field
    rv = ni_url.validate_ni_url(has_params = True)
    if (rv != ni_errs.niSUCCESS):
        if verbose:
            print("Error: %s is not a complete, valid ni scheme URL: %s" % (ni_url.get_url(), ni_errs_txt[rv]))
        sys.exit(-2)

    # Generate file name for output if not specified
    if (options.file_name == None):
        options.file_name = ni_url.get_digest()

    # Decide Convergence Layer to use and locator to access
    netloc = ni_url.get_netloc()
    cl = HTTP_SCHEME
    if netloc == "":
        # Must have -w option
        if options.loc is None:
            if verbose:
                print("Error: Must provide a locator either in ni URI or via -w/--whence")
            sys.exit(-3)
        loc = options.loc.lower()
    elif options.loc is not None:
        if verbose:
            print("Warning: -w/--whence locator option overrides netloc in ni URI")
        loc = options.loc.lower()
    else:
        loc = netloc.lower()

    # See if URI scheme was specified
    if loc.startswith(HTTP_SCHEME):
        loc = loc[len(HTTP_SCHEME):]
    elif loc.startswith(DTN_SCHEME):
        loc = loc[len(DTN_SCHEME):]
        cl = DTN_SCHEME
    else:
        ssep = loc.find("://")
        if ssep != -1:
            if verbose:
                print("Error: Convergence Layer for scheme %s is not supported - use dtn or http" %
                      loc[:ssep])
            sys.exit(-4)
        # Default assume HTTP

    # Action the GET according to CL selected
    if cl == HTTP_SCHEME:
        json_report, got_content, faulty = get_via_http(ni_url, loc,
                                                        options.file_name,
                                                        verbose, options.lax)
    else:
        json_report, got_content, faulty = get_via_dtn(ni_url, loc,
                                                       options.file_name,
                                                       verbose, options.lax)

    if options.view:
        print("Returned metadata for %s:" % args[0])
        print json.dumps(json_report, indent = 4)
    elif options.metadata:
        print json.dumps(json_report, separators=(",", ":"))

    if not got_content:
        rv = 1
    elif faulty:
        rv = 2
    else:
        rv = 0

    if verbose and got_content:
        if not faulty:
            print("Content successfully retrieved and placed in file %s." %
                  options.file_name)
        else:
            print("Content retrieved and placed in file %s but digest didn't verify." %
                  options.file_name)
    elif verbose:
        print("Only metadata retrieved")

    sys.exit(rv)
示例#11
0
def main():
    parser = OptionParser()
    parser.add_option('-c',
                      '--config',
                      dest='configfile',
                      metavar='FILE',
                      help='JSON configuration file to load')
    parser.add_option(
        '-d',
        '--daemonize',
        action='store_const',
        const=True,
        dest='daemonize',
        default=None,
        help='Run mockmail in the background. Overwrites configuration')
    parser.add_option(
        '-i',
        '--interactive',
        action='store_const',
        const=False,
        dest='daemonize',
        default=None,
        help='Run mockmail in the foreground. Overwrites configuration')
    parser.add_option('--resourcedir',
                      dest='resourcedir',
                      metavar='DIR',
                      help='Load resources and templates from this directrory')
    parser.add_option('--pidfile',
                      dest='pidfile',
                      default=None,
                      help='Set pidfile to use. Overwrites configuration')
    parser.add_option('--ctl-status',
                      action='store_const',
                      dest='ctl',
                      const='status',
                      default=None,
                      help='Check whether mockmail service is running.')
    parser.add_option('--ctl-start',
                      action='store_const',
                      dest='ctl',
                      const='start',
                      default=None,
                      help='Start mockmail service.')
    parser.add_option('--ctl-stop',
                      action='store_const',
                      dest='ctl',
                      const='stop',
                      default=None,
                      help='Stop mockmail  service.')
    parser.add_option('--quiet-ctl',
                      action='store_true',
                      dest='quiet_ctl',
                      default=False,
                      help='Do not print announcement in --ctl-* operations.')
    parser.add_option(
        '--dumpconfig',
        action='store_true',
        dest='dumpconfig',
        help='Do not run mockmail, but dump the effective configuration')
    parser.add_option('--version',
                      action='store_true',
                      dest='dumpversion',
                      help='Do not run mockmail, but output the version')
    parser.add_option(
        '--check-resourcedir',
        action='store_true',
        dest='check_resourcedir',
        help=
        'Do not run mockmail, but check that the resource directory is set correctly'
    )
    opts, args = parser.parse_args()

    if len(args) != 0:
        parser.error(
            'Did not expect any arguments. Use -c to specify a configuration file.'
        )

    if opts.dumpversion:
        print(__version__)
        return

    config = {
        'smtpaddr':
        '',  # IP address to bind the SMTP port on. The default allows anyone to send you emails.
        'smtpport':
        2525,  # SMTP port number. On unixoid systems, you will need superuser privileges to bind to a port < 1024
        'httpaddr':
        '',  # IP address to bind the web interface on. The default allows anyone to see your mail.
        'httpport':
        2580,  # Port to bind the web interface on. You may want to configure your webserver on port 80 to proxy the connection.
        'chroot': None,  # Specify the directory to chroot into.
        'chroot_mkdir':
        False,  # Automatically create the chroot directory if it doesn't exist, and chroot is set.
        'dropuser':
        None,  # User account (name or uid) to drop to, None to not drop privileges
        'dropgroup':
        None,  # User group (name or gid) to drop into. By default, this is the primary group of the user.
        'static_dev':
        False,  # Read static files on demand. Good for development (a reload will update the file), but should not be set in production
        'daemonize':
        False,  # Whether mockmail should go into the background after having started
        'pidfile':
        None,  # File to write the process ID of mockmail to (relative to the chroot)
        'resourcedir': None,  # Directory to load templates and resources
        'workarounds': True,  # Work around platform bugs
        'static_cache_secs': 0,  # Cache duration for static files
        'smtp_grace_period':
        None,  # Set to a number to wait that long to open a port
    }
    if opts.configfile:
        with open(opts.configfile, 'r') as cfgf:
            config.update(json.load(cfgf))
    if opts.daemonize is not None:
        config['daemonize'] = opts.daemonize
    if opts.pidfile is not None:
        config['pidfile'] = opts.pidfile
    if opts.resourcedir is not None:
        config['resourcedir'] = opts.resourcedir

    if opts.dumpconfig:
        json.dump(config, sys.stdout, indent=4)
        sys.stdout.write('\n')
        return

    if config['resourcedir'] is None:
        config['resourcedir'] = os.path.normpath(
            os.path.join(os.path.dirname(__file__), '..', 'share', 'mockmail'))

    if opts.check_resourcedir:
        print('Loading resources from ' +
              os.path.abspath(config['resourcedir']) + ' ...')

        _readIds(_TEMPLATES,
                 lambda fid: os.path.join(config['resourcedir'], 'templates',
                                          fid + '.mustache'),
                 mapContent=lambda content: content.decode('UTF-8'),
                 ondemand=False)
        _readIds(
            _STATIC_FILES,
            lambda fid: os.path.join(config['resourcedir'], 'static', fid),
            ondemand=False)
        sys.exit(0)

    ctl_print = (lambda s: 0) if opts.quiet_ctl else sys.stdout.write
    if opts.ctl == 'status':
        pid = _getPid(_effectivePidfile(config))
        if pid:
            ctl_print('mockmail is running.\n')
            sys.exit(0)
        else:
            ctl_print('mockmail is NOT running.\n')
            sys.exit(3)
    elif opts.ctl == 'start':
        pid = _getPid(_effectivePidfile(config))
        ctl_print('Starting Test MTA: mockmail')
        if pid:
            sys.stdout.write(' (pid ' + str(pid) + ') already running.\n')
            sys.exit(0)
        else:
            config['daemonize'] = True
            mockmail(config)
            ctl_print('.\n')
            return
    elif opts.ctl == 'stop':
        pidfn = _effectivePidfile(config)
        pid = _getPid(pidfn)
        ctl_print('Stopping Test MTA: mockmail ...')
        if pid:
            os.kill(pid, signal.SIGTERM)
            try:
                os.unlink(pidfn)
            except OSError:
                pass
        ctl_print('.\n')
        sys.exit(0)

    if config['pidfile']:
        pid = _getPid(_effectivePidfile(config))
        if pid:
            raise Exception(
                'mockmail is already running (pid %s), read from %s' %
                (pid, _effectivePidfile(config)))

    mockmail(config)
示例#12
0
def py_nipub():
    """
    @brief Command line program to perform a NetInf 'publish' operation using http
    @brief convergence layer.
    
    Uses NIproc global instance of NI operations class

    Run:
    
    >  nipub.py --help

    to see usage and options.

    Exit code is 0 for success, 1 if HTTP returned something except 200,
    and negative for local errors.
    """
    
    # Options parsing and verification stuff
    usage = "%%prog %s\n       %%prog %s\n%s\n       %%prog %s\n       %%prog %s\n%s\n%s" % \
            ("[-q] [-e] [-j|-v|-w|-p] -f <pathname of content file> -d <digest alg> [-l <FQDN - locator>]{1,2}",
             "[-q] [-e] [-j|-v|-w|-p] [-f <pathname of content file>] -n <ni name> [-l <FQDN - locator>]{0,2}",
             "          -- publish file via NI URI over HTTP",
             "[-q] [-e] [-j|-v|-w|-p] -u <HTTP URI of content file> -d <digest alg> [-l <FQDN - locator>]{1,2}",
             "[-q] [-e] [-j|-v|-w|-p] [-u <HTTP URI of content file>] -n <ni name> [-l <FQDN - locator>]{0,2}",
             "          -- publish web content via NI URI over HTTP",
             "Send response as HTML document (-w), plain text (-p), or JSON (-v or -j)\n"
             "Unless -q is specified, the response is sent to standard output.\n"
             "For a JSON response, it can either be output as a 'raw' JSON string (-j) or pretty printed (-v).\n"
             "If none of  -j, -v, -w or -p are specified, a raw JSON response will be requested.")
    parser = OptionParser(usage)
    
    parser.add_option("-f", "--file", dest="file_name",
                      type="string",
                      help="Pathname for local file to be published.")
    parser.add_option("-u", "--uri", dest="http_name",
                      type="string",
                      help="HTTP URL for content to be published.")
    parser.add_option("-d", "--digest", dest="hash_alg",
                      type="string",
                      help="Digest algorithm to be used to hash content "
                           "and create NI URI. Defaults to sha-256.")
    parser.add_option("-n", "--name", dest="ni_name",
                      type="string",
                      help="Complete ni name. If specified with a file or "
                           "HTTP URL, the digest generated from the content "
                           "will be checked against th digest in the name.")
    parser.add_option("-e", "--ext", dest="ext",
                      type="string",
                      help="A JSON encoded object to be sent as the 'ext' "
                           "parameter for the Publish message.")
    parser.add_option("-l", "--loc", dest="locs", action="append",
                      type="string",
                      help="An FQDN where NI might be retrieved. Maybe be "
                           "zero to two if -n is present and has a non-empty netloc. "
                           "Otherwise must be one or two. HTTP is sent to first "
                           "loc if no authority in -n.")
    parser.add_option("-q", "--quiet", default=False,
                      action="store_true", dest="quiet",
                      help="Suppress textual output")
    parser.add_option("-j", "--json", default=False,
                      action="store_true", dest="json_raw",
                      help="Request response as JSON string and output raw JSON "
                           "string returned on stdout.")
    parser.add_option("-v", "--view", default=False,
                      action="store_true", dest="json_pretty",
                      help="Request response as JSON string and pretty print "
                           "JSON string returned on stdout.")
    parser.add_option("-w", "--web", default=False,
                      action="store_true", dest="html",
                      help="Request response as HTML document and output HTML "
                           "returned on stdout.")
    parser.add_option("-p", "--plain", default=False,
                      action="store_true", dest="plain",
                      help="Request response as plain text document and output text "
                           "returned on stdout.")


    (options, args) = parser.parse_args()

    # Check command line options:
    # Arguments -q, -e, -w, -p, -j and -v are optional; there must be one of a -n with an authority in it or at least one -l.
    # Either -d or -n must be specified.
    # If -d is specified, there must be either a -f or a -u but not both at once.
    # If -n is specified, one of -f or -u may be specified. No leftover arguments allowed.
    # Specifying more than one of -w, -p, -j and -v is inappropriate.
    if len(args) != 0:
        parser.error("Unrecognized arguments %s supplied." % str(args))
        sys.exit(-1)
    if ((options.locs is not None) and (len(options.locs) > 2)):
        parser.error("Initial version only supports two locators (-l/--loc).")
        sys.exit(-1)
    if ((options.ni_name == None) and (options.locs == None)):
        parser.error("Must specify a locator (-l/--loc) or a name (-n/--name) with a netloc component to define where to send the request.")
        sys.exit(-1)
    if ((options.hash_alg != None) and (options.ni_name != None)):
        parser.error("Cannot specify both digest algorithm to be used (-d) and complete ni name with algorithm and digest (-n).")
        sys.exit(-1)
    if ((options.hash_alg == None) and (options.ni_name == None)):
        parser.error("Must specify either digest algorithm to be used (-d) or complete ni name with algorithm and digest (-n).")
        sys.exit(-1)
    if ((((options.ni_name == None) and (options.file_name == None) and (options.http_name == None))) or
        ((options.file_name != None) and (options.http_name != None))):
        parser.error("Exactly one of -f/--file and -u/--uri must be specified with -d and optionally with -n.")
        sys.exit(-1)
    fc = 0
    for flag in [options.json_raw, options.json_pretty, options.html, options.plain]:
        if flag:
            fc += 1
    if fc > 1:
        parser.error("Should specify at most one response type argument out of -j, -v, -w and -p.")
        sys.exit(-1)

    file_name = None
    
    # **** -u is not implemented yet
    if options.http_name != None:
        target = options.http_name
        print "Web name as source(-u/--uri option) not yet implemented. Exiting"
        sys.exit(-2)

    if options.file_name != None:
        target = options.file_name
        file_name = options.file_name
        full_put = True
    else:
        target = None
        full_put = False
    debug("full_put: %s" %full_put)

    verbose = not options.quiet

    #  If we have a full ni name (-n option) given..
    if options.ni_name is not None:
        # Check the validity of the ni name
        try:
            ni_name = NIname(options.ni_name)
        except Exception, e:
            if verbose:
                print("Error: value of -n/--name option '%s' is not a valid ni name" % options.ni_name)
            sys.exit(-3)
        rv = ni_name.validate_ni_url()
        if rv != ni_errs.niSUCCESS:
            if verbose:
                print("Error: value of -n/--name option '%s' is not a valid ni name" % options.ni_name)
            sys.exit(-3)

        # Extract the scheme and hash algorithm from the name
        scheme = ni_name.get_scheme()
        hash_alg = ni_name.get_alg_name()

        # If the ni name has a netloc in it then that is where to send; if not must have a loc
        nl = ni_name.get_netloc()
        if ((nl == "") and (options.locs == None)):
            print("Error: name (-n/--name) mist have a netloc if no locator options given,")
            sys.exit(-4)
        if nl != "":
            destination = nl
            authority = nl
        else:
            destination = options.locs[0]
            authority = ""
示例#13
0
        # Create NIdigester for use with form encoder and StreamingHTTP
        ni_digester = NIdigester()

        # Install the template URL built from the scheme, the authority and the digest algorithm
        rv = ni_digester.set_url((scheme, authority, "/%s" % hash_alg))
        if rv != ni_errs.niSUCCESS:
            print("Cannot construct valid ni URL: %s" % ni_errs_txt[rv])
            sys.exit(-4)
        debug(ni_digester.get_url())

        # Open the file if possible
        try:
            f = open(options.file_name, "rb")
        except Exception, e :
            debug("Cannot open file %s: Error: %s" %(options.file_name, str(e)))
            parser.error("Unable to open file %s: Error: %s" % (options.file_name, str(e)))
            sys.exit(-5)

        # Guess the mimetype of the file
        m = magic.Magic(mime=True)
        ctype = m.from_file(options.file_name)
        debug("Content-Type: %s" % ctype)
        if ctype is None:
            # Guessing didn't work - default
            ctype = "application/octet-stream"

        # Set up HTTP form data for publish request
        # Make parameter for file with digester
        octet_param = MultipartParam("octets",
                                     fileobj=f,
                                     filetype=ctype,
示例#14
0
def run():
    parser = make_argparser()
    args = parser.parse_args()

    logger.addHandler(
        logging.handlers.RotatingFileHandler(args.log, maxBytes=4000))
    logger.setLevel(getattr(logging, args.log_level))

    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(args.cert, args.key)

    if args.local:
        if args.mboxdir is None and args.wmaildir is None:
            parser.error('--local requires --mboxdir or --wmaildir')
        elif args.mboxdir:
            logger.debug('Ensuring mbox path exists')
            args.mboxdir.mkdir(parents=True, exist_ok=True)
            handler = LocalMboxHandler(
                ok_domains=args.delivery_domain,
                mboxdir=args.mboxdir,
            )
        elif args.wmaildir:
            handler = LocalWMaildirHandler(
                ok_domains=args.delivery_domain,
                wmaildir=args.wmaildir,
            )

    controllers = []
    if args.forward:
        controllers.append(
            AuthController(
                ForwardingHandler(
                    ok_domains=args.forward_domain,
                    forward_host=args.forward_host,
                    forward_port=args.forward_port,
                ),
                port=args.port,
                hostname=args.host,
                starttls_context=context,
            ))
        if args.ssl_port:
            controllers.append(
                AuthController(
                    ForwardingHandler(
                        ok_domains=args.forward_domain,
                        forward_host=args.forward_host,
                        forward_port=args.forward_port,
                    ),
                    port=args.ssl_port,
                    hostname=args.host,
                    starttls_context=context,
                    ssl_context=context,
                ))

    if args.local:
        controllers.append(
            AuthController(
                handler,
                port=args.forward_port,
                hostname='0.0.0.0',
                ssl_context=context,
                starttls_context=context,
            ))

    logger.warn(f'orouboros {__version__} staring with pid {os.getpid()}')
    for controller in controllers:
        logger.debug(f'starting controller {controller}')
        controller.start()

    if controllers:
        logger.info('Waiting for SIGINT or SIGQUIT')
        sig = signal.sigwait([signal.SIGINT, signal.SIGQUIT])
        logger.warn(f'{sig} caught, shutting down')
    else:
        print(
            'Specify at least one of --forward or --local on the command line')

    for controller in controllers:
        logger.debug(f'stopping controller {controller}')
        controller.stop()
示例#15
0
def py_nipubalt():
    """
    @brief Command line program to perform a NetInf 'publish' operation using http
    @brief convergence layer.
    
    Uses NIproc global instance of NI operations class

    Run:
    
    >  nipubalt.py --help

    to see usage and options.

    Exit code is 0 for success, 1 if HTTP returned something except 200,
    and negative for local errors.
    """
    
    # Options parsing and verification stuff
    usage = "%%prog %s\n       %%prog %s\n%s\n%s" % \
            ("[-q] [-e] [-j|-v|-w|-p] -f <pathname of content file> -d <digest alg> [-l <FQDN - locator>]{1,2}",
             "[-q] [-e] [-j|-v|-w|-p] [-f <pathname of content file>] -n <ni name> [-l <FQDN - locator>]{0,2}",
             "          -- publish file via NI URI over HTTP and/or DTN",
             "At least one locator must be given either as part of the -n option or via a -l option.\n"
             "Locators given with -l options can optionally be prefixed with the HTTP scheme (http://) or \n"
             "the DTN scheme (dtn://).  If a -l option is given, this is used to determine the initial\n"
             "publication destination and the convergence layer used will be HTPP unless the -l option\n"
             "explicitly gives the DTN scheme prefix.  If there are no -l options but the -n option has\n"
             "a netloc compnent (FQDN or IP address with optional port) the this will be used with the\n"
             "HTTP convergence layer\n"
             "The response will be sent as HTML document (-w), plain text (-p), or JSON (-v or -j)\n"
             "Unless -q is specified, the response is sent to standard output.\n"
             "For a JSON response, it can either be output as a 'raw' JSON string (-j) or pretty printed (-v).\n"
             "If none of  -j, -v, -w or -p are specified, a raw JSON response will be requested.")
    parser = OptionParser(usage)
    
    parser.add_option("-f", "--file", dest="file_name",
                      type="string",
                      help="Pathname for local file to be published.")
    parser.add_option("-d", "--digest", dest="hash_alg",
                      type="string",
                      help="Digest algorithm to be used to hash content "
                           "and create NI URI. Defaults to sha-256.")
    parser.add_option("-n", "--name", dest="ni_name",
                      type="string",
                      help="Complete ni name. If specified with a file or "
                           "HTTP URL, the digest generated from the content "
                           "will be checked against th digest in the name.")
    parser.add_option("-e", "--ext", dest="ext",
                      type="string",
                      help="A JSON encoded object to be sent as the 'ext' "
                           "parameter for the Publish message.")
    parser.add_option("-l", "--loc", dest="locs", action="append",
                      type="string",
                      help="A locator where NI might be retrieved. Maybe be "
                           "zero to two if -n is present and has a non-empty netloc. "
                           "Otherwise must be one or two. HTTP or DTN is sent to first "
                           "loc if present. Otherwise sent to netloc (authority) in -n."
                           "NOTE: this precedence differs from earlier versions of nipub.")
    parser.add_option("-q", "--quiet", default=False,
                      action="store_true", dest="quiet",
                      help="Suppress textual output")
    parser.add_option("-j", "--json", default=False,
                      action="store_true", dest="json_raw",
                      help="Request response as JSON string and output raw JSON "
                           "string returned on stdout.")
    parser.add_option("-v", "--view", default=False,
                      action="store_true", dest="json_pretty",
                      help="Request response as JSON string and pretty print "
                           "JSON string returned on stdout.")
    parser.add_option("-w", "--web", default=False,
                      action="store_true", dest="html",
                      help="Request response as HTML document and output HTML "
                           "returned on stdout.")
    parser.add_option("-p", "--plain", default=False,
                      action="store_true", dest="plain",
                      help="Request response as plain text document and output text "
                           "returned on stdout.")


    (options, args) = parser.parse_args()

    # Check command line options:
    # Arguments -q, -e, -w, -p, -j and -v are optional; there must be one of a -n with an authority in it or at least one -l.
    # If -n option is specified then there must not be a -d.
    # If -d is specified, there must be a -f.
    # If -n is specified, -f may be specified - otherwise only metadata is published. No leftover arguments allowed.
    # Specifying more than one of -w, -p, -j and -v is inappropriate.
    if len(args) != 0:
        parser.error("Unrecognized arguments %s supplied." % str(args))
        sys.exit(-1)
    if ((options.locs is not None) and (len(options.locs) > 2)):
        parser.error("Initial version only supports two locators (-l/--loc).")
        sys.exit(-1)
    if ((options.ni_name == None) and (options.locs == None)):
        parser.error("Must specify a locator (-l/--loc) or a name (-n/--name) with a netloc component to define where to send the request.")
        sys.exit(-1)
    if ((options.hash_alg != None) and (options.ni_name != None)):
        parser.error("Cannot specify both digest algorithm to be used (-d) and complete ni name with algorithm and digest (-n).")
        sys.exit(-1)
    fc = 0
    for flag in [options.json_raw, options.json_pretty, options.html, options.plain]:
        if flag:
            fc += 1
    if fc > 1:
        parser.error("Should specify at most one response type argument out of -j, -v, -w and -p.")
        sys.exit(-1)

    file_name = None
    
    if options.file_name != None:
        file_name = os.path.abspath(options.file_name)
        # Check the file is readable
        if not os.access(file_name, os.R_OK):
            if verbose:
                print("File to be published %s is not readable" % file_name)
            sys.exit(1)
        full_put = True
    else:
        full_put = False
    debug("full_put: %s" %full_put)

    verbose = not options.quiet

    if ((options.locs is not None) and (len(options.locs) > 2)):
        if verbose:
            print "Warning: only first two -l/--loc locators will be published"

    #  If we have a full ni name (-n option) given..
    if options.ni_name is not None:
        # Check the validity of the ni name
        try:
            ni_name = NIname(options.ni_name)
        except Exception, e:
            if verbose:
                print("Error: value of -n/--name option '%s' is not a valid ni name" %
                      options.ni_name)
            sys.exit(-3)
        rv = ni_name.validate_ni_url()
        if rv != ni_errs.niSUCCESS:
            if verbose:
                print("Error: value of -n/--name option '%s' is not a valid ni name" %
                      options.ni_name)
            sys.exit(-3)

        # Extract the scheme and hash algorithm from the name
        scheme = ni_name.get_scheme()
        hash_alg = ni_name.get_alg_name()

        # If there is a -l option, that is where the request is sent.
        nl = ni_name.get_netloc()
        if ((options.locs is None) and (nl == "")) :
            print("Error: name (-n/--name) must have a netloc if no locator options given,")
            sys.exit(-4)
        # NOTE: The following logic ie reversed from earlier versions so that 
        # can force use of DTN convergence layer with a -l option.
        if nl == "":
            # Already checked this exists
            destination = options.locs[0]
        else:
            destination = nl
        authority = nl