root / pykota / trunk / bin / pkmail @ 2060

Revision 2028, 6.8 kB (checked in by jalet, 20 years ago)

Modified copyright years

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