Kodiologist · 2022-06-06 21:21
I recently set up mu4e with mbsync and smtpmail and overall I'm pretty happy with it so far. The one thing that gets me is that I'm not clear how to keep the remote IMAP server up to date. I have `mu4e-get-mail-command` set to `"mbsync -a"`, and I know `mu4e-update-interval` can be used to run that command every so often, but as I understand it, if I make a change like deleting a message and then quit Emacs before the next update interval, the server won't see that change until I'm running mu4e again. I think what's needed is a way to trigger mbsync after every change, or every batch of changes, rather than after a set time. What's a good way to do this?
[deleted] · 2022-06-06 22:03
[deleted]
polaris64 · 2022-06-07 08:42
I've just got into the habit of running `mu4e-update-mail-and-index` whenever I do a batch of operations that I want committed immediately. I use multiple mu4e contexts so I've also created a function which temporarily binds a context-specific value to `mu4e-get-mail-command` (e.g. "mbsync my-profile-name") which allows me to commit changes to a single account if I want.
I find this to be better than for example adding a hook which runs an update after every change. I might make a mistake and it's handy that things aren't committed immediately to the server.
alrasdk · 2022-06-07 19:01
A couple of years ago I also looked for a way to query mu/mu4e for a list of changed folders which could be synchronized using "mbsync account:folder".
As neither mu nor mu4e could answer my query, I resorted to comparing the filesystem timestamp of the "maildir/account/folder/.mbsyncstate" file against the "cur", "new" and "tmp" directories in the same folder. If any dir has a newer timestamp, the folder needs updating.
My python experience was limited at the time, but I came up with the following
​
#!/usr/bin/python3
# mail-changes-sync.py
import os import sys
def findChangedFolders(maildir, account, sep): changedFolders = []
accountDir = maildir+"/"+account
#print("AccountDir: "+accountDir)
for root, dirs, files in os.walk(accountDir, topdown=True, followlinks=False):
#print("Root: "+root)
if '.mbsyncstate' in files:
mbstateTime = os.path.getmtime(root+"/.mbsyncstate")
dirsTime = max(os.path.getmtime(root+"/cur"),
os.path.getmtime(root+"/new"),
os.path.getmtime(root+"/tmp"))
if (mbstateTime < dirsTime): changedFolders.append(
account+":"+sep+root.replace(accountDir+"/",""))
# Do not recurse into account folder subdirs
dirs.remove('cur')
dirs.remove('new')
dirs.remove('tmp')
return(changedFolders)
def updateFolders(folderList):
for f in folderList:
mailFolder = f.replace(" ", "\\ ")
print("Syncing folder: "+mailFolder)
mailSync = "mbsync "+mailFolder
print(mailSync)
os.system(mailSync)
maildir = "/home/user/.maildir"
updateFolders(findChangedFolders(maildir, "privatemail", ""))
updateFolders(findChangedFolders(maildir, "workmail1", "/"))
updateFolders(findChangedFolders(maildir, "workmail2", "/"))
​
There are two peculiarities about the script/method.
1. Any Drafts folder seems to always be recognized as needing updates. This is just a single folder update, so I didn't investigate further.
2. The reason for the "sep" arg in "findChangedFolders" is that at least one mail server fails when running "mbsync account:/folder", but succeeds without the slash: "mbsync account:folder". For other servers it is/was the other way around. I didn't look into why this is or if there are ways to determine the need for the '/' automatically.
At the time I just needed something that worked and the script still does it's job for me on a daily basis; your mileage may vary, so adapt as you see fit.In emacs you can make a function to run the script and bind this to a mu4e shortcut:
(defun mail-changes-sync ()
(interactive)
(call-process "/home/alras/.local/bin/mail-changes-sync.py" nil (get-buffer-create "Mail-Sync") nil) )
(define-key mu4e-main-mode-map (kbd "Y") #'mail-changes-sync)
There used to be a "mu4e-headers-view-quit-hook", which was perfect for adding the above function to so the changes were sync'ed automatically when returning from a folder view to the mu4e Main page. Nowadays, I just run the script via shortcut after a "deal with email session".
\[edit: formatting\]
Kodiologist · 2022-06-07 21:35
Why not just `mbsync -a`, instead of trying to determine which folders need updates yourself?
alrasdk · 2022-06-08 05:44
The simple reason is speed; it's much faster to update only a few folders instead of everything.
One particular use-case is marking a few mails in a single INBOX as read to synchronize an external mail-notifier like mailnag. There's also no need to run "empty" updates on servers without any changes.