From 9a23ae29de6eb1312f59fddebe8f58f2a55577c7 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Tue, 12 Jun 2018 15:03:51 +0200 Subject: [PATCH 1/4] allow to specify args for notmuch new In move mode, afew calls `notmuch new` after moving mails around. This prevents `afew -m` from being used in a pre-new hook in `notmuch`. Allow to specify args, so that `afew -m --notmuch-args=--no-hooks` can live happily in a pre-new hook. --- afew/MailMover.py | 5 +++-- afew/commands.py | 4 ++++ afew/main.py | 2 +- docs/commandline.rst | 4 ++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/afew/MailMover.py b/afew/MailMover.py index d47d1aa..f37a495 100644 --- a/afew/MailMover.py +++ b/afew/MailMover.py @@ -19,7 +19,7 @@ class MailMover(Database): ''' - def __init__(self, max_age=0, rename = False, dry_run=False): + def __init__(self, max_age=0, rename = False, dry_run=False, notmuch_args=''): super().__init__() self.db = notmuch.Database(self.db_path) self.query = 'folder:"{folder}" AND {subquery}' @@ -31,6 +31,7 @@ def __init__(self, max_age=0, rename = False, dry_run=False): now=now.strftime('%s')) self.dry_run = dry_run self.rename = rename + self.notmuch_args = notmuch_args def get_new_name(self, fname, destination): if self.rename: @@ -107,7 +108,7 @@ def __update_db(self, maildir): Update the database after mail files have been moved in the filesystem. ''' try: - check_call(['notmuch', 'new']) + check_call(['notmuch', 'new'] + self.notmuch_args.split()) except CalledProcessError as err: logging.error("Could not update notmuch database " \ "after syncing maildir '{}': {}".format(maildir, err)) diff --git a/afew/commands.py b/afew/commands.py index 336d0c7..ddb5f1e 100644 --- a/afew/commands.py +++ b/afew/commands.py @@ -89,6 +89,10 @@ help='be more verbose, can be given multiple times' ) +options_group.add_argument( + '-N', '--notmuch-args', default='', + help='arguments for notmuch new (in move mode)' +) def main(): if sys.version_info < (3,4): diff --git a/afew/main.py b/afew/main.py index 79325d5..295614c 100644 --- a/afew/main.py +++ b/afew/main.py @@ -29,7 +29,7 @@ def main(options, database, query_string): quick_find_dirs_hack(database.db_path)) elif options.move_mails: for maildir, rules in options.mail_move_rules.items(): - mover = MailMover(options.mail_move_age, options.mail_move_rename, options.dry_run) + mover = MailMover(options.mail_move_age, options.mail_move_rename, options.dry_run, options.notmuch_args) mover.move(maildir, rules) mover.close() else: diff --git a/docs/commandline.rst b/docs/commandline.rst index 7eca252..dbe3d27 100644 --- a/docs/commandline.rst +++ b/docs/commandline.rst @@ -63,6 +63,10 @@ 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 :doc:`move_mode`. From d9bc00cd0e9f5cc4c0eb2e5ad2f09b0ec4f9856f Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Thu, 14 Jun 2018 13:38:38 +0200 Subject: [PATCH 2/4] MailMover: fix renames `:flags` need to be preserved when renaming files, but UIDs of the form `U=[0-9]+` should be removed. The current code fails to do that when a mail file has a UID but no flags. Change the code to nuke the non-flag part in any case. --- afew/MailMover.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/afew/MailMover.py b/afew/MailMover.py index d47d1aa..821c0f8 100644 --- a/afew/MailMover.py +++ b/afew/MailMover.py @@ -34,11 +34,16 @@ def __init__(self, max_age=0, rename = False, dry_run=False): def get_new_name(self, fname, destination): if self.rename: + parts = os.path.basename(fname).split(':') + if len(parts) > 1: + flagpart = ':' + parts[-1] + else: + flagpart = '' return os.path.join( destination, # construct a new filename, composed of a made-up ID and the flags part # of the original filename. - str(uuid.uuid1()) + ':' + os.path.basename(fname).split(':')[-1] + str(uuid.uuid1()) + flagpart ) else: return destination From b89d86ab78c1980c483b481ab287289fb4a7d09d Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Thu, 14 Jun 2018 14:19:15 +0200 Subject: [PATCH 3/4] MailMover: refactor get_new_name() Refactor so that the name generation becomes clearer, and before changing the dir generation. Change in behavour: returns a full path instead of a dir now in the rename==False case. --- afew/MailMover.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/afew/MailMover.py b/afew/MailMover.py index 821c0f8..2f278c3 100644 --- a/afew/MailMover.py +++ b/afew/MailMover.py @@ -33,20 +33,17 @@ def __init__(self, max_age=0, rename = False, dry_run=False): self.rename = rename def get_new_name(self, fname, destination): + basename = os.path.basename(fname) if self.rename: - parts = os.path.basename(fname).split(':') + parts = basename.split(':') if len(parts) > 1: flagpart = ':' + parts[-1] else: flagpart = '' - return os.path.join( - destination, # construct a new filename, composed of a made-up ID and the flags part # of the original filename. - str(uuid.uuid1()) + flagpart - ) - else: - return destination + basename = str(uuid.uuid1()) + flagpart + return os.path.join(destination, basename) def move(self, maildir, rules): ''' From d96c0accd4babe6a4bd0dd2b1bbe04ed2e369af0 Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Thu, 14 Jun 2018 14:30:33 +0200 Subject: [PATCH 4/4] MailMover: preserve maildir subdir Currently, MailMover moves all mail to `/cur`. But everyone moving mail from `/new` to `/cur` is required to set up the maildir flags field in the name. Rather than setting up that field, preserve the maildir subdir part and let other clients change subdirs as necessary. After all, "moving" does not constitute "reading". --- afew/MailMover.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/afew/MailMover.py b/afew/MailMover.py index 2f278c3..9f75122 100644 --- a/afew/MailMover.py +++ b/afew/MailMover.py @@ -34,6 +34,7 @@ def __init__(self, max_age=0, rename = False, dry_run=False): def get_new_name(self, fname, destination): basename = os.path.basename(fname) + submaildir = os.path.split(os.path.split(fname)[0])[1] if self.rename: parts = basename.split(':') if len(parts) > 1: @@ -43,7 +44,7 @@ def get_new_name(self, fname, destination): # construct a new filename, composed of a made-up ID and the flags part # of the original filename. basename = str(uuid.uuid1()) + flagpart - return os.path.join(destination, basename) + return os.path.join(destination, submaildir, basename) def move(self, maildir, rules): ''' @@ -54,7 +55,7 @@ def move(self, maildir, rules): to_delete_fnames = [] moved = False for query in rules.keys(): - destination = '{}/{}/cur/'.format(self.db_path, rules[query]) + destination = '{}/{}/'.format(self.db_path, rules[query]) main_query = self.query.format( folder=maildir.replace("\"", "\\\""), subquery=query) logging.debug("query: {}".format(main_query))