Example #1
0
    def validate(self, configuration):
        val = ConfString.validate(self, configuration)
        if val is None:
            return None
        val = expand_user_vars(val)
        if not os.path.isfile(val):
            raise getmailConfigurationError(
                '%s: specified mbox file "%s" does not exist' % (self.name, val)
            )
        fd = os.open(val, os.O_RDWR)
        status_old = os.fstat(fd)
        f = os.fdopen(fd, 'r+')
        # Check if it _is_ an mbox file.  mbox files must start with "From "
        # in their first line, or are 0-length files.
        f.seek(0, 0)
        first_line = f.readline()
        if first_line and first_line[:5] != 'From ':
            # Not an mbox file; abort here
            raise getmailConfigurationError('%s: not an mboxrd file' % val)
        # Reset atime and mtime
        try:
            os.utime(val, (status_old.st_atime, status_old.st_mtime))
        except OSError as o:
            # Not root or owner; readers will not be able to reliably
            # detect new mail.  But you shouldn't be delivering to
            # other peoples' mboxes unless you're root, anyways.
            pass

        return val
 def validate(self, configuration):
     val = ConfString.validate(self, configuration)
     if val is None:
         return None
     val = expand_user_vars(val)
     if not os.path.isfile(val):
         raise getmailConfigurationError(
             '%s: specified mbox file "%s" does not exist'
             % (self.name, val)
         )
     fd = os.open(val, os.O_RDWR)
     status_old = os.fstat(fd)
     f = os.fdopen(fd, 'r+b')
     lock_file(f)
     # Check if it _is_ an mbox file.  mbox files must start with "From "
     # in their first line, or are 0-length files.
     f.seek(0, 0)
     first_line = f.readline()
     unlock_file(f)
     if first_line and first_line[:5] != 'From ':
         # Not an mbox file; abort here
         raise getmailConfigurationError(
             '%s: not an mboxrd file' % val
         )
     # Reset atime and mtime
     try:
         os.utime(val, (status_old.st_atime, status_old.st_mtime))
     except OSError, o:
         # Not root or owner; readers will not be able to reliably
         # detect new mail.  But you shouldn't be delivering to
         # other peoples' mboxes unless you're root, anyways.
         pass
Example #3
0
 def validate(self, configuration):
     val = ConfString.validate(self, configuration)
     if val is None:
         return None
     val = expand_user_vars(val)
     if not os.path.isfile(val):
         raise getmailConfigurationError(
             '%s: specified file "%s" does not exist' % (self.name, val))
     return val
Example #4
0
 def validate(self, configuration):
     val = ConfString.validate(self, configuration)
     if val is None:
         return None
     val = expand_user_vars(val)
     if not os.path.isfile(val):
         raise getmailConfigurationError(
             '%s: specified file "%s" does not exist' % (self.name, val)
         )
     return val
