Package: cs.app.mailfiler
Mailfiler is my email message filing system.Latest release 20200719:mailfiler: make "-R rules_pattern" a global option.Add some Received: headers, improving traceability.More friendly and less noisy terminal output (I run mailfiler as a daemon in a tmux session).Quite a few small internal changes.It monitors multiple Maildir folders for new messages
and files them according to various easy to write rules.
Its use is described fully in the mailfiler(1cs) manual entry.The rules files are broadly quite simple and described fully
in the mailfiler(5cs) manual entry.
The rules are normally single line rules of the form:target,... label conditionIf the rule should always fire
then the condition may be omitted.The targets may be
mail folders (file the message in the named folder),
assignment statements (set an environment variable),
email addresses (send the message to the specified address)
or some other special purpose actions.The conditions are usually tests of the header email addresses
including whether an address is a member of some group/alias
but may also test various other things about the message headers.ClassCondition_AddressMatch(_Condition,types.SimpleNamespace)A condition testing for the presence of an address.MethodCondition_AddressMatch.test_value(self, filer, header_name, header_value)Test this condition against a header value.ClassCondition_HeaderFunction(_Condition,types.SimpleNamespace)A condition testing the contents of a header.MethodCondition_HeaderFunction.test_func_contains(self, filer, header_name, header_value)Test if the rule's string is in the header.MethodCondition_HeaderFunction.test_value(self, filer, header_name, header_value)Test the header value against to test function.ClassCondition_InGroups(_Condition,types.SimpleNamespace)A condition testing messages addresses against address groups.MethodCondition_InGroups.test_value(self, filer, header_name, header_value)Test this condition against a header value.ClassCondition_Regexp(_Condition,types.SimpleNamespace)A condition testing headers against a regular expression.MethodCondition_Regexp.test_value(self, filer, header_name, header_value)Test this condition against a header value.Functioncurrent_value(envvar, cfg, cfg_key, default, environ)Compute a configurable path value on the fly.FunctionFilterReport(rule, matched, saved_to, ok_actions, failed_actions)Create a FilterReport object.Parameters:rule: theRuleon which to reportmatched: whether the rule was matchedsaved_to: where messages were filedok_actions: actions which succeededfailed_actions: actions which failedFunctionget_target(s, offset, quoted=False)Parse a single target specification from a string; return Target and new offset.Parameters:s: the string to parseoffset: the starting offset of the parsequoted: if true then the parser is already inside quotes:
do not expect comma or whitespace to end the target specification.
Default:FalseFunctionget_targets(s, offset)Parse list of targets from the stringsstarting atoffset.
Return the list of Targets strings and the new offset.Functionmaildir_from_name(mdirname, maildir_root, maildir_cache)Return the Maildir derived from mdirpath.ClassMailFiler(types.SimpleNamespace)A mail filer.MethodMailFiler.__init__(self, config_path=None, environ=None, rules_pattern=None)Initialise the MailFiler.Parameters:config_path: location of config file, default fromDEFAULT_MAILFILER_RC.environ: initial environment, default fromos.environ.rules_pattern: rules pattenr, default fromenvsub(DEFAULT_RULES_PATTERN)MethodMailFiler.file_wmdir_key(self, wmdir, key)Accept a WatchedMaildirwmdirand a messagekey, return success.
This does not remove a successfully filed message or update the lurking list.MethodMailFiler.folder_logfile(self, folder_path)Return path to log file associated with the named folder.
TODO: base on relative path from folder root, not just basename.MethodMailFiler.maildir_from_folderspec(self, folderspec)Return the Maildir fromfolderspec.MethodMailFiler.maildir_watcher(self, folderspec)Return the singleton WatchedMaildir indicated by thefolderspec.MethodMailFiler.monitor(self, folders, *, delay=None, justone=False, no_remove=False, upd=None)Monitor the specifiedfolders, a list of folder spcifications.
Ifdelayis not None, poll the folders repeatedly with a
delay ofdelayseconds between each pass.MethodMailFiler.report(msgfp)Implementation for command line "report" function: report on message.MethodMailFiler.save(self, targets, msgfp)Implementation for command line "save" function: save file to target.MethodMailFiler.subcfg(self, section_name)Return a section of the configuration.MethodMailFiler.sweep(self, wmdir, *, justone=False, no_remove=False, logfile=None, upd=None)Scan a WatchedMaildir for messages to filter.
Return the number of messages processed.Update the set of lurkers with any keys not removed to prevent
filtering on subsequent calls.
Ifjustone, return after filing the first message.ClassMailFilerCommand(cs.cmdutils.BaseCommand)MailFiler commandline implementation.Command line usage:Usage: MailFilerCommand [-R rules_pattern] subopt [subopt-args...]
      -R rules_pattern
          Specify the rules file pattern used to specify rules files from
          Maildir names.
          Default: $HOME/.mailfiler/{maildir.basename}
  Subcommands:
    help [subcommand-names...]
      Print the help for the named subcommands,
      or for all subcommands if no names are specified.
    monitor [-1] [-d delay] [-n] [maildirs...]
      Monitor Maildirs for new messages and file them.
      -1  File at most 1 message per Maildir.
      -d delay
          Delay between runs in seconds.
          Default is to make only one run over the Maildirs.
      -n  No remove. Keep filed messages in the origin Maildir.
    report <message
      Report various things about a message from standard input.
    save target[,target...] <message
      Save a message from standard input to the specified targets.MethodMailFilerCommand.apply_defaults(options)Set up default options.MethodMailFilerCommand.apply_opts(opts, options)Apply command line options.MethodMailFilerCommand.cmd_monitor(self, argv, options)Usage: {cmd} [-1] [-d delay] [-n] [maildirs...]
