I had assumed that most modern email services, like Gmail, allow users to schedule emails to be sent at some later specified time, but a quick Google search reveals that that’s not quite the case. It looks like you need to use a browser extension like Boomerang or Right Inbox.
But what if you don’t trust browser extensions/third parties to handle private
emails? Or what if you don’t use Firefox, Chrome, etc.? (I use dwb.) In
this post I’ll explain how Linux users who are already set up with mutt (or
any mail client with similar command-line capability) can harness the powers of
mutt to schedule emails.
at command lets you schedule tasks (shell commands) that are to be
executed at a specified time. The basic syntax is
at TIMESPEC, where timespec
is something like
now + 10 minutes,
11:59pm Dec 31, etc.
at command is run from a terminal, and once you specify the timespec and
hit enter, you’re put into an interactive prompt where you list the commands
that you want
at to execute at the specified time. Hit
<Ctrl-D> to finish,
<Ctrl-C> to cancel. For example:
$ at now + 1 minute warning: commands will be executed using /bin/sh at> echo "testing out at" >>~/my-at-test at> <EOT> job 13 at Fri Jan 4 11:46:00 2013
In the above code, we tell
at that 1 minute from now, it should append the
text “testing out at” to the file
my-at-test (and create it if it doesn’t
You can run
atq to view the queue of current jobs,
atrm JOBID to remove a
at -c JOBID to view (cat) a queued job.
at accepts any shell command, we can schedule emails using mutt’s
command-line interface. The basic syntax for sending emails with mutt from the
command line is
$ echo "MSG" | mutt -s SUBJ -- RECIPIENT # for simple messages $ mutt -s SUBJ -- RECIPIENT <MSG # for longer messages (files)
Suppose I want to email myself a reminder tomorrow at 10am to call John. Here’s what I do.2
$ at 10am tomorrow warning: commands will be executed using /bin/sh at> echo "Remember to call John." | mutt -s "Call John" -- me at> <EOT> job 14 at Sat Jan 5 10:00:00 2013
There’s a problem though. If my computer is off tomorrow at 10am, nothing will happen. And if my computer is on but not connected to the internet, then the job will technically be executed (and thus be subsequently removed from the queue), but no mail will be sent.
Moreover, if my computer is off tomorrow at 10am, then
at will execute the
command the next time I boot, but unfortunately it’ll do so immediately, before
enough time has passed to allow my wifi connection to be established.
There’s really no complete remedy to these problems except to ensure that the computer is on and connected to the internet at the specified time (which is no problem for people who rarely turn off their computers, or for dedicated servers).
But if the computer is off and/or not online, there is still a way to ensure
that the email is not sent until a wifi connection is established. We just need
to write a simple shell script,
check-wifi, which only exits once a wifi
connection is established.
#!/bin/bash until [[ -n "$(iwgetid)" ]]; do sleep 1 done exit 0
iwgetid is a command that returns the ESSID of the current wifi connection if
there is one, and nothing otherwise. So this script does the following: keep
waiting (sleeping) until
iwgetid returns a string of nonzero length, then exit
with status 0. (Remember to make it executable:
chmod a+x check-wifi.)
Now we can modify our
at commands as follows:
$ at 10am tomorrow at> /path/to/check-wifi at> echo "Remember to call John." | mutt -s "Call John" -- me at> <EOT>
Now the email won’t try to be delivered until
check-wifi finishes running,
i.e., until a wifi connection is established.
We can also modify
check-wifi to time out after, say, 3 minutes of no wifi,
and to write something to a log file.
#!/bin/bash COUNT=0 TIMEOUT=180 E_TIMEOUT=70 until [[ -n "$(iwgetid)" ]]; do sleep 1 let "COUNT+=1" # wait $TIMEOUT seconds, then exit if [[ $COUNT -ge $TIMEOUT ]]; then echo "$(date '+%F %T') \ Wifi connection not established. No mail sent." >>~/.at.log exit $E_TIMEOUT fi done exit 0
The result of all this is that I can schedule an email for, say, 6am tomorrow, when my computer is probably off, and it’ll get delivered the moment I boot up and connect to the internet. Or I can schedule a birthday email for 6am on John’s birthday, and it’ll get sent the moment I boot up and get online, assuming I do so on John’s birthday.
As you can see, the possibilities with
at, mutt, and shell scripting are
atcomes with a daemon,
atd, which must be running in order to schedule and execute commands. If you get the error
Can't open /var/run/atd.pid to signal atd. No atd running?
then it means
atdis not running. Either run
sudo atdto run
atdjust this once, or do whatever is necessary to have
atdload on boot. (In Arch Linux:
sudo systemctl enable atd.service.) ↩
mealiased to my email address in
~/.mutt/alias, which is sourced in