12

I don't like waking up early but people prefer to be emailed in the morning rather than at 3AM. Therefore I often use at to send the email whilst I'm asleep.

But that comes with the complication that I need to write the email as a text file and send it with sendmail. I leave those not yet sent emails in Mutt's postponed mbox. Is there a way to use mutt to send that email?

OK, one way to send a mail later with mutt is the following:

echo 'cat /home/grochmal/body | mutt -s "mail" [email protected]' | at now + 12 hours

But I have that mail in the postponed mbox.

If I have only a single postponed mail, I can do this:

echo '/usr/sbin/sendmail -t <(cat /home/grochmal/mail/postponed | sed 1d)' | at now + 12 hours

But I often have several postponed emails in my postponed mbox, how do I select the one I want to send?

The relevant parts of my muttrc are:

set sendmail  = "/usr/sbin/sendmail -oem -oi -f $EMAIL"
set folder    = $HOME/mail
set record    = +sent
set postponed = +postponed

My /usr/sbin/sendmail is just a softlink to the postfix wrapper.

Matthias Braun
  • 7,797
  • 7
  • 45
  • 54
grochmal
  • 8,489
  • 4
  • 30
  • 60
  • Interactively: `Shift-r` to open a menu. On the command line: `mutt -p`. Not sure what happens when you have several postponed messages and you run `mutt -p`, but I presume it's easy to experiment and find out. – Satō Katsura Sep 17 '16 at 03:32
  • @SatoKatsura - Ooops, I just noticed that I have not been clear. I made a small revamp of the question. In summary, I normally use `at` to send emails because I'm asleep during the period I want the email to come out. – grochmal Sep 17 '16 at 03:53
  • @SatoKatsura - Oh yeah, just tested, `mutt -p` simply opens the postponed mbox (and displays a list of postponed messages) when there is more than one. – grochmal Sep 17 '16 at 03:55
  • 3
    Then you're using the wrong tool for the job. Send messages normally. Configure your MTA to defer messages by default, then flush the queue from `cron` between night hours. – Satō Katsura Sep 17 '16 at 04:45
  • As an alternative: Open `mutt -p`, select the message of interest, save it to a file, and then use that file in your `at` pipeline command. – John1024 Sep 17 '16 at 07:10
  • @SatoKatsura - Valid point, but on serverfault they [argue the opposite](http://serverfault.com/questions/312516/postfix-delay-mail-processing). But I'm not taking their side, that looks like an MTA task for me. Still `man 8 defer` did not give me the info on how to force queues into defer mode. And I'm not confident in using `postsuper -H ALL` and `postsuper -h ALL` (i.e. it does not appear to work and I'm struggling to debug it) – grochmal Sep 18 '16 at 02:16
  • To defer all messages you'd point a transport to `defer`, but the exact incantation depends on your setup. It certainly can't be done blindly. One way to hold all messages is to add `static:HOLD` to an access map. To do that only for outgoing messages you'd need some simple `main.cf`-fu. To release messages from hold you'd run `postsuper -H ALL`, then `postsuper -r ALL` to re-queue them. Also run `postsuper -h ALL` and `postsuper -r ALL` at the start of the day, to put back on hold the ones that couldn't go out in time. Either way, you'd need to understand what you're doing. – Satō Katsura Sep 18 '16 at 03:35
  • using command `mutt -e 'push y; push =.;exec recall-message; push :set\ editor='` allow to send postponed message automatically. If you change equal sign in `push =` into any number it will select desired (by number) message (equal sign is first, and asterisk is last message in postpone mailbox, but be aware of dependence of your sorting scheme). You can also use `/string_to_find` to select message with substring search. **BUT**: I don't know why it does not work when I pass this to `at` or `cron` scheduler. – mrajner Sep 18 '16 at 13:55
  • @SatoKatsura - Thanks for that. This gives me a reason to start reading that Postfix book i bought 5 years ago and never went past the introduction. I'll probably make a self answer in 2-3 months (I read slowly). – grochmal Sep 22 '16 at 02:52
  • I recommend you to get the earliest versions of postfix you can find and read the docs. The overall architecture hasn't changed that much over the years, and an early version should give you a higher level view of what the various daemons are supposed to be doing and how they are playing together, without all the clutter that has been added over the years. After you get an idea what's going on you can of course read the details in the current manuals. – Satō Katsura Sep 22 '16 at 04:27
  • 2
    I'd suggest using a maildir instead of an mbox for postponed messages; then you can use a simple shell `for` loop to loop over all postponed mail and send it out. You can even get fancy and add a custom header to each that determines when it should be sent. – András Korn May 15 '19 at 20:53

1 Answers1

4

I've discovered this script msmtpqueue mentioned by whereistejas on irc.freenode.net/neomutt

Change your smtp command to msmtp-enqueue.sh. Emails will be queued instead of being sent. You can send them later with msmtp-runqueue.sh. To schedule sending you can use at(1).

All emails in a queue are sent when msmtp-runqueue.sh is executed. But with a little change to msmtp-runqueue.sh you can schedule multiple bulks to be sent.

QUEUEDIR=${QUEUEDIR:-~/.msmtpqueue}

To send messages in two different bulks you can:

  1. enqueue the first bulk
  2. move the QUEUEDIR
  3. schedule msmtp-runqueue.sh with at(1) with QUEUEDIR env var pointing to the new directory location
  4. repeat steps for second bulk
Matthias Braun
  • 7,797
  • 7
  • 45
  • 54
Jakub Jindra
  • 1,392
  • 1
  • 12
  • 25
  • Just did have the time to try it, it is pretty neat (+1). Very simple but well made piece of code, with proper locks and wait times. Can be `cron`-ed or `at`-ed. I believe it is good enough to be considered part of the `mutt` family of scripts. – grochmal Dec 09 '19 at 17:01
  • Can we do something similar with postfix + smtp? – user3236841 Oct 06 '21 at 03:02