Monitor Maildirs for new messages and file them.
-1  File at most 1 message per Maildir.
-d delay
Delay between runs in seconds.
Default is to make only one run over the Maildirs.
-n  No remove. Keep filed messages in the origin Maildir.MethodMailFilerCommand.cmd_report(self, argv, options)Usage: {cmd} <message
Report various things about a message from standard input.MethodMailFilerCommand.cmd_save(self, argv, options)Usage: {cmd} target[,target...] <message
Save a message from standard input to the specified targets.Save message to thetargets,
a single command line argument of the form
of a mailfiler targets field.MethodMailFilerCommand.mailfiler(self, options)Prepare aMailFilerfrom theoptions.MethodMailFilerCommand.run_context(self, argv, options)Run commands at STATUS logging level (or lower if already lower).Functionmain(argv=None, stdin=None)Mailfiler main programme.ClassMessageFiler(types.SimpleNamespace)A message filing object, filtering state information used during rule evaluation.Attributes:.maildb: Current MailDB..environ: Storage for variable settings..addresses(header): Caching list of addresses from specified header.MethodMessageFiler.__init__(self, context, environ=None)context: External state object, with maildb property, etc..environ: Mapping which supplies initial variable names.
Default from os.environ.MethodMessageFiler.addresses(self, *headers)Return the core addresses from the current Message and suppliedheaders. Caches results for rapid rule evaluation.MethodMessageFiler.alert(self, alert_level, alert_message=None)Issue an alert with the specifiedalert_message.
If missing or None, use self.alert_message(self.message).
Ifalert_levelis more than 1, prepend "-l alert_level"
to the alert command line arguments.MethodMessageFiler.alert_message(self, M)Return the alert message filled out with parameters from the MessageM.MethodMessageFiler.apply_rule(self, R)Apply this the ruleRto this MessageFiler.
The rule label, if any, is appended to the .labels attribute.
Each target is applied to the state.MethodMessageFiler.env(self, envvar, default)Shorthand for environment lookup.MethodMessageFiler.file(self, M, rules, message_path=None)File the specified messageMaccording to the suppliedrules.
If specified and notNone, themessage_pathparameter
specifies the filename of the message, supporting hard linking
the message into a Maildir.MethodMessageFiler.format_message(self, M, fmt)Compute the alert message for the messageMusing the supplied format stringfmt.MethodMessageFiler.group(self, group_name)Return the set of addresses in the named group.MethodMessageFiler.learn_header_addresses(self, header_names, *group_names)Update maildb groups with addresses from message headers.
Extract all the addresses from the specified
headers and add to the maildb groups named bygroup_names.MethodMessageFiler.learn_message_ids(self, header_names, *group_names)Update msgiddb groups with message-ids from message headers.MethodMessageFiler.maildir(self, mdirpath)Return the Maildir formdirpath.MethodMessageFiler.modify(self, hdr, new_value, always=False)Modify the value of the named headerhdrto the new valuenew_valueusing cs.mailutils.modify_header.new_valuemay be a string or an iterable of strings.
If headers were changed, forget self.message_path.MethodMessageFiler.process_environ(self)Compute the environment for a subprocess.MethodMessageFiler.resolve(self, foldername)Resolve a mailfoldernameagainst the filer'sMAILDIRattribute.MethodMessageFiler.save_message(self)Perform the message save step based on the current filer state.
This is separated out to support the command line "save target" operation.MethodMessageFiler.save_to_pipe(self, argv, environ=None, mfp=None)Pipe a message to the command specific byargv.mfpis a file containing the message text.
Ifmfpis None, use the text of the current message.MethodMessageFiler.sendmail(self, address, mfp=None, sender=None)Dispatch a message toaddress.mfpis a file containing the message text.
Ifmfpis None, use the text of the current message.
Ifsenderis supplied, pass to sendmail with -f option.Functionparserules(fp)Read rules fromfp, yield Rules.Functionresolve_mail_path(mdirpath, maildir_root)Return the full path to the requested mail folder.ClassRuleA filing rule.MethodRule.match(self, filer)Test the message in filer against this rule.ClassRules(builtins.list)Simple subclass of list storing rules, with methods to load
rules and filter a message using the rules.MethodRules.load(self, fp)Import an open rule file.MethodRules.match(self, filer)Match the current message (filer.message) against the rules.
Update filer for matching rules.Functionsave_to_folderpath(folderpath, M, message_path, flags)Save the MessageMto the resolvedfolderpath.Parameters:folderpath: the path to the target mail folder.M: the message to save.message_path: pathname of existing message file, allowing
hardlinking to new maildir if notNone.flags: save flags as from MessageFiler.flagsFunctionscrub_header(value)"Scrub" a header value.
Presently this means to undo RFC2047 encoding where possible.ClassTarget_Assign(types.SimpleNamespace)A filing target to set a filing state environment variable.MethodTarget_Assign.apply(self, filer)Apply the target by updating the filer environment.ClassTarget_EnvSub(types.SimpleNamespace)A filing target to delivery to a string
which is subject to environment subject to environment variable expansion
where the environment variables are derived from the filing state.MethodTarget_EnvSub.apply(self, filer)Perform environment substitution on target string and then
deliver to resulting string.ClassTarget_Function(types.SimpleNamespace)A filing target to run a Python function against a message.MethodTarget_Function.apply(self, filer)Apply this target:
run the Python function against the message.ClassTarget_MailAddress(types.SimpleNamespace)A filing target for an email address.MethodTarget_MailAddress.apply(self, filer)Apply this target:
addself.addressto the set of target forwarding email addresses.ClassTarget_MailFolder(types.SimpleNamespace)A filing target for a mail folder.MethodTarget_MailFolder.apply(self, filer)Apply this target:
if the folder name is '.'
mark the filer as saving to the source folder,
otherwise add the resolved folder name to the set of target folders.ClassTarget_PipeLine(types.SimpleNamespace)A filing target to pipe the message contents to a shell command.MethodTarget_PipeLine.apply(self, filer)Apply this target:
appendself.shcmdto the list of save commands.ClassTarget_SetFlag(types.SimpleNamespace)A filing target to apply a flag to a message.MethodTarget_SetFlag.apply(self, filer)Apply this target:
set a flag on the message.ClassTarget_Substitution(types.SimpleNamespace)A filing target to apply a regular expression string substitution
to message headers.MethodTarget_Substitution.apply(self, filer)Apply this target:
apply a regexp substitution to the message headers.ClassWatchedMaildir(types.SimpleNamespace)A class to monitor a Maildir and filter messages.MethodWatchedMaildir.close(self)Close the WatchedMaildir.MethodWatchedMaildir.flush(self)Forget state.
The set of lurkers is emptied.MethodWatchedMaildir.keypath(self, key)Return the kypath forkey.MethodWatchedMaildir.keys(self, flush=False)Return the keys of the Maildir.MethodWatchedMaildir.lurk(self, key)Addkeyto the luking list.MethodWatchedMaildir.remove(self, key)Removekeyfrom the maildir.MethodWatchedMaildir.unlurk(self, key)Removekeyfrom the lurking list.Release LogRelease 20200719:mailfiler: make "-R rules_pattern" a global option.Add some Received: headers, improving traceability.More friendly and less noisy terminal output (I run mailfiler as a daemon in a tmux session).Quite a few small internal changes.Release 20191006:
Update for recent cs.deco.cachedmethod rename.Release 20190512:Promote $DEFAULT to a list of targets.Implement save-to-self "." target to support folders where filing elsewhere is an exception.Move the manual entries to Markdown format.Release 20190103.1:
DISTINFO fix.Release 20190103:
Various fixes. Documentation improvements.Release 20160828:Update metadata with "install_requires" instead of "requires".A few bugfixes.Release 20160403:
Bug fix for new $ALERT_TARGETS feature.Release 20160402:Make rule processing more robust in the face of errors in individual targets.Add "report" operation for debugging rules against a test message.Add "function" targets.Make header values available for use in substitution rules.Allow local@domain and @domain inside (...|...) group matches.Honour new $ALERT_TARGETS variable for addition targets implied by issues an alert for a message.Release 20150805:better handling of configuration errorssubstitution actions accept multiple header namesinitial "scrub" actionfiddle headers of resent messages to avoid blowback to original authorsRelease 20150118.6:
further README updatesRelease 20150118.5:
more README formattingRelease 20150118.4:
more README fixesRelease 20150118.3:
cs.app.mailfiler README fixesRelease 20150118.2:
doc updatesRelease 20150118:
Initial PyPI release.