Example #5
0
def main():
    try:
        parser = OptionParser(version='%%prog %s' % __version__)
        parser.add_option('-g',
                          '--getmaildir',
                          dest='getmaildir',
                          action='store',
                          default=defaults['getmaildir'],
                          help='look in DIR for config/data files',
                          metavar='DIR')
        parser.add_option(
            '-r',
            '--rcfile',
            dest='rcfile',
            action='append',
            default=[],
            help='load configuration from FILE (may be given multiple times)',
            metavar='FILE')
        parser.add_option('--dump',
                          dest='dump_config',
                          action='store_true',
                          default=False,
                          help='dump configuration and exit (debugging)')
        parser.add_option(
            '--trace',
            dest='trace',
            action='store_true',
            default=False,
            help='print extended trace information (extremely verbose)')
        overrides = OptionGroup(
            parser, 'Overrides',
            'The following options override those specified in any '
            'getmailrc file.')
        overrides.add_option(
            '-v',
            '--verbose',
            dest='override_verbose',
            action='count',
            help='operate more verbosely (may be given multiple times)')
        overrides.add_option('-q',
                             '--quiet',
                             dest='override_verbose',
                             action='store_const',
                             const=0,
                             help='operate quietly (only report errors)')
        overrides.add_option(
            '-d',
            '--delete',
            dest='override_delete',
            action='store_true',
            help='delete messages from server after retrieving')
        overrides.add_option(
            '-l',
            '--dont-delete',
            dest='override_delete',
            action='store_false',
            help='do not delete messages from server after retrieving')
        overrides.add_option('-a',
                             '--all',
                             dest='override_read_all',
                             action='store_true',
                             help='retrieve all messages')
        overrides.add_option('-n',
                             '--new',
                             dest='override_read_all',
                             action='store_false',
                             help='retrieve only unread messages')
        parser.add_option_group(overrides)

        (options, args) = parser.parse_args(sys.argv[1:])
        if args:
            raise getmailOperationError('unknown argument(s) %s ; try --help' %
                                        args)

        if options.trace:
            log.clearhandlers()

        if not options.rcfile:
            options.rcfile.append(defaults['rcfile'])

        s = ''
        for attr in dir(options):
            if attr.startswith('_'):
                continue
            if s:
                s += ','
            s += '%s="%s"' % (attr, pprint.pformat(getattr(options, attr)))
        log.debug('parsed options:  %s\n' % s)

        getmaildir_type = 'Default'
        if options.getmaildir != defaults['getmaildir']:
            getmaildir_type = 'Specified'
        getmaildir = expand_user_vars(options.getmaildir)
        if not os.path.exists(getmaildir):
            raise getmailOperationError(
                '%s config/data dir "%s" does not exist - create '
                'or specify alternate directory with --getmaildir option' %
                (getmaildir_type, getmaildir))
        if not os.path.isdir(getmaildir):
            raise getmailOperationError(
                '%s config/data dir "%s" is not a directory - fix '
                'or specify alternate directory with --getmaildir option' %
                (getmaildir_type, getmaildir))
        if not os.access(getmaildir, os.W_OK):
            raise getmailOperationError(
                '%s config/data dir "%s" is not writable - fix permissions '
                'or specify alternate directory with --getmaildir option' %
                (getmaildir_type, getmaildir))

        configs = []
        for filename in options.rcfile:
            path = os.path.join(os.path.expanduser(options.getmaildir),
                                filename)
            log.debug('processing rcfile %s\n' % path)
            if not os.path.exists(path):
                raise getmailOperationError('configuration file %s does '
                                            'not exist' % path)
            elif not os.path.isfile(path):
                raise getmailOperationError('%s is not a file' % path)
            f = open(path, 'rb')
            config = {
                'verbose': defaults['verbose'],
                'read_all': defaults['read_all'],
                'delete': defaults['delete'],
                'delete_after': defaults['delete_after'],
                'max_message_size': defaults['max_message_size'],
                'max_messages_per_session':
                defaults['max_messages_per_session'],
                'max_bytes_per_session': defaults['max_bytes_per_session'],
                'delivered_to': defaults['delivered_to'],
                'received': defaults['received'],
                'logfile': defaults['logfile'],
                'message_log': defaults['message_log'],
                'message_log_verbose': defaults['message_log_verbose'],
                'message_log_syslog': defaults['message_log_syslog'],
            }
            # Python's ConfigParser .getboolean() couldn't handle booleans in
            # the defaults. Submitted a patch; they fixed it a different way.
            # But for the extant, unfixed versions, an ugly hack....
            parserdefaults = config.copy()
            for (key, value) in parserdefaults.items():
                if type(value) == bool:
                    parserdefaults[key] = str(value)

            try:
                configparser = ConfigParser.RawConfigParser(parserdefaults)
                configparser.readfp(f, path)
                for option in options_bool:
                    log.debug('  looking for option %s ... ' % option)
                    if configparser.has_option('options', option):
                        log.debug('got "%s"' %
                                  configparser.get('options', option))
                        try:
                            config[option] = configparser.getboolean(
                                'options', option)
                            log.debug('-> %s' % config[option])
                        except ValueError:
                            raise getmailConfigurationError(
                                'configuration file %s incorrect (option %s '
                                'must be boolean, not %s)' %
                                (path, option,
                                 configparser.get('options', option)))
                    else:
                        log.debug('not found')
                    log.debug('\n')

                for option in options_int:
                    log.debug('  looking for option %s ... ' % option)
                    if configparser.has_option('options', option):
                        log.debug('got "%s"' %
                                  configparser.get('options', option))
                        try:
                            config[option] = configparser.getint(
                                'options', option)
                            log.debug('-> %s' % config[option])
                        except ValueError:
                            raise getmailConfigurationError(
                                'configuration file %s incorrect (option %s '
                                'must be integer, not %s)' %
                                (path, option,
                                 configparser.get('options', option)))
                    else:
                        log.debug('not found')
                    log.debug('\n')

                # Message log file
                for option in options_str:
                    log.debug('  looking for option %s ... ' % option)
                    if configparser.has_option('options', option):
                        log.debug('got "%s"' %
                                  configparser.get('options', option))
                        config[option] = configparser.get('options', option)
                        log.debug('-> %s' % config[option])
                    else:
                        log.debug('not found')
                    log.debug('\n')
                if config['message_log']:
                    try:
                        config['logfile'] = logfile(config['message_log'])
                    except IOError, o:
                        raise getmailConfigurationError(
                            'error opening message_log file %s (%s)' %
                            (config['message_log'], o))

                # Clear out the ConfigParser defaults before processing further
                # sections
                configparser._defaults = {}

                # Retriever
                log.debug('  getting retriever\n')
                retriever_type = configparser.get('retriever', 'type')
                log.debug('    type="%s"\n' % retriever_type)
                retriever_func = getattr(retrievers, retriever_type)
                if not callable(retriever_func):
                    raise getmailConfigurationError(
                        'configuration file %s specifies incorrect '
                        'retriever type (%s)' % (path, retriever_type))
                retriever_args = {
                    'getmaildir': options.getmaildir,
                    'configparser': configparser,
                }
                for (name, value) in configparser.items('retriever'):
                    if name in ('type', 'configparser'):
                        continue
                    if name == 'password':
                        log.debug('    parameter %s=*\n' % name)
                    else:
                        log.debug('    parameter %s="%s"\n' % (name, value))
                    retriever_args[name] = value
                log.debug('    instantiating retriever %s with args %s\n' %
                          (retriever_type, format_params(retriever_args)))
                try:
                    retriever = retriever_func(**retriever_args)
                    log.debug('    checking retriever configuration for %s\n' %
                              retriever)
                    retriever.checkconf()
                except getmailOperationError, o:
                    log.error('Error initializing retriever: %s\n' % o)
                    continue

                # Destination
                log.debug('  getting destination\n')
                destination_type = configparser.get('destination', 'type')
                log.debug('    type="%s"\n' % destination_type)
                destination_func = getattr(destinations, destination_type)
                if not callable(destination_func):
                    raise getmailConfigurationError(
                        'configuration file %s specifies incorrect destination '
                        'type (%s)' % (path, destination_type))
                destination_args = {'configparser': configparser}
                for (name, value) in configparser.items('destination'):
                    if name in ('type', 'configparser'):
                        continue
                    if name == 'password':
                        log.debug('    parameter %s=*\n' % name)
                    else:
                        log.debug('    parameter %s="%s"\n' % (name, value))
                    destination_args[name] = value
                log.debug('    instantiating destination %s with args %s\n' %
                          (destination_type, format_params(destination_args)))
                destination = destination_func(**destination_args)

                # Filters
                log.debug('  getting filters\n')
                _filters = []
                filtersections = [
                    section.lower() for section in configparser.sections()
                    if section.lower().startswith('filter')
                ]
                filtersections.sort()
                for section in filtersections:
                    log.debug('    processing filter section %s\n' % section)
                    filter_type = configparser.get(section, 'type')
                    log.debug('      type="%s"\n' % filter_type)
                    filter_func = getattr(filters, filter_type)
                    if not callable(filter_func):
                        raise getmailConfigurationError(
                            'configuration file %s specifies incorrect filter '
                            'type (%s)' % (path, filter_type))
                    filter_args = {'configparser': configparser}
                    for (name, value) in configparser.items(section):
                        if name in ('type', 'configparser'):
                            continue
                        if name == 'password':
                            log.debug('    parameter %s=*\n' % name)
                        else:
                            log.debug('    parameter %s="%s"\n' %
                                      (name, value))
                        filter_args[name] = value
                    log.debug('      instantiating filter %s with args %s\n' %
                              (filter_type, format_params(filter_args)))
                    mail_filter = filter_func(**filter_args)
                    _filters.append(mail_filter)

            except ConfigParser.NoSectionError, o:
                raise getmailConfigurationError(
                    'configuration file %s missing section (%s)' % (path, o))