root / pykota / trunk / bin / pkmail @ 2512

Revision 2512, 6.0 kB (checked in by jerome, 19 years ago)

Ensure that human made errors (like incorrect command line options)
don't produce a traceback anymore. No need to frighten users with
such complete tracebacks and email reporting each time they mistype
some command.
Makes pykosd check more carefully the values of its command line options.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[1952]1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# An email gateway for PyKota
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
[2028]8# (c) 2003, 2004, 2005 Jerome Alet <alet@librelogiciel.com>
[1952]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 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
[2303]21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
[1952]22#
23# $Id$
24#
[2091]25#
[1952]26
27import sys
28import os
29import popen2
30import smtplib
31import email
32
[2512]33from pykota.tool import PyKotaTool, PyKotaToolError, PyKotaCommandLineError, crashed, N_
[2352]34   
[2344]35__doc__ = N_("""pkmail v%(__version__)s (c) %(__years__)s %(__author__)s
[1952]36
37Email gateway for PyKota.
38
39command line usage :
40
41  pkmail  [options]
42
43options :
44
45  -v | --version       Prints pkmail's version number then exits.
46  -h | --help          Prints this message then exits.
47 
48   
49  This command is meant to be used from your mail server's aliases file,
50  as a pipe. It will then accept commands send to it in email messages,
51  and will send the answer to the command's originator.
52 
53  To use this command, create an email alias in /etc/aliases with
54  the following format :
55 
56    pykotacmd: "|/usr/bin/pkmail"
57   
58  Then run the 'newaliases' command to regenerate the aliases database.
59 
60  You can now send commands by email to 'pykotacmd@yourdomain.com', with
61  the command in the subject.
62 
63  List of supported commands :
64 
65        report [username]
66 
67  NB : For pkmail to work correctly, you may have to put the 'mail'
[2091]68  system user in the 'pykota' system group to ensure this user can
[1952]69  read the /etc/pykota/pykotadmin.conf file, and restart your
70  mail server (e.g. /etc/init.d/exim restart). It is strongly advised
71  that you think at least twice before doing this though.
72 
73  Use at your own risk !
[2344]74""")
[1952]75       
76       
77class PKMail(PyKotaTool) :       
78    """A class for pkmail."""
79    def main(self, files, options) :
80        """Accepts commands passed in an email message."""
81        data = sys.stdin.read()
82        message = email.message_from_string(data)
83        useremail = message["From"]
84        whoami = message["To"]
85        cmdargs = message["Subject"].split()
86        try :
87            (command, arguments) = (cmdargs[0].capitalize(), cmdargs[1:])
88        except IndexError :   
[2512]89            raise PyKotaCommandLineError, "No command found !"
[1952]90       
[1953]91        badchars = """/<>&"'#!%*$,;\\"""
92        cheatmeonce = 0
93        for c in "".join(arguments) :
94            if c in badchars :
95                cheatmeonce = 1
96           
97        if cheatmeonce :   
98            self.logdebug("Possible intruder at %s : %s" % (useremail, str(arguments)))
99            result = "Either you mistyped your command, or you're a bad guy !"
100        else :
101            self.logdebug("Launching internal command '%s' with arguments %s" % (command, str(arguments)))
102            cmdfunc = getattr(self, "cmd%s" % command, self.cmdDefault)
103            result = cmdfunc(arguments)
[1952]104       
105        self.logdebug("Sending answer to : %s" % useremail)
106        server = smtplib.SMTP(self.smtpserver)
107        server.sendmail(whoami, [ useremail ], "From: %s\nTo: %s\nSubject: Result of your commands\n\n%s\n" % (whoami, useremail, result))
108        server.quit()
109        self.logdebug("Answer sent to : %s" % useremail)
110       
111        return 0
112       
113    def runCommand(self, cmd) :   
114        """Executes a command."""
115        self.logdebug("Launching : '%s'" % cmd)
116        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
117        child = popen2.Popen3(cmd)
118        child.tochild.close()
119        result = child.fromchild.read()
120        status = child.wait()
121        if os.WIFEXITED(status) :
122            status = os.WEXITSTATUS(status)
123        self.logdebug("'%s' exited with status %s" % (cmd, status))
124        return result
125       
126    def cmdDefault(self, arguments) :   
127        """Default command : sends an 'unknown command' message."""
128        return "Unknown command."
129       
130    def cmdReport(self, args) :   
131        """Generates a print quota report."""
132        return self.runCommand("repykota %s" % ' '.join([ '"%s"' % a for a in args ]))
133           
134if __name__ == "__main__" : 
135    retcode = 0
136    try :
137        defaults = { \
138                   }
139        short_options = "vh"
140        long_options = ["help", "version"]
141       
142        # Initializes the command line tool
143        mailparser = PKMail(doc=__doc__)
[2210]144        mailparser.deferredInit()
[1952]145       
146        # parse and checks the command line
147        (options, args) = mailparser.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
148       
149        # sets long options
150        options["help"] = options["h"] or options["help"]
151        options["version"] = options["v"] or options["version"]
152       
153        if options["help"] :
154            mailparser.display_usage_and_quit()
155        elif options["version"] :
156            mailparser.display_version_and_quit()
157        else :
158            retcode = mailparser.main(args, options)
[2216]159    except KeyboardInterrupt :       
160        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
[2512]161    except PyKotaCommandLineError, msg :   
162        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
[1952]163    except SystemExit :       
164        pass
165    except :
166        try :
167            mailparser.crashed("pkmail failed")
168        except :   
169            crashed("pkmail failed")
170        retcode = -1
171
172    try :
173        mailparser.storage.close()
174    except (TypeError, NameError, AttributeError) :   
175        pass
176       
177    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.