msmtpq (10791B)
1 #!/bin/bash 2 3 #-------------------------------------------------------------- 4 # 5 # msmtpq : queue funtions to manage the msmtp queue, 6 # as it was defined by Martin Lambers 7 # Copyright (C) 2008 Chris Gianniotis 8 # 9 # This program is free software: you can redistribute it and/or modify 10 # it under the terms of the GNU General Public License as published by 11 # the Free Software Foundation, either version 3 of the License, or (at 12 # your option) any later version. 13 # 14 #-------------------------------------------------------------- 15 16 #-------------------------------------------------------------- 17 # 18 # This version has tiny modifications by Marianne Promberger to the original 19 # found here: 20 # http://www.mail-archive.com/msmtp-users@lists.sourceforge.net/msg00005.html 21 # 22 # -- cleaned up accidental linebreaks in comments 23 # -- changed shell from /bin/sh to /bin/bash 24 # -- changed logfile location 25 # 26 # marianne@promberger.info 27 #-------------------------------------------------------------- 28 29 #-------------------------------------------------------------- 30 # the msmtp queue contains unique filenames of the following form : 31 # two for each mail in the queue 32 # 33 # create new unique filenames of the form : 34 # MLF: ccyy-mm-dd-hh.mm.ss[-x].mail -- mail file 35 # MSF: ccyy-mm-dd-hh.mm.ss[-x].msmtp -- msmtp command line file 36 # where x is a consecutive number only appended for uniqueness 37 # if you send more than one mail per second 38 #-------------------------------------------------------------- 39 40 41 # msmtpq is meant to be used to maintain the msmtp queue 42 # there is a separate log file for all events & operations on the msmtp 43 # queue that is defined below 44 45 46 ## !! please define the following two vars before using the msmtpq & msmtpQ 47 ## !! routines 48 49 # msmtpQ is meant to be used directly by an email client - in 'sendmail' mode 50 51 # set the queue var to the location of the msmtp queue directory 52 # if the queue dir doesn't yet exist, better to create it (0700) 53 # before using this routine (it will only complain ...) 54 # 55 Q=~/msmtp.queue # the queue - modify this to reflect where 56 # you'd like it to be 57 58 # set the queue log var to the location of the msmtp queue log file 59 # where it is or where you'd like it to be 60 # ( note that the LOG setting could be the same as the ) 61 # ( 'logfile' setting in .msmtprc - but there may be ) 62 # ( some advantage in keeping the two logs separate ) 63 # if you don't want the log please unset (comment out) this var 64 # 65 LOG=~/logs/msmtp-queue # the log - modify to taste ... 66 67 umask 077 # set secure permissions on created 68 # directories and files 69 70 declare -i CNT # a count of mail(s) currently in the queue 71 72 usage() { 73 echo 74 [ -n "$1" ] && { dsp '' "$@" '' ; echo ; } 75 echo ' usage : msmtpq functions' 76 echo 77 echo ' msmtpq <op>' 78 echo ' ops : -r run (flush) mail queue' 79 echo ' -d display (list) queue contents' 80 echo ' -p purge a single mail from queue' 81 echo ' -a purge all mail in queue' 82 echo ' -h this helpful blurt' 83 echo 84 echo ' - note that only one op per invocation is allowed' 85 echo ' - if more than one op is specified, the first one' 86 echo ' only is executed' 87 echo 88 [ -n "$1" ] && exit 1 89 exit 0 90 } 91 92 # display a message, possibly an error 93 # usage : dsp [ -e ] [ -l ] msg [ msg ] ... 94 # opts : -e an error ; display msg & terminate w/prejudice 95 # opts : -L don't log this ; display msg only 96 dsp() { 97 local ARG ERR NOL PFX 98 99 [ "$1" == '-e' ] && \ 100 { ERR='t' ; shift ; } # set error flag ; shift opt off 101 [ "$1" == '-L' ] && \ 102 { NOL='t' ; shift ; } # set don't log flag ; shift opt off 103 104 for ARG ; do # each msg line out ; no content - send blank 105 if [ -n "$ARG" ] ; then # line has content 106 echo " $ARG" # send it out 107 else 108 echo # send out blank 109 fi 110 done 111 112 if [ -n "$LOG" ] && [ -z "$NOL" ] ; then # logging allowed (not suppressed) 113 PFX="$(/bin/date +'%Y %b %d %H:%M:%S')" # time stamp prefix - "2008 Mar 13 114 # 03:59:45 " 115 for ARG ; do # each msg line out 116 [ -n "$ARG" ] && \ 117 echo "$PFX : $ARG" >> "$LOG" # line has content ; send it to log 118 done 119 fi 120 121 [ -n "$ERR" ] && exit 1 # error ; leave w/error return 122 } 123 124 # verify that the msmtp queue is present 125 # the first version can be used if you'd like to create the queue dir 126 # if it's not found ; I'd rather just be warned if it's not there 127 check_queue() { # make certain queue dir is present 128 #if [ ! -d "$Q" ] ; then # queue dir not present ; create it 129 # /bin/mkdir -p "$Q" || dsp -e 'could not create queue dir' 130 # dsp "created msmtp queue dir [ $Q ]" 131 #fi 132 [ -d "$Q" ] || \ 133 dsp -e "can't find msmtp queue [ $Q ]" # queue dir not present - complain 134 } 135 136 # run (flush) queue 137 run_queue() { # run queue 138 local LOK="${Q}/.lock" MLF MSF # lock file name ; queued mail filename pairs 139 local -i MAX=120 SEC=0 RC # max seconds to gain a lock ; seconds waiting 140 141 if (( $(/bin/ls -1 ${Q}/*.mail 2> /dev/null | \ 142 /usr/bin/wc -l) > 0 )) ; then # if any mail in Q 143 # attempt to lock queue 144 while [ -e "$LOK" ] && (( SEC < MAX )) ; do # if a lock file there 145 /bin/sleep 1 # wait a second 146 (( ++SEC )) # accumulate seconds 147 done # try again while locked 148 # for MAX secs 149 if [ -e "$LOK" ] ; then # lock file still there, give up 150 dsp -e '' "cannot use $Q : waited $MAX seconds for"\ 151 " lockfile [ $LOK ] to vanish ; giving up"\ 152 'if you are sure that no other instance of this script'\ 153 ' is running, then delete the lock file manually' '' 154 fi 155 156 /bin/touch "$LOK" || \ 157 dsp -e "couldn't create lock file [ $LOK ]" # lock queue 158 159 for MLF in ${Q}/*.mail ; do # process all mails 160 dsp "sending mail file [ $MLF ] ..." # scratch user's itch 161 MSF="${MLF%.*}.msmtp" 162 if [ ! -f "$MSF" ] ; then # no corresponding MSF file found 163 dsp "corresponding mail file [ $MSF ] not found in queue"\ 164 ' worth an investigation ...' # give user the bad news 165 continue # crank on 166 fi 167 /usr/bin/msmtp $(/bin/cat "$MSF") < "$MLF" # this mail goes out the door 168 RC=$? 169 if [ $RC == 0 ] ; then # send was successful 170 /bin/rm -f "$MLF" "$MSF" # nuke the mail files 171 dsp "sent mail [ $MLF ] from queue : send successful ; purged from queue" # good news to user 172 else # send was unsuccessful 173 dsp "sent mail [ $MLF ] from queue ; send failed ; msmtp rc = $RC" # bad news ... 174 fi 175 done 176 else # no mails in queue 177 dsp -L '' 'mail queue is empty'\ 178 'nothing to run/flush' '' # inform user 179 fi 180 181 /bin/rm -f "$LOK" # remove the lock 182 nohup notmuch new & 183 } 184 185 # display queue contents 186 display_queue() { 187 local M LST="$(/bin/ls $Q/*.mail 2>/dev/null)" # list of mails in queue 188 189 (( CNT = 0 )) 190 if [ -n "$LST" ] ; then # list has contents (any mails in queue) 191 for M in $LST ; do # cycle through each 192 dsp -L '' "mail id = [ $(/usr/bin/basename $M .mail) ]" # show mail id 193 /bin/egrep -s --colour -h '(^From:|^To:|^Subject:)' "$M" # show mail info 194 (( CNT++ )) # bump counter 195 done 196 echo 197 else # no mails ; no contents 198 dsp -L '' 'no mail in queue' '' # inform user 199 fi 200 } 201 202 # delete all mail in queue 203 purge_all_mail() { # <-- 'one mail' opt (-1) 204 local YN I C # confirmation response ; question text ; ack text 205 206 if [ "$1" == '-1' ] ; then # queue contains single mail 207 I="remove the only mail from the queue" 208 C="single mail purged from queue" 209 else # queue contains multiple mails 210 I="remove (purge) all mail from the queue" 211 C="msmtp queue purged (all mail)" 212 display_queue 213 fi 214 215 echo -n " $I [y/N] ? ...: " ; read YN 216 case $YN in # nuke all mail in queue (dir) 217 y|Y) /bin/rm -f "$Q"/*.* ; dsp '' "$C ..." '' ;; 218 *) dsp -L '' 'nothing done ; queue is untouched ...' '' ;; 219 esac 220 } 221 222 # purge a single mail from queue 223 purge_one_mail() { 224 local ID # id of mail being deleted 225 226 while true ; do # purge an individual mail from queue 227 display_queue # show queue contents, if any 228 if (( CNT > 0 )) ; then # something there 229 if (( CNT == 1 )) ; then # only one mail 230 purge_all_mail -1 # purge it 231 break 232 else # more than one mail 233 echo ' remove (purge) a mail from the queue ; enter its id' 234 echo -n ' ( <cr> only to exit ) ...: ' ; read ID 235 if [ -n "$ID" ] ; then # <-- file name (only, no suff) 236 if [ -n "$(/bin/ls "$Q"/"$ID".* 2>/dev/null)" ] ; then 237 /bin/rm -f "$Q"/"$ID".* # msmtp - nukes a single mail in queue (dir) 238 dsp '' "mail [ $ID ] purged from queue ..." 239 else # invalid id entered 240 dsp -L '' "mail [ $ID ] not found ; bad id ..." 241 fi 242 else # nothing entered 243 dsp -L '' 'nothing done ; queue is untouched ...' '' 244 break 245 fi 246 fi 247 else 248 break 249 fi 250 done 251 } 252 253 # 254 ## -- entry point 255 # 256 257 [ -z "$1" ] && usage 'msmtpq requires an instruction' 258 259 check_queue # check that queue directory is present ... 260 OP=${1:1} # trim off first char of OP 261 case "$OP" in # sort ops ; run according to spec 262 r) run_queue ;; # run (flush) the queue 263 d) display_queue ;; # display (list) all mail in queue 264 p) purge_one_mail ;; # purge an individual mail from queue 265 a) purge_all_mail ;; # purge all mail in queue 266 h) usage ;; # show help 267 *) usage "[ $A ] is an unknown msmtpq option" ;; 268 esac 269 270 exit 0