root / pykota / trunk / bin / pkmail @ 3013

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

Killed another item from the TODO list

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