root / pykota / trunk / bin / pkmail @ 3260

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

Changed license to GNU GPL v3 or later.
Changed Python source encoding from ISO-8859-15 to UTF-8 (only ASCII
was used anyway).

  • 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 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.tool import PyKotaTool, PyKotaCommandLineError, crashed, N_
34   
35__doc__ = N_("""pkmail v%(__version__)s (c) %(__years__)s %(__author__)s
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'
68  system user in the 'pykota' system group to ensure this user can
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 !
74""")
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 :   
89            raise PyKotaCommandLineError, "No command found !"
90       
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.printInfo("Possible intruder at %s : %s" % (useremail, str(arguments)), "warn")
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)
104       
105        self.logdebug("Sending answer to : %s" % useremail)
106        emailmsg = MIMEText(result, _charset=self.charset)
107        emailmsg["Subject"] = Header(_("Result of your commands"), charset=self.charset)
108        emailmsg["From"] = whoami
109        emailmsg["To"] = useremail
110        emailmsg["Date"] = email.Utils.formatdate(localtime=True)
111        server = smtplib.SMTP(self.smtpserver)
112        server.sendmail(whoami, [ useremail ], emailmsg.as_string())
113        server.quit()
114        self.logdebug("Answer sent to : %s" % useremail)
115       
116        return 0
117       
118    def runCommand(self, cmd) :   
119        """Executes a command."""
120        self.logdebug("Launching : '%s'" % cmd)
121        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
122        child = popen2.Popen3(cmd)
123        child.tochild.close()
124        result = child.fromchild.read()
125        status = child.wait()
126        if os.WIFEXITED(status) :
127            status = os.WEXITSTATUS(status)
128        self.logdebug("'%s' exited with status %s" % (cmd, status))
129        return result
130       
131    def cmdDefault(self, arguments) :   
132        """Default command : sends an 'unknown command' message."""
133        return "Unknown command."
134       
135    def cmdReport(self, args) :   
136        """Generates a print quota report."""
137        return self.runCommand("repykota %s" % ' '.join([ '"%s"' % a for a in args ]))
138           
139if __name__ == "__main__" : 
140    retcode = 0
141    try :
142        defaults = { \
143                   }
144        short_options = "vh"
145        long_options = ["help", "version"]
146       
147        # Initializes the command line tool
148        mailparser = PKMail(doc=__doc__)
149        mailparser.deferredInit()
150       
151        # parse and checks the command line
152        (options, args) = mailparser.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
153       
154        # sets long options
155        options["help"] = options["h"] or options["help"]
156        options["version"] = options["v"] or options["version"]
157       
158        if options["help"] :
159            mailparser.display_usage_and_quit()
160        elif options["version"] :
161            mailparser.display_version_and_quit()
162        else :
163            retcode = mailparser.main(args, options)
164    except KeyboardInterrupt :       
165        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
166        retcode = -3
167    except PyKotaCommandLineError, msg :   
168        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
169        retcode = -2
170    except SystemExit :       
171        pass
172    except :
173        try :
174            mailparser.crashed("pkmail failed")
175        except :   
176            crashed("pkmail failed")
177        retcode = -1
178
179    try :
180        mailparser.storage.close()
181    except (TypeError, NameError, AttributeError) :   
182        pass
183       
184    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.