Mercurial > p > roundup > code
annotate scripts/imapServer.py @ 8531:4fe0d14cf915
chore(build): bump actions/upload-artifact from 6.0.0 to 7.0.0. #84
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 10 Mar 2026 22:52:54 -0400 |
| parents | fed0f839c260 |
| children | 9c3ec0a5c7fc |
| rev | line source |
|---|---|
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
1 #!/usr/bin/env python3 |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
2 """\ |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
3 This script is a wrapper around the mailgw.py script that exists in roundup. |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
4 It runs as service instead of running as a one-time shot. |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
5 It also connects to a secure IMAP server. The main reasons for this script are: |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
6 |
| 3203 | 7 1) The roundup-mailgw script isn't designed to run as a server. It |
| 8 expects that you either run it by hand, and enter the password each | |
| 9 time, or you supply the password on the command line. I prefer to | |
| 10 run a server that I initialize with the password, and then it just | |
| 11 runs. I don't want to have to pass it on the command line, so | |
| 12 running through crontab isn't a possibility. (This wouldn't be a | |
| 13 problem on a local machine running through a mailspool.) | |
| 14 2) mailgw.py somehow screws up SSL support so IMAP4_SSL doesn't work. So | |
| 15 hopefully running that work outside of the mailgw will allow it to work. | |
| 16 3) I wanted to be able to check multiple projects at the same time. | |
| 17 roundup-mailgw is only for 1 mailbox and 1 project. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
18 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
19 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
20 *TODO*: |
| 3203 | 21 For the first round, the program spawns a new roundup-mailgw for |
| 22 each imap message that it finds and pipes the result in. In the | |
| 23 future it might be more practical to actually include the roundup | |
| 24 files and run the appropriate commands using python. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
25 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
26 *TODO*: |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
27 Look into supporting a logfile instead of using 2>/logfile |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
28 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
29 *TODO*: |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
30 Add an option for changing the uid/gid of the running process. |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
31 """ |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
32 |
|
5376
64b05e24dbd8
Python 3 preparation: convert print to a function.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5141
diff
changeset
|
33 from __future__ import print_function |
| 3203 | 34 import getpass |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
35 import logging |
| 3203 | 36 import imaplib |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
37 import argparse |
| 3203 | 38 import os |
| 39 import re | |
| 40 import time | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
41 import sys |
| 3203 | 42 |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
43 from roundup.anypy.my_input import my_input |
|
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
44 |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
45 logging.basicConfig() |
|
4421
67bef70ab9b9
- more logger fixes, sorry for the noise.
Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net>
parents:
3609
diff
changeset
|
46 log = logging.getLogger('roundup.IMAPServer') |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
47 |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
48 version = '0.1.3' |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
49 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
50 class RoundupMailbox: |
| 3203 | 51 """This contains all the info about each mailbox. |
| 52 Username, Password, server, security, roundup database | |
| 53 """ | |
| 54 def __init__(self, dbhome='', username=None, password=None, mailbox=None | |
| 55 , server=None, protocol='imaps'): | |
| 56 self.username = username | |
| 57 self.password = password | |
| 58 self.mailbox = mailbox | |
| 59 self.server = server | |
| 60 self.protocol = protocol | |
| 61 self.dbhome = dbhome | |
| 62 | |
| 63 try: | |
| 64 if not self.dbhome: | |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
65 self.dbhome = my_input('Tracker home: ') |
| 3203 | 66 if not os.path.exists(self.dbhome): |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
67 raise ValueError('Invalid home address: ' \ |
|
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
68 'directory "%s" does not exist.' % self.dbhome) |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
69 |
| 3203 | 70 if not self.server: |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
71 self.server = my_input('Server: ') |
| 3203 | 72 if not self.server: |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
73 raise ValueError('No Servername supplied') |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
74 protocol = my_input('protocol [imaps]? ') |
| 3203 | 75 self.protocol = protocol |
| 76 | |
| 77 if not self.username: | |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
78 self.username = my_input('Username: ') |
| 3203 | 79 if not self.username: |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
80 raise ValueError('Invalid Username') |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
81 |
| 3203 | 82 if not self.password: |
|
5376
64b05e24dbd8
Python 3 preparation: convert print to a function.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5141
diff
changeset
|
83 print('For server %s, user %s' % (self.server, self.username)) |
| 3203 | 84 self.password = getpass.getpass() |
| 85 # password can be empty because it could be superceeded | |
| 86 # by a later entry | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
87 |
| 3203 | 88 #if self.mailbox is None: |
|
5401
4cf48ff01e04
Python 3 preparation: replace raw_input uses.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5381
diff
changeset
|
89 # self.mailbox = my_input('Mailbox [INBOX]: ') |
| 3203 | 90 # # We allow an empty mailbox because that will |
| 91 # # select the INBOX, whatever it is called | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
92 |
| 3203 | 93 except (KeyboardInterrupt, EOFError): |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
94 raise ValueError('Canceled by User') |
| 3203 | 95 |
| 96 def __str__(self): | |
| 97 return 'Mailbox{ server:%(server)s, protocol:%(protocol)s, ' \ | |
| 98 'username:%(username)s, mailbox:%(mailbox)s, ' \ | |
| 99 'dbhome:%(dbhome)s }' % self.__dict__ | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
100 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
101 |
| 3203 | 102 # [als] class name is misleading. this is imap client, not imap server |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
103 class IMAPServer: |
| 3203 | 104 |
| 105 """IMAP mail gatherer. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
106 |
| 3203 | 107 This class runs as a server process. It is configured with a list of |
| 108 mailboxes to connect to, along with the roundup database directories | |
| 109 that correspond with each email address. It then connects to each | |
| 110 mailbox at a specified interval, and if there are new messages it | |
| 111 reads them, and sends the result to the roundup.mailgw. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
112 |
| 3203 | 113 *TODO*: |
| 114 Try to be smart about how you access the mailboxes so that you can | |
| 115 connect once, and access multiple mailboxes and possibly multiple | |
| 116 usernames. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
117 |
| 3203 | 118 *NOTE*: |
| 119 This assumes that if you are using the same user on the same | |
| 120 server, you are using the same password. (the last one supplied is | |
| 121 used.) Empty passwords are ignored. Only the last protocol | |
| 122 supplied is used. | |
| 123 """ | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
124 |
| 3203 | 125 def __init__(self, pidfile=None, delay=5, daemon=False): |
| 126 #This is sorted by servername, then username, then mailboxes | |
| 127 self.mailboxes = {} | |
| 128 self.delay = float(delay) | |
| 129 self.pidfile = pidfile | |
| 130 self.daemon = daemon | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
131 |
| 3203 | 132 def setDelay(self, delay): |
| 133 self.delay = delay | |
| 134 | |
| 135 def addMailbox(self, mailbox): | |
| 136 """ The linkage is as follows: | |
| 137 servers -- users - mailbox:dbhome | |
| 138 So there can be multiple servers, each with multiple users. | |
| 139 Each username can be associated with multiple mailboxes. | |
| 140 each mailbox is associated with 1 database home | |
| 141 """ | |
| 142 log.info('Adding mailbox %s', mailbox) | |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
143 if mailbox.server not in self.mailboxes: |
| 3203 | 144 self.mailboxes[mailbox.server] = {'protocol':'imaps', 'users':{}} |
| 145 server = self.mailboxes[mailbox.server] | |
| 146 if mailbox.protocol: | |
| 147 server['protocol'] = mailbox.protocol | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
148 |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
149 if mailbox.username not in server['users']: |
| 3203 | 150 server['users'][mailbox.username] = {'password':'', 'mailboxes':{}} |
| 151 user = server['users'][mailbox.username] | |
| 152 if mailbox.password: | |
| 153 user['password'] = mailbox.password | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
154 |
|
5381
0942fe89e82e
Python 3 preparation: change "x.has_key(y)" to "y in x".
Joseph Myers <jsm@polyomino.org.uk>
parents:
5378
diff
changeset
|
155 if mailbox.mailbox in user['mailboxes']: |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
156 raise ValueError('Mailbox is already defined') |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
157 |
| 3203 | 158 user['mailboxes'][mailbox.mailbox] = mailbox.dbhome |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
159 |
| 3203 | 160 def _process(self, message, dbhome): |
| 161 """Actually process one of the email messages""" | |
| 162 child = os.popen('roundup-mailgw %s' % dbhome, 'wb') | |
| 163 child.write(message) | |
| 164 child.close() | |
| 165 #print message | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
166 |
| 3203 | 167 def _getMessages(self, serv, count, dbhome): |
| 168 """This assumes that you currently have a mailbox open, and want to | |
| 169 process all messages that are inside. | |
| 170 """ | |
| 171 for n in range(1, count+1): | |
| 172 (t, data) = serv.fetch(n, '(RFC822)') | |
| 173 if t == 'OK': | |
| 174 self._process(data[0][1], dbhome) | |
| 175 serv.store(n, '+FLAGS', r'(\Deleted)') | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
176 |
| 3203 | 177 def checkBoxes(self): |
| 178 """This actually goes out and does all the checking. | |
| 179 Returns False if there were any errors, otherwise returns true. | |
| 180 """ | |
| 181 noErrors = True | |
| 182 for server in self.mailboxes: | |
| 183 log.info('Connecting to server: %s', server) | |
| 184 s_vals = self.mailboxes[server] | |
| 185 | |
| 186 try: | |
| 187 for user in s_vals['users']: | |
| 188 u_vals = s_vals['users'][user] | |
| 189 # TODO: As near as I can tell, you can only | |
| 190 # login with 1 username for each connection to a server. | |
| 191 protocol = s_vals['protocol'].lower() | |
| 192 if protocol == 'imaps': | |
| 193 serv = imaplib.IMAP4_SSL(server) | |
| 194 elif protocol == 'imap': | |
| 195 serv = imaplib.IMAP4(server) | |
| 196 else: | |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5376
diff
changeset
|
197 raise ValueError('Unknown protocol %s' % protocol) |
| 3203 | 198 |
| 199 password = u_vals['password'] | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
200 |
| 3203 | 201 try: |
| 202 log.info('Connecting as user: %s', user) | |
| 203 serv.login(user, password) | |
| 204 | |
| 205 for mbox in u_vals['mailboxes']: | |
| 206 dbhome = u_vals['mailboxes'][mbox] | |
| 207 log.info('Using mailbox: %s, home: %s', | |
| 208 mbox, dbhome) | |
| 209 #access a specific mailbox | |
| 210 if mbox: | |
| 211 (t, data) = serv.select(mbox) | |
| 212 else: | |
| 213 # Select the default mailbox (INBOX) | |
| 214 (t, data) = serv.select() | |
| 215 try: | |
| 216 nMessages = int(data[0]) | |
| 217 except ValueError: | |
| 218 nMessages = 0 | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
219 |
| 3203 | 220 log.info('Found %s messages', nMessages) |
| 221 | |
| 222 if nMessages: | |
| 223 self._getMessages(serv, nMessages, dbhome) | |
| 224 serv.expunge() | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
225 |
| 3203 | 226 # We are done with this mailbox |
| 227 serv.close() | |
|
8528
fed0f839c260
fix: replace except: with except Exception: (by haosenwang1018@github)
John Rouillard <rouilj@ieee.org>
parents:
7053
diff
changeset
|
228 except Exception: |
| 3203 | 229 log.exception('Exception with server %s user %s', |
| 230 server, user) | |
| 231 noErrors = False | |
| 232 | |
| 233 serv.logout() | |
| 234 serv.shutdown() | |
| 235 del serv | |
|
8528
fed0f839c260
fix: replace except: with except Exception: (by haosenwang1018@github)
John Rouillard <rouilj@ieee.org>
parents:
7053
diff
changeset
|
236 except Exception: |
| 3203 | 237 log.exception('Exception while connecting to %s', server) |
| 238 noErrors = False | |
| 239 return noErrors | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
240 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
241 |
| 3203 | 242 def makeDaemon(self): |
| 243 """Turn this process into a daemon. | |
| 244 | |
| 245 - make our parent PID 1 | |
| 246 | |
| 247 Write our new PID to the pidfile. | |
| 248 | |
| 249 From A.M. Kuuchling (possibly originally Greg Ward) with | |
| 250 modification from Oren Tirosh, and finally a small mod from me. | |
| 251 Originally taken from roundup.scripts.roundup_server.py | |
| 252 """ | |
| 253 log.info('Running as Daemon') | |
| 254 # Fork once | |
| 255 if os.fork() != 0: | |
| 256 os._exit(0) | |
| 257 | |
| 258 # Create new session | |
| 259 os.setsid() | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
260 |
| 3203 | 261 # Second fork to force PPID=1 |
| 262 pid = os.fork() | |
| 263 if pid: | |
| 264 if self.pidfile: | |
| 265 pidfile = open(self.pidfile, 'w') | |
| 266 pidfile.write(str(pid)) | |
| 267 pidfile.close() | |
| 268 os._exit(0) | |
| 269 | |
| 270 def run(self): | |
| 271 """Run email gathering daemon. | |
| 272 | |
| 273 This spawns itself as a daemon, and then runs continually, just | |
| 274 sleeping inbetween checks. It is recommended that you run | |
| 275 checkBoxes once first before you select run. That way you can | |
| 276 know if there were any failures. | |
| 277 """ | |
| 278 if self.daemon: | |
| 279 self.makeDaemon() | |
| 280 while True: | |
| 281 | |
| 282 time.sleep(self.delay * 60.0) | |
| 283 log.info('Time: %s', time.strftime('%Y-%m-%d %H:%M:%S')) | |
| 284 self.checkBoxes() | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
285 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
286 def getItems(s): |
| 3203 | 287 """Parse a string looking for userame@server""" |
| 288 myRE = re.compile( | |
| 289 r'((?P<protocol>[^:]+)://)?'#You can supply a protocol if you like | |
| 290 r'(' #The username part is optional | |
| 291 r'(?P<username>[^:]+)' #You can supply the password as | |
| 292 r'(:(?P<password>.+))?' #username:password@server | |
| 293 r'@)?' | |
| 294 r'(?P<server>[^/]+)' | |
| 295 r'(/(?P<mailbox>.+))?$' | |
| 296 ) | |
| 297 m = myRE.match(s) | |
| 298 if m: | |
| 299 return m.groupdict() | |
| 300 else: | |
| 301 return None | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
302 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
303 def main(): |
| 3203 | 304 """This is what is called if run at the prompt""" |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
305 parser = argparse.ArgumentParser( |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
306 formatter_class=argparse.RawDescriptionHelpFormatter, |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
307 epilog=""" |
| 3203 | 308 |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
309 The server takes pairs of home/server. |
| 3203 | 310 So each entry has a home, and then the server configuration. Home is just |
| 311 a path to the roundup issue tracker. The server is something of the form: | |
| 312 | |
| 313 imaps://user:password@server/mailbox | |
| 314 | |
| 315 If you don't supply the protocol, imaps is assumed. Without user or | |
| 316 password, you will be prompted for them. The server must be supplied. | |
| 317 Without mailbox the INBOX is used. | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
318 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
319 Examples: |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
320 %(prog)s /home/roundup/trackers/test imaps://test@imap.example.com/test |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
321 %(prog)s /home/roundup/trackers/test imap.example.com \\ |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
322 /home/roundup/trackers/test2 imap.example.com/test2 |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
323 """ % dict(prog = sys.argv [0]) |
| 3203 | 324 ) |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
325 parser.add_argument('args', nargs='*') |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
326 parser.add_argument('-d', '--delay', dest='delay', type=float, |
| 3203 | 327 metavar='<sec>', default=5, |
| 328 help="Set the delay between checks in minutes. (default 5)" | |
| 329 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
330 parser.add_argument('-p', '--pid-file', dest='pidfile', |
| 3203 | 331 metavar='<file>', default=None, |
| 332 help="The pid of the server process will be written to <file>" | |
| 333 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
334 parser.add_argument('-n', '--no-daemon', dest='daemon', |
| 3203 | 335 action='store_false', default=True, |
| 336 help="Do not fork into the background after running the first check." | |
| 337 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
338 parser.add_argument('--version', action="store_true", |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
339 help="Print version and exit") |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
340 parser.add_argument('-v', '--verbose', dest='verbose', |
| 3203 | 341 action='store_const', const=logging.INFO, |
| 342 help="Be more verbose in letting you know what is going on." | |
| 343 " Enables informational messages." | |
| 344 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
345 parser.add_argument('-V', '--very-verbose', dest='verbose', |
| 3203 | 346 action='store_const', const=logging.DEBUG, |
| 347 help="Be very verbose in letting you know what is going on." | |
| 348 " Enables debugging messages." | |
| 349 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
350 parser.add_argument('-q', '--quiet', dest='verbose', |
| 3203 | 351 action='store_const', const=logging.ERROR, |
| 352 help="Be less verbose. Ignores warnings, only prints errors." | |
| 353 ) | |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
354 parser.add_argument('-Q', '--very-quiet', dest='verbose', |
| 3203 | 355 action='store_const', const=logging.CRITICAL, |
| 356 help="Be much less verbose. Ignores warnings and errors." | |
| 357 " Only print CRITICAL messages." | |
| 358 ) | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
359 |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
360 args = parser.parse_args() |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
361 if args.version: |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
362 print('%s %s' % (sys.argv [0], version)) |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
363 sys.exit(0) |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
364 if not len(args.args) or len(args.args) % 2 == 1: |
| 3203 | 365 parser.error('Invalid number of arguments. ' |
| 366 'Each site needs a home and a server.') | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
367 |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
368 if args.verbose == None: |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
369 args.verbose = logging.WARNING |
|
5141
939dce88cfc2
issue2550776: fix missing intialization
John Rouillard <rouilj@ieee.org>
parents:
4421
diff
changeset
|
370 |
|
7053
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
371 log.setLevel(args.verbose) |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
372 myServer = IMAPServer(delay=args.delay, pidfile=args.pidfile, |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
373 daemon=args.daemon) |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
374 for i in range(0,len(args.args),2): |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
375 home = args.args[i] |
|
b5fffd2a64af
issue2551195: port scripts to argparse
Ralf Schlatterbeck <rsc@runtux.com>
parents:
5401
diff
changeset
|
376 server = args.args[i+1] |
| 3203 | 377 if not os.path.exists(home): |
| 378 parser.error('Home: "%s" does not exist' % home) | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
379 |
| 3203 | 380 info = getItems(server) |
| 381 if not info: | |
| 382 parser.error('Invalid server string: "%s"' % server) | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
383 |
| 3203 | 384 myServer.addMailbox( |
| 385 RoundupMailbox(dbhome=home, mailbox=info['mailbox'] | |
| 386 , username=info['username'], password=info['password'] | |
| 387 , server=info['server'], protocol=info['protocol'] | |
| 388 ) | |
| 389 ) | |
| 390 | |
| 391 if myServer.checkBoxes(): | |
| 392 myServer.run() | |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
393 |
|
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
394 if __name__ == '__main__': |
| 3203 | 395 main() |
|
3176
18ad9d702a5b
added "imapServer.py" script (patch [SF#934567])
Richard Jones <richard@users.sourceforge.net>
parents:
diff
changeset
|
396 |
| 3203 | 397 # vim: et ft=python si sts=4 sw=4 |
