Provided by: afew_3.0.1-4_all bug

NAME

       afew - afew Documentation

       afew is an initial tagging script for notmuch mail:

       • http://notmuchmail.org/http://notmuchmail.org/initial_tagging/

       Its  basic  task  is  to  provide  automatic tagging each time new mail is registered with
       notmuch. In a classic setup, you might call it after notmuch new in  an  offlineimap  post
       sync hook or in the notmuch post-new hook.

       It  can  do  basic  thing  such  as adding tags based on email headers or maildir folders,
       handling killed threads and spam.

       fyi: afew plays nicely with alot, a GUI for notmuch mail ;)

       • https://github.com/pazz/alot

       Contents:

COMMAND LINE USAGE

       Ultimately afew is a command line tool.  You have to specify an action, and whether to act
       on all messages, or only on new messages.  The actions you can choose from are:

       tag    run the tag filters.  See Initial tagging.

       watch  continuously monitor the mailbox for new files

       move-mails
              move mail files between maildir folders

   Initial tagging
       Basic tagging stuff requires no configuration, just run

          $ afew --tag --new
          # or to tag *all* messages
          $ afew --tag --all

       To do this automatically you can add the following hook into your ~/.offlineimaprc:

          postsynchook = ionice -c 3 chrt --idle 0 /bin/sh -c "notmuch new && afew --tag --new"

       There  is  a  lot more to say about general filter Configuration and the different Filters
       provided by afew.

   Simulation
       Adding --dry-run to any --tag or --sync-tags action prevents modification of  the  notmuch
       db. Add some -vv goodness to see some action.

   Move Mode
       To  invoke  afew  in move mode, provide the --move-mails option on the command line.  Move
       mode will respect --dry-run, so throw in --verbose and watch what effects a real run would
       have.

       In  move  mode,  afew will check all mails (or only recent ones) in the configured maildir
       folders, deciding whether they should be moved to another folder.

       The decision is based on rules defined in your config file. A rule is bound  to  a  source
       folder and specifies a target folder into which a mail will be moved that is matched by an
       associated query.

       This way you will be able to transfer your  sorting  principles  roughly  to  the  classic
       folder  based maildir structure understood by your traditional mail server. Tag your mails
       with notmuch, call afew --move-mails in an offlineimap presynchook and enjoy a clean inbox
       in your webinterface/GUI-client at work.

       Note  that  in  move  mode, afew calls notmuch new after moving mails around.  You can use
       afew -m --notmuch-args=--no-hooks in a pre-new notmuch hook to avoid loops.

       For information on how to configure rules for move mode, what you can do with it and  what
       you can't, please refer to Move Mode.

   Commandline help
       The full set of options is:

          $ afew --help
          Usage: afew [options] [--] [query]

          Options:
            -h, --help            show this help message and exit

            Actions:
              Please specify exactly one action.

              -t, --tag           run the tag filters
              -w, --watch         continuously monitor the mailbox for new files
              -m, --move-mails    move mail files between maildir folders

            Query modifiers:
              Please specify either --all or --new or a query string.

              -a, --all           operate on all messages
              -n, --new           operate on all new messages

            General options:
              -C NOTMUCH_CONFIG, --notmuch-config=NOTMUCH_CONFIG
                                  path to the notmuch configuration file [default:
                                  $NOTMUCH_CONFIG or ~/.notmuch-config]
              -e ENABLE_FILTERS, --enable-filters=ENABLE_FILTERS
                                  filter classes to use, separated by ',' [default:
                                  filters specified in afew's config]
              -d, --dry-run       don't change the db [default: False]
              -R REFERENCE_SET_SIZE, --reference-set-size=REFERENCE_SET_SIZE
                                  size of the reference set [default: 1000]
              -T DAYS, --reference-set-timeframe=DAYS
                                  do not use mails older than DAYS days [default: 30]
              -v, --verbose       be more verbose, can be given multiple times

CONFIGURATION

   Configuration File
       Customization of tag filters takes place in afew's config file in ~/.config/afew/config.

   NotMuch Config
       afew  tries  to  adapt  to the new tag that notmuch sets on new email, but has mostly been
       developed and used against the new tag.  To use that,  make  sure  that  ~/.notmuch-config
       contains:

          [new]
          tags=new

       afew reads the notmuch database location from notmuch config. When no database path is set
       in notmuch config, afew uses the MAILDIR environment variable when set, or $HOME/mail as a
       fallback,  like  notmuch CLI does. If a relative path is provided, afew prepends $HOME/ to
       the path in the same manner as notmuch, which was introduced in version 0.28 of notmuch.

   Filter Configuration
       You can modify filters, and define your own versions of the base Filter that allow you  to
       tag  messages  in  a  similar  way to the notmuch tag command, using the config file.  The
       default config file is:

          [SpamFilter]
          [KillThreadsFilter]
          [ListMailsFilter]
          [ArchiveSentMailsFilter]
          sent_tag = ''
          [InboxFilter]

       See the Filters page for the details of  those  filters  and  the  custom  arguments  they
       accept.

       You  can  add  filters  based  on  the  base  filter  as well.  These can be customised by
       specifying settings beneath them.  The standard settings, which apply to all filters, are:

       message
              text that will be displayed while running this filter  if  the  verbosity  is  high
              enough.

       query  the  query to use against the messages, specified in standard notmuch format.  Note
              that you don't need to specify the new tag - afew will add that when run  with  the
              --new flag.

       tags   the  tags  to  add  or  remove  for  messages that match the query. Tags to add are
              preceded by a + and tags to  remove  are  preceded  by  a  -.   Multiple  tags  are
              separated by semicolons.

       tags_blacklist
              if  the  message has one of these tags, don't add tags to it. Tags are separated by
              semicolons.

       So to add the deer tag to any message to or from antelope@deer.com you could do:

          [Filter.1]
          query = 'antelope@deer.com'
          tags = +deer
          message = Wild animals ahoy

       You can also (in combination with the InboxFilter) have email skip the Inbox  by  removing
       the new tag before you get to the InboxFilter:

          [Filter.2]
          query = from'pointyheaded@boss.com'
          tags = -new;+boss
          message = Message from above

   Full Sample Config
       Showing some sample configs is the easiest way to understand.  The notmuch initial tagging
       page shows a sample config:

          # immediately archive all messages from "me"
          notmuch tag -new -- tag:new and from:me@example.com

          # delete all messages from a spammer:
          notmuch tag +deleted -- tag:new and from:spam@spam.com

          # tag all message from notmuch mailing list
          notmuch tag +notmuch -- tag:new and to:notmuch@notmuchmail.org

          # finally, retag all "new" messages "inbox" and "unread"
          notmuch tag +inbox +unread -new -- tag:new

       The (roughly) equivalent set up in afew would be:

          [ArchiveSentMailsFilter]

          [Filter.1]
          message = Delete all messages from spammer
          query = from:spam@spam.com
          tags = +deleted;-new

          [Filter.2]
          message = Tag all messages from the notmuch mailing list
          query = to:notmuch@notmuchmail.org
          tags = +notmuch

          [InboxFilter]

       Not that the queries do not generally include tag:new because this is implied when afew is
       run with the --new flag.

       The differences between them is that

       • the  ArchiveSentMailsFilter will add tags specified by sent_tag option (default '' means
         add no tags. You may want to set it to sent), as well as archiving  the  email.  And  it
         will not archive email that has been sent to one of your own addresses.

       • the  InboxFilter  does  not  add  the unread tag.  But most mail clients will manage the
         unread status directly in maildir.

   More Filter Examples
       Here are a few more example filters from github dotfiles:

          [Filter.1]
          query = 'sicsa-students@sicsa.ac.uk'
          tags = +sicsa
          message = sicsa

          [Filter.2]
          query = 'from:foosoc.ed@gmail.com OR from:GT Silber OR from:lizzie.brough@eusa.ed.ac.uk'
          tags = +soc;+foo
          message = foosoc

          [Filter.3]
          query = 'folder:gmail/G+'
          tags = +G+
          message = gmail spam

          # skip inbox
          [Filter.6]
          query = 'to:notmuch@notmuchmail.org AND (subject:emacs OR subject:elisp OR "(defun" OR "(setq" OR PATCH)'
          tags = -new
          message = notmuch emacs stuff

          # Assuming the following workflow: all messages for projects or releases should be tagged
          # as "project/A", "project/B" respectively "release/1.0.1" or "release/1.2.0".
          #
          # In most cases replies to messages retain their context: the project, the release(s), ..
          #
          # The following config will propagate all project/... or release/... tags from a thread
          # to all new messages.

          [PropagateTagsByRegexInThreadFilter.1]
          propagate_tags = project/.*
          # do not tag spam
          filter = not is:spam

          [PropagateTagsByRegexInThreadFilter.2]
          propagate_tags = release/.*

FILTERS

       The default filter set (if you don't specify anything in the config) is:

          [SpamFilter]
          [KillThreadsFilter]
          [ListMailsFilter]
          [ArchiveSentMailsFilter]
          [InboxFilter]

       The standard filter Configuration can be applied to these filters  as  well.  Though  note
       that  most  of  the  filters below set their own value for message, query and/or tags, and
       some ignore some of the standard settings.

   ArchiveSentMailsFilter
       It extends SentMailsFilter with the following feature:

          • Emails filtered by this filter have the new tag removed, so will not have  the  inbox
            tag added by the InboxFilter.

   DKIMValidityFilter
       This  filter  verifies  DKIM  signatures  of E-Mails with DKIM header, and adds dkin-ok or
       dkin-fail tags.

   DMARCReportInspectionFilter
       DMARC reports usually come in ZIP files. To check the report you have to unpack and search
       thru XML document which is very tedious. This filter tags the message as follows:

       if  there's  any SPF failure in any attachment, tag the message with "dmarc-spf-fail" tag,
       otherwise tag with "dmarc-spf-ok"

       if there's any DKIM failure in any attachment, tag the message with "dmarc-dkim-fail" tag,
       otherwise tag with "dmarc-dkim-ok"

   FolderNameFilter
       For each email, it looks at all folders it is in, and uses the path and filename as a tag,
       for the email.  So if you have a procmail or sieve set up that puts emails in folders  for
       you, this might be useful.

       • folder_explicit_list = <folder list>

          • Tag  mails  with  tag in <folder list> only. <folder list> is a space separated list,
            not enclosed in quotes or any other way.

          • Empty list means all folders (of course blacklist still applies).

          • The default is empty list.

          • You may use it e.g. to set tags only for specific folders like 'Sent'.

       • folder_blacklist = <folder list>

          • Never tag mails with tag in <folder list>. <folder list> is a space  separated  list,
            not enclosed in quotes or any other way.

          • The default is to blacklist no folders.

          • You  may  use  it  e.g. to avoid mails being tagged as 'INBOX' when there is the more
            standard 'inbox' tag.

       • folder_transforms = <transformation rules>

          • Transform folder names  according  to  the  specified  rules  before  tagging  mails.
            <transformation  rules>  is  a  space separated list consisting of 'folder:tag' style
            pairs. The colon separates the name of the folder to be transformed from the  tag  it
            is to be transformed into.

          • The default is to transform to folder names.

          • You  may  use  the  rules  e.g. to transform the name of your 'Junk' folder into your
            'spam' tag or fix capitalization of your draft and sent folder:

          folder_transforms = Junk:spam Drafts:draft Sent:sent

       • folder_lowercases = true

         • Use lowercase tags for all folder names

       • maildir_separator = <sep>

          • Use <sep> to split your maildir hierarchy into individual tags.

          • The default is to split on '.'

          • If your maildir hierarchy is represented in the filesystem as collapsed  dirs,  <sep>
            is used to split it again before applying tags. If your maildir looks like this:

          [...]
          /path/to/maildir/devel.afew/[cur|new|tmp]/...
          /path/to/maildir/devel.alot/[cur|new|tmp]/...
          /path/to/maildir/devel.notmuch/[cur|new|tmp]/...
          [...]

       the mails in your afew folder will be tagged with 'devel' and 'afew'.

       If instead your hierarchy is split by a more conventional '/' or any other divider

          [...]
          /path/to/maildir/devel/afew/[cur|new|tmp]/...
          /path/to/maildir/devel/alot/[cur|new|tmp]/...
          /path/to/maildir/devel/notmuch/[cur|new|tmp]/...
          [...]

       you need to configure that divider to have your mails properly tagged:

          maildir_separator = /

   HeaderMatchingFilter
       This  filter  adds  tags  to  a message if the named header matches the regular expression
       given.  The tags can be set, or based on the match.  The settings you can use are:

       • header = <header_name>

       • pattern = <regex_pattern>

       • tags = <tag_list>

       If you surround a tag with {} then it will be replaced with the named match.

       Some examples are:

          [HeaderMatchingFilter.1]
          header = X-Spam-Flag
          pattern = YES
          tags = +spam

          [HeaderMatchingFilter.2]
          header = List-Id
          pattern = <(?P<list_id>.*)>
          tags = +lists;+{list_id}

          [HeaderMatchingFilter.3]
          header = X-Redmine-Project
          pattern = (?P<project>.*)
          tags = +redmine;+{project}

       SpamFilter and ListMailsFilter are implemented using HeaderMatchingFilter,  and  are  only
       slightly more complicated than the above examples.

   InboxFilter
       This  removes  the  new  tag,  and adds the inbox tag, to any message that isn't killed or
       spam.  (The new tags are set in your notmuch config, and default to just new.)

   KillThreadsFilter
       If the new message has been added to a thread that has already been tagged killed then add
       the  killed  tag  to  this  message.  This allows for ignoring all replies to a particular
       thread.

   ListMailsFilter
       This filter looks for the List-Id header, and if it finds it, adds a tag lists and  a  tag
       named lists/<list-id>.

   MeFilter
       Add  filter tagging mail sent directly to any of addresses defined in Notmuch config file:
       primary_email or other_email.  Default tag is to-me and  can  be  customized  with  me_tag
       option.

   SentMailsFilter
       The settings you can use are:

       • sent_tag = <tag>

          • Add  <tag>  to  all mails sent from one of your configured mail addresses, and not to
            any of your addresses.

          • The default is to add no tag, so you need to specify something.

          • You may e.g. use it to tag all mails sent by you as 'sent'.  This  may  make  special
            sense  in  conjunction with a mail client that is able to not only search for threads
            but individual mails as well.

       • to_transforms = <transformation rules>

          • Transform To/Cc/Bcc e-mail addresses  to  tags  according  to  the  specified  rules.
            <transformation    rules>    is    a    space    separated    list    consisting   of
            'user_part@domain_part:tags' style pairs. The colon separates the e-mail  address  to
            be  transformed  from  tags  it is to be transformed into. ':tags' is optional and if
            empty, 'user_part' is used as  tag.   'tags'  can  be  a  single  tag  or  semi-colon
            separated list of tags.

          • It  can  be  used for example to easily tag posts sent to mailing lists which at this
            stage don't have List-Id field.

   SpamFilter
       The settings you can use are:

       • spam_tag = <tag>

          • Add <tag> to all mails recognized as spam.

          • The default is 'spam'.

          • You may use it to tag your spam as 'junk', 'scum' or whatever suits your mood.   Note
            that only a single tag is supported here.

       Email will be considered spam if the header X-Spam-Flag is present.

   Customizing filters
       To customize these filters, there are basically two different possibilities:

       Let's say you like the SpamFilter, but it is way too polite

       1. Create an filter object and customize it

          [SpamFilter.0] # note the index
          message = meh

       The  index  is  required if you want to create a new SpamFilter in addition to the default
       one. If you need just one customized SpamFilter, you can drop the index and customize  the
       default instance.

       2. Create a new type...

          [ShitFilter(SpamFilter)]
          message = I hatez teh spam!

       and create an object or two

          [ShitFilter.0]
          [ShitFilter.1]
          message = Me hatez it too.

       You can provide your own filter implementations too. You have to register your filters via
       entry points. See the afew setup.py for examples on how to register your filters.  To  add
       your  filters,  you  just  need  to  install  your  package  in  the  context  of the afew
       application.

MOVE MODE

   Configuration Section
       Here is a full sample configuration for move mode:

          [MailMover]
          folders = INBOX Junk
          rename = False
          max_age = 15

          # rules
          INBOX = 'tag:spam':Junk 'NOT tag:inbox':Archive
          Junk = 'NOT tag:spam AND tag:inbox':INBOX 'NOT tag:spam':Archive

       Below we explain what each bit of this means.

   Rules
       First you need to specify which folders should be checked for mails that are to  be  moved
       (as a whitespace separated list). Folder names containing whitespace need to be quoted:

          folders = INBOX Junk "Sent Mail"

       Then you have to specify rules that define move actions of the form

          <src> = ['<qry>':<dst>]+

       Every  mail  in  the <src> folder that matches a <qry> will be moved into the <dst> folder
       associated with that query.  A message that matches multiple queries  will  be  copied  to
       multiple destinations.

       You  can  bind  as  many rules to a maildir folder as you deem necessary. Just add them as
       elements of a (whitespace separated) list.

       Please note, though, that you need to specify at least one rule for every folder given  by
       the folders option and at least one folder to check in order to use the move mode.

          INBOX = 'tag:spam':Junk

       will  bind  one rule to the maildir folder INBOX that states that all mails in said folder
       that carry (potentially among others) the tag spam are to be moved into the folder Junk.

       With <qry> being an arbitrary notmuch query, you have the power to  construct  arbitrarily
       flexible  rules.  You  can  check for the absence of tags and look out for combinations of
       attributes:

          Junk = 'NOT tag:spam AND tag:inbox':INBOX 'NOT tag:spam':Archive

       The above rules will move all mails in Junk that don't have the spam tag but  do  have  an
       inbox  tag  into  the  directory INBOX. All other mails not tagged with spam will be moved
       into Archive.

   Max Age
       You can limit the age of mails you want to move by  setting  the  max_age  option  in  the
       configuration section. By providing

          max_age = 15

       afew will only check mails at most 15 days old.

   Rename
       Set  this  option  if  you  are  using the mbsync IMAP syncing tool.  mbsync adds a unique
       identifier to files' names when it syncs them.  If the rename option is  not  set,  moving
       files  can cause UID conflicts and prevent mbsync from syncing with error messages such as
       "Maildir error: duplicate UID 1234" or "UID 567 is beyond highest assigned UID 89".

       When the option is set, afew will rename files while moving them,  removing  the  UID  but
       preserving  other  mbsync information.  This allows mbsync to assign a new UID to the file
       and avoid UID conflicts.

       If you are using offlineimap, you can safely ignore this option.

          rename = True

   Limitations
       (1) Rules don't manipulate tags.

          INBOX = 'NOT tag:inbox':Archive
          Junk = 'NOT tag:spam':INBOX

       The above combination of rules might prove tricky, since you might expect de-spammed mails
       to  end  up  in  INBOX. But since the Junk rule will not add an inbox tag, the next run in
       move mode might very well move the matching mails into Archive.

       Then again, if you remove the spam tag and do not set an inbox tag, how would you come  to
       expect the mail would end up in your INBOX folder after moving it? ;)

       (2)  There  is no 1:1 mapping between folders and tags. And that's a feature. If you tag a
       mail with two tags and there is a rule for each of them, both rules will apply.  Your mail
       will be copied into two destination folders, then removed from its original location.

EXTENDING AFEW

       You can put python files in ~/.config/afew/ and they will be imported by afew.  If you use
       that python file to define a Filter class and use the register_filter decorator  then  you
       can refer to it in your filter configuration.

       So an example small filter you could add might be:

          from afew.filters.BaseFilter  import Filter
          from afew.FilterRegistry import register_filter

          PROJECT_MAPPING = {
              'fabric': 'deployment',
              'oldname': 'new-name',
          }

          @register_filter
          class RedmineFilter(Filter):
              message = 'Create tag based on redmine project'
              query = 'NOT tag:redmine'

              def handle_message(self, message):
                  project = message.get_header('X-Redmine-Project')
                  if project in PROJECT_MAPPING:
                      project = PROJECT_MAPPING[project]
                  self.add_tags(message, 'redmine', project)

       We  have  defined  the message and query class variables that are used by the parent class
       Filter.  The message is printed when running with verbose flags.  The  query  is  used  to
       select  messages to run against - here we ensure we don't bother looking at messages we've
       already looked at.

       The handle_message() method is the key one to implement.  This will  be  called  for  each
       message  that  matches  the  query.   The argument is a notmuch message object and the key
       methods used by the afew filters are get_header(), get_filename() and get_thread().

       Of the  methods  inherited  from  the  Filter  class  the  key  ones  are  add_tags()  and
       remove_tags(),  but read about the Implementation or just read the source code to get your
       own ideas.

       Once you've defined your filter, you can add it to your config like any other filter:

          [RedmineFilter]

IMPLEMENTATION

   Database Manager
       The  design  of  the  database  manager   was   inspired   by   alots   database   manager
       alot.db.DBManager.

       class afew.Database.Database
              Convenience wrapper around notmuch.

              add_message(path, sync_maildir_flags=False, new_mail_handler=None)
                     Adds the given message to the notmuch index.

                     Parameterspath (str) -- path to the message

                            • sync_maildir_flags  (bool) -- if True notmuch converts the standard
                              maildir flags to tags

                            • new_mail_handler (a function that is called with a  notmuch.Message
                              object as its only argument) -- callback for new messages

                     Raises notmuch.NotmuchError if adding the message fails

                     Returns
                            a notmuch.Message object

              close()
                     Closes the notmuch database if it has been opened.

              do_query(query)
                     Executes a notmuch query.

                     Parameters
                            query (str) -- the query to execute

                     Returns
                            the query result

                     Return type
                            notmuch.Query

              get_messages(query, full_thread=False)
                     Get all messages mathing the given query.

                     Parametersquery (str) -- the query to execute using Database.do_query()full_thread (bool) -- return all messages from mathing threads

                     Returns
                            an iterator over notmuch.Message objects

              remove_message(path)
                     Remove the given message from the notmuch index.

                     Parameters
                            path (str) -- path to the message

              walk_replies(message)
                     Returns all replies to the given message.

                     Parameters
                            message (notmuch.Message) -- the message to start from

                     Returns
                            an iterator over notmuch.Message objects

              walk_thread(thread)
                     Returns all messages in the given thread.

                     Parameters
                            thread (notmuch.Thread) -- the tread you are interested in

                     Returns
                            an iterator over notmuch.Message objects

   Filter
       class afew.filters.BaseFilter.Filter(database, **kwargs)

              flush_changes()
                     (Re)Initializes  the  data  structures that hold the enqueued changes to the
                     notmuch database.

   Configuration management
   Miscellanious utility functionsIndexModule IndexSearch Page

AUTHOR

       Justus Winter

COPYRIGHT

       afewmail project