root / pykota / trunk / bin / pkmail @ 3290

Revision 3288, 6.2 kB (checked in by jerome, 16 years ago)

Moved all exceptions definitions to a dedicated module.

  • 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
33from pykota.errors import PyKotaCommandLineError
34from pykota.tool import PyKotaTool, crashed, N_
35   
36__doc__ = N_("""pkmail v%(__version__)s (c) %(__years__)s %(__author__)s
37
38Email gateway for PyKota.
39
40command line usage :
41
42  pkmail  [options]
43
44options :
45
46  -v | --version       Prints pkmail's version number then exits.
47  -h | --help          Prints this message then exits.
48 
49   
50  This command is meant to be used from your mail server's aliases file,
51  as a pipe. It will then accept commands send to it in email messages,
52  and will send the answer to the command's originator.
53 
54  To use this command, create an email alias in /etc/aliases with
55  the following format :
56 
57    pykotacmd: "|/usr/bin/pkmail"
58   
59  Then run the 'newaliases' command to regenerate the aliases database.
60 
61  You can now send commands by email to 'pykotacmd@yourdomain.com', with
62  the command in the subject.
63 
64  List of supported commands :
65 
66        report [username]
67 
68  NB : For pkmail to work correctly, you may have to put the 'mail'
69  system user in the 'pykota' system group to ensure this user can
70  read the /etc/pykota/pykotadmin.conf file, and restart your
71  mail server (e.g. /etc/init.d/exim restart). It is strongly advised
72  that you think at least twice before doing this though.
73 
74  Use at your own risk !
75""")
76       
77       
78class PKMail(PyKotaTool) :       
79    """A class for pkmail."""
80    def main(self, files, options) :
81        """Accepts commands passed in an email message."""
82        data = sys.stdin.read()
83        message = email.message_from_string(data)
84        useremail = message["From"]
85        whoami = message["To"]
86        cmdargs = message["Subject"].split()
87        try :
88            (command, arguments) = (cmdargs[0].capitalize(), cmdargs[1:])
89        except IndexError :   
90            raise PyKotaCommandLineError, "No command found !"
91       
92        badchars = """/<>&"'#!%*$,;\\"""
93        cheatmeonce = 0
94        for c in "".join(arguments) :
95            if c in badchars :
96                cheatmeonce = 1
97           
98        if cheatmeonce :   
99            self.printInfo("Possible intruder at %s : %s" % (useremail, str(arguments)), "warn")
100            result = "Either you mistyped your command, or you're a bad guy !"
101        else :
102            self.logdebug("Launching internal command '%s' with arguments %s" % (command, str(arguments)))
103            cmdfunc = getattr(self, "cmd%s" % command, self.cmdDefault)
104            result = cmdfunc(arguments)
105       
106        self.logdebug("Sending answer to : %s" % useremail)
107        emailmsg = MIMEText(result, _charset=self.charset)
108        emailmsg["Subject"] = Header(_("Result of your commands"), charset=self.charset)
109        emailmsg["From"] = whoami
110        emailmsg["To"] = useremail
111        emailmsg["Date"] = email.Utils.formatdate(localtime=True)
112        server = smtplib.SMTP(self.smtpserver)
113        server.sendmail(whoami, [ useremail ], emailmsg.as_string())
114        server.quit()
115        self.logdebug("Answer sent to : %s" % useremail)
116       
117        return 0
118       
119    def runCommand(self, cmd) :   
120        """Executes a command."""
121        self.logdebug("Launching : '%s'" % cmd)
122        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
123        child = popen2.Popen3(cmd)
124        child.tochild.close()
125        result = child.fromchild.read()
126        status = child.wait()
127        if os.WIFEXITED(status) :
128            status = os.WEXITSTATUS(status)
129        self.logdebug("'%s' exited with status %s" % (cmd, status))
130        return result
131       
132    def cmdDefault(self, arguments) :   
133        """Default command : sends an 'unknown command' message."""
134        return "Unknown command."
135       
136    def cmdReport(self, args) :   
137        """Generates a print quota report."""
138        return self.runCommand("repykota %s" % ' '.join([ '"%s"' % a for a in args ]))
139           
140if __name__ == "__main__" : 
141    retcode = 0
142    try :
143        defaults = { \
144                   }
145        short_options = "vh"
146        long_options = ["help", "version"]
147       
148        # Initializes the command line tool
149        mailparser = PKMail(doc=__doc__)
150        mailparser.deferredInit()
151       
152        # parse and checks the command line
153        (options, args) = mailparser.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
154       
155        # sets long options
156        options["help"] = options["h"] or options["help"]
157        options["version"] = options["v"] or options["version"]
158       
159        if options["help"] :
160            mailparser.display_usage_and_quit()
161        elif options["version"] :
162            mailparser.display_version_and_quit()
163        else :
164            retcode = mailparser.main(args, options)
165    except KeyboardInterrupt :       
166        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
167        retcode = -3
168    except PyKotaCommandLineError, msg :   
169        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
170        retcode = -2
171    except SystemExit :       
172        pass
173    except :
174        try :
175            mailparser.crashed("pkmail failed")
176        except :   
177            crashed("pkmail failed")
178        retcode = -1
179
180    try :
181        mailparser.storage.close()
182    except (TypeError, NameError, AttributeError) :   
183        pass
184       
185    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.