root / pykota / trunk / bin / pkmail @ 3295

Revision 3295, 6.3 kB (checked in by jerome, 16 years ago)

Made the CGI scripts work again.
Moved even more functions to the utils module.
Removed the cgifuncs module, moved (and changed) content into utils.
If no output encoding defined, use UTF-8 : when wget is used to try
the CGI scripts, it doesn't set by default the accepted charset and
language headers.

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