hi everyone however they didn't work for me! strangely they added every mail to the queue directory...
and i got this output all over my logfiles when sending through msmtpQ (symlinked to sendmail): -------------------- /usr/sbin/sendmail: 39: declare: not found [: 170: Illegal number: == local: 184: -i: bad variable name PING 64.233.183.147 (64.233.183.147) 56(84) bytes of data. --- 64.233.183.147 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 35.872/35.872/35.872/0.000 ms [: 184: ==: unexpected operator [: 184: ==: unexpected operator local: 184: -i: bad variable name [: 184: ==: unexpected operator [: 184: -e: unexpected operator -------------------- this might be specific because i am using the script with the version shipped with ubuntu 8.04 LTS... thanks for writing the msmtpq scripts anyway :-) since i have no clue of shell scripting i was unable to fix this script and because i need one to work now with the msmtp version shipped with ubuntu 8.04 i wrote a new one in python that works almost in the same way as the shell scripts included in mstmp. mostly i combined everything into one script and when unable to send a mail it automatically forks of as a daemon, trying to flush the queue each minute. when the queue is empty the daemon will quit (which is very nice if you have network outages of a few minutes once a week). like the included scripts it determines a live internet connection through pinging google, although i've changed it to pinging smtp.google.com... well anyway i just thought it might be useful to someone. claude nobs ------------------- #!/usr/bin/env python # -*- coding: utf8 -*- """ msmtp-queue <http:/mq.blunet.cc/> Copyright (C) 2008 Claude Nobs Based on scripts from Martin Lambers & Chris Gianniotis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. For more details, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html """ import sys, os, time, pwd, signal, re def _usage() : print "Usage: %s [COMMAND]|[MSMTP-ARGS]" % sys.argv[0] print "\nCommands:" print " --version show version number" print " --help show this help message" print " daemon run the queue daemon" print " display display (list) queue state" print " remove remove a single mail from the queue" print " purge purge all mail from the queue" print "\nNote that only one command is allowed! msmtpq does not use the -h option in\norder to be transparent to msmtp/sendmail." print "\nIf you want to send an email just work as you would with msmtp (don't specify\nany of the above commands), but note that if there is no internet connection\nany mstmp command gets enqueued (even wrong ones)!" print "\nIf you want to do anything else than sending a mail, use msmtp/sendmail directly!" print "\nNOTE: You should add 'msmtpq daemon' to /etc/rc.local (or by other means\nconfigure your system to run the msmtpq daemon on startup) in case there is mail\nin the queue and the system crashes/is rebooted." def log(string) : sys.stdout.write(time.strftime("%Y-%m-%d--%H-%M",time.localtime()) + ' ' + string + '\n') sys.stdout.flush() def enqueue_mail(mail) : queueitem = os.path.join(queuedir,time.strftime("%Y-%m-%d--%H-%M-%S",time.localtime())) if os.path.exists(queueitem) : f = open(logpath,"a+") f.write("ERROR : queue item %s already exists! appending mail here:\n%s\n%s\n" % (queueitem,sys.argv,mail)) f.close() sys.exit(os.EX_IOERR) else : try: f = open(queueitem,'w') f.write(" ".join(sys.argv)+"\n") f.write(mail) f.close() print "SUCCESS : queued mail as %s" % queueitem # get to be server if it isn't already running # FIXME if not already_running(title) : # this is nearly save because daemons last action is to evaluate listdir > 0 daemon() # we might wait a second before looking if daemon is there to make it really safe except (IOError,os.error), e : f = open(logpath,"a+") f.write("ERROR : failed to queue item %s! appending mail here:\n%s\n%s\n" % (queueitem,sys.argv,mail)) f.close() ####################################################################### COMMON LIBRARY FUNCTIONS ### def set_process_title(title): import ctypes libc = ctypes.CDLL('libc.so.6') libc.prctl(15,title,0,0,0) # FreeBSD : libc.setproctitle('rsyncbackup') def already_running(title,uid=None,gid=None): """ check if the process with the given title already exists. if it does, return a tuple of [[PID,UID,GID,CMD]...] else return [] on error return False """ import os, subprocess try : p = subprocess.Popen(['ps','-C',title,'--no-headers','-o',",".join(['pid','uid','gid','cmd'])], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = [each.split(None,3) for each in p.stdout.read().strip().split("\n")] if p.wait() != 0: if output != [[]]: print "WARNING : ps execution returned unexpected result! : %s" % str(output) return False return [] else: if uid != None : return [each for each in output if int(each[1]) == uid] elif gid != None : return [each for each in output if int(each[2]) == uid] else : return output except OSError, e : print "ERROR : could not execute ps! ",e return False def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): ''' This forks the current process into a daemon. The stdin, stdout, and stderr arguments are file names that will be opened and be used to replace the standard file descriptors in sys.stdin, sys.stdout, and sys.stderr. These arguments are optional and default to /dev/null. Note that stderr is opened unbuffered, so if it shares a file with stdout then interleaved output may not appear in the order that you expect. ''' # Do first fork. try: pid = os.fork() if pid > 0: sys.exit(0) # Exit first parent. except OSError, e: sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) ) sys.exit(1) # Decouple from parent environment. os.chdir("/") os.umask(0) os.setsid() # Do second fork. try: pid = os.fork() if pid > 0: sys.exit(0) # Exit second parent. except OSError, e: sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) ) sys.exit(1) # Now I am a daemon! # Redirect standard file descriptors. si = open(stdin, 'r') so = open(stdout, 'a+') se = open(stderr, 'a+', 0) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) ################################################################################# MODE FUNCTIONS ### def version() : print "%s v.1.0 beta" % sys.argv[0] sys.exit(os.EX_OK) def usage() : _usage() sys.exit(os.EX_OK) def daemon() : set_process_title(title) daemonize('/dev/null',logpath,logpath) log('%s started as a Daemon with pid %d' % (__file__, os.getpid())) while len(os.listdir(queuedir)) > 0 : time.sleep(60) ping = os.popen('ping -qnc 1 209.85.135.111') #we use mx.google.com but you could use just google.com : 64.233.183.147 if ping.close() == None : # notify sysadmin that there was an outage try: p = os.popen('msmtp %s' % sysemail,'w') p.write("Subject: NOTE : there was an email outage!") p.close() except : log("ERROR : could not inform sysadmin of outage!") # process the queue for each in os.listdir(queuedir) : try : f = open(os.path.join(queuedir,each),'r') p = os.popen(f.readline().strip(),'w') p.write(f.read()) f.close() if p.close() : log("ERROR : could not send %s from queue." % each) else : log("SUCCESS : sent %s from queue." % each) try : os.remove(os.path.join(queuedir,each)) except (IOError,os.error), e : log("ERROR : could not remove %s from queue." % each) except (IOError,os.error), e : log("ERROR : could not send %s from queue." % each) def display() : if len(os.listdir(queuedir)) > 0 : for each in os.listdir(queuedir) : try : f = open (os.path.join(queuedir,each),'r') info = re.findall('^(msmtp(\s+-[^\s])|To:|Cc:|Bcc:)([EMAIL PROTECTED])+\s*$|^Subject:(.+)$',f.read(), re.I | re.M) f.close() print "%s %s | %s" % (each," ".join([ i[2].strip() for i in info if i[0] != '' ])," ".join([ i[3].strip() for i in info if i[0] == '' ])) except (IOError,os.error), e : print "ERROR : could not open %s!" % each if not already_running(title) : print "msmtpq daemon was not running! spawning daemon now..." daemon() else : print "queue is empty" def remove() : if len(sys.argv) < 3 : print "you must specify an item to remove! item id is of format : %Y-%m-%d--%H-%M-%S" sys.exit(os.EX_USAGE) if len(os.listdir(queuedir)) > 0 : if os.path.isfile(os.path.join(queuedir,sys.argv[2])) : try: os.remove(os.path.join(queuedir,sys.argv[2])) print "removed %s from queue." % sys.argv[2] except (IOError,os.error), e : print "ERROR : could not remove %s!" % sys.argv[2] else : print "ERROR : %s is not in queue!" % sys.argv[2] else : print "ERROR : queue is empty" def purge() : if raw_input("Will delete all mails in queue! Type 'yes' to confirm: ") == 'yes' : if len(os.listdir(queuedir)) > 0 : for each in os.listdir(queuedir) : try: os.remove(os.path.join(queuedir,each)) print "removed %s from queue." % each except (IOError,os.error), e : print "ERROR : could not remove %s!" % each else : print "ERROR : queue is empty" else : print "leaving queue untouched..." def send_mail(mail='') : while True: s = sys.stdin.read(1) mail += s if not s: break ping = os.popen('ping -qnc 1 209.85.135.111') #we use mx.google.com but you could use just google.com : 64.233.183.147 if ping.close() == None : try : p = os.popen(" ".join(sys.argv),'w') except (IOError,os.error), e : print "WARNING : error executing '%s'! trying to enqueue mail..." % " ".join(sys.argv) enqueue_mail(mail) p.write(mail) if p.close() : print "WARNING : sending email was unsuccessful! trying to enqueue mail..." enqueue_mail(mail) else : print "WARNING : no route to the internet! trying to enqueue mail..." enqueue_mail(mail) ########################################################################################### MAIN ### if __name__ == "__main__": """ set global variables parse commandline select mode function """ # set global variables title = 'msmtpq' sys.argv[0] = 'msmtp' # so we can use sys.argv as if the user had called msmtp directly logpath = os.path.join(os.path.expanduser('/var/log/'),'msmtpq.log') queuedir = os.path.join(os.path.expanduser('/var/tmp/'),'msmtp.queue') sysemail = '[EMAIL PROTECTED]' # msmtp and we need at least one argument if len(sys.argv) < 2 : usage() sys.exit(os.EX_USAGE) # these commands must work even if the queue is missing if sys.argv[1] =='--version': version() if sys.argv[1] =='--help' : usage() # check if queue dir exists (or can be created) if not os.path.isdir(queuedir) : try : os.makedirs(queuedir) except (IOError,os.error), e : print "ERROR : can't create queue dir : %s" % queuedir sys.exit(os.EX_IOERR) elif not os.access(queuedir,os.W_OK) : print "ERROR : can't write to queue dir : %s" % queuedir sys.exit(os.EX_IOERR) # ready to run ! if sys.argv[1] in ('daemon','display','remove','purge') : eval(sys.argv[1]+'()') else : send_mail() sys.exit(os.EX_OK) ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ msmtp-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/msmtp-users
