Changeset 359
- Timestamp:
- 05/19/10 15:30:25 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/email2trac.py.in
r356 r359 113 113 env = None 114 114 comment = '> ' 115 115 116 116 def __init__(self, env, parameters, version): 117 117 self.env = env … … 284 284 285 285 self.trac_smtp_from = self.get_config('notification', 'smtp_from') 286 287 self.system = None 286 288 287 289 ########## Email Header Functions ########################################################### … … 611 613 Transfrom a string of the form [<key>=<value>]+ to dict[<key>] = <value> 612 614 """ 615 if self.VERBOSE: 616 print "VB: str_to_dict" 613 617 614 618 fields = string.split(s, self.SUBJECT_FIELD_SEPARATOR) … … 1103 1107 # 1104 1108 fd = open(path, 'rb') 1105 att = attachment.Attachment(self.env, 'ticket', self.id) 1106 1109 if self.system == 'discussion': 1110 att = attachment.Attachment(self.env, 'discussion', 'topic/%s' 1111 % (self.id,)) 1112 else: 1113 att = attachment.Attachment(self.env, 'ticket', self.id) 1114 1107 1115 # This will break the ticket_update system, the body_text is vaporized 1108 1116 # ;-( … … 1126 1134 return status 1127 1135 1128 ########## Fullblog functions ################################################# ##########1136 ########## Fullblog functions ################################################# 1129 1137 1130 1138 def blog(self, id): … … 1171 1179 1172 1180 1173 1174 ########## MAIN function ########################################################### 1181 ########## Discussion functions ############################################## 1182 1183 def discussion_topic(self, content, subject): 1184 1185 # Import modules. 1186 from tracdiscussion.api import DiscussionApi 1187 from trac.util.datefmt import to_timestamp, utc 1188 1189 if self.DEBUG: 1190 print 'TD: Creating a new topic in forum:', self.id 1191 1192 # Get dissussion API component. 1193 api = self.env[DiscussionApi] 1194 context = self._create_context(content, subject) 1195 1196 # Get forum for new topic. 1197 forum = api.get_forum(context, self.id) 1198 1199 if not forum and self.DEBUG: 1200 print 'ERROR: Replied forum doesn\'t exist' 1201 1202 # Prepare topic. 1203 topic = {'forum' : forum['id'], 1204 'subject' : context.subject, 1205 'time': to_timestamp(datetime.now(utc)), 1206 'author' : self.author, 1207 'subscribers' : [self.email_addr], 1208 'body' : self.body_text(context.content_parts)} 1209 1210 # Add topic to DB and commit it. 1211 self._add_topic(api, context, topic) 1212 self.db.commit() 1213 1214 def discussion_topic_reply(self, content, subject): 1215 1216 # Import modules. 1217 from tracdiscussion.api import DiscussionApi 1218 from trac.util.datefmt import to_timestamp, utc 1219 1220 if self.DEBUG: 1221 print 'TD: Replying to discussion topic', self.id 1222 1223 # Get dissussion API component. 1224 api = self.env[DiscussionApi] 1225 context = self._create_context(content, subject) 1226 1227 # Get replied topic. 1228 topic = api.get_topic(context, self.id) 1229 1230 if not topic and self.DEBUG: 1231 print 'ERROR: Replied topic doesn\'t exist' 1232 1233 # Prepare message. 1234 message = {'forum' : topic['forum'], 1235 'topic' : topic['id'], 1236 'replyto' : -1, 1237 'time' : to_timestamp(datetime.now(utc)), 1238 'author' : self.author, 1239 'body' : self.body_text(context.content_parts)} 1240 1241 # Add message to DB and commit it. 1242 self._add_message(api, context, message) 1243 self.db.commit() 1244 1245 def discussion_message_reply(self, content, subject): 1246 1247 # Import modules. 1248 from tracdiscussion.api import DiscussionApi 1249 from trac.util.datefmt import to_timestamp, utc 1250 1251 if self.DEBUG: 1252 print 'TD: Replying to discussion message', self.id 1253 1254 # Get dissussion API component. 1255 api = self.env[DiscussionApi] 1256 context = self._create_context(content, subject) 1257 1258 # Get replied message. 1259 message = api.get_message(context, self.id) 1260 1261 if not message and self.DEBUG: 1262 print 'ERROR: Replied message doesn\'t exist' 1263 1264 # Prepare message. 1265 message = {'forum' : message['forum'], 1266 'topic' : message['topic'], 1267 'replyto' : message['id'], 1268 'time' : to_timestamp(datetime.now(utc)), 1269 'author' : self.author, 1270 'body' : self.body_text(context.content_parts)} 1271 1272 # Add message to DB and commit it. 1273 self._add_message(api, context, message) 1274 self.db.commit() 1275 1276 def _create_context(self, content, subject): 1277 1278 # Import modules. 1279 from trac.mimeview import Context 1280 from trac.web.api import Request 1281 from trac.perm import PermissionCache 1282 1283 # TODO: Read server base URL from config. 1284 # Create request object to mockup context creation. 1285 # 1286 environ = {'SERVER_PORT' : 80, 1287 'SERVER_NAME' : 'test', 1288 'REQUEST_METHOD' : 'POST', 1289 'wsgi.url_scheme' : 'http', 1290 'wsgi.input' : sys.stdin} 1291 chrome = {'links': {}, 1292 'scripts': [], 1293 'ctxtnav': [], 1294 'warnings': [], 1295 'notices': []} 1296 1297 if self.env.base_url_for_redirect: 1298 environ['trac.base_url'] = self.env.base_url 1299 1300 req = Request(environ, None) 1301 req.chrome = chrome 1302 req.tz = 'missing' 1303 req.authname = self.author 1304 req.perm = PermissionCache(self.env, self.author) 1305 1306 # Create and return context. 1307 context = Context.from_request(req) 1308 context.realm = 'discussion-email2trac' 1309 context.cursor = self.db.cursor() 1310 context.content = content 1311 context.subject = subject 1312 1313 # Read content parts from content. 1314 context.content_parts = self.get_message_parts(content) 1315 context.content_parts = self.unique_attachment_names( 1316 context.content_parts) 1317 1318 return context 1319 1320 def _add_topic(self, api, context, topic): 1321 context.req.perm.assert_permission('DISCUSSION_APPEND') 1322 1323 # Filter topic. 1324 for discussion_filter in api.discussion_filters: 1325 accept, topic_or_error = discussion_filter.filter_topic( 1326 context, topic) 1327 if accept: 1328 topic = topic_or_error 1329 else: 1330 raise TracError(topic_or_error) 1331 1332 # Add a new topic. 1333 api.add_topic(context, topic) 1334 1335 # Get inserted topic with new ID. 1336 topic = api.get_topic_by_time(context, topic['time']) 1337 1338 # Attach attachments. 1339 self.id = topic['id'] 1340 self.attach_attachments(context.content_parts, self.VERSION == 0.9) 1341 1342 # Notify change listeners. 1343 for listener in api.topic_change_listeners: 1344 listener.topic_created(context, topic) 1345 1346 def _add_message(self, api, context, message): 1347 context.req.perm.assert_permission('DISCUSSION_APPEND') 1348 1349 # Filter message. 1350 for discussion_filter in api.discussion_filters: 1351 accept, message_or_error = discussion_filter.filter_message( 1352 context, message) 1353 if accept: 1354 message = message_or_error 1355 else: 1356 raise TracError(message_or_error) 1357 1358 # Add message. 1359 api.add_message(context, message) 1360 1361 # Get inserted message with new ID. 1362 message = api.get_message_by_time(context, message['time']) 1363 1364 # Attach attachments. 1365 self.id = message['topic'] 1366 self.attach_attachments(context.content_parts, self.VERSION == 0.9) 1367 1368 # Notify change listeners. 1369 for listener in api.message_change_listeners: 1370 listener.message_created(context, message) 1371 1372 ########## MAIN function ###################################################### 1175 1373 1176 1374 def parse(self, fp): … … 1230 1428 self.notification = 0 1231 1429 1232 1430 if not m['Subject']: 1431 subject = 'No Subject' 1432 else: 1433 subject = self.email_to_unicode(m['Subject']) 1434 1435 if self.DEBUG: 1436 print "TD:", subject 1437 1438 # 1439 # [hic] #1529: Re: LRZ 1440 # [hic] #1529?owner=bas,priority=medium: Re: LRZ 1441 # 1442 ticket_regex = r''' 1443 (?P<new_fields>[#][?].*) 1444 |(?P<reply>(?P<id>[#][\d]+)(?P<fields>\?.*?:)*) 1445 ''' 1233 1446 # Check if FullBlogPlugin is installed 1234 1447 # 1235 1448 blog_enabled = None 1449 blog_regex = '' 1236 1450 if self.get_config('components', 'tracfullblog.*') in ['enabled']: 1237 1451 blog_enabled = True 1238 1239 if not m['Subject']: 1240 subject = 'No Subject' 1241 else: 1242 subject = self.email_to_unicode(m['Subject']) 1243 1244 # 1245 # [hic] #1529: Re: LRZ 1246 # [hic] #1529?owner=bas,priority=medium: Re: LRZ 1247 # 1248 TICKET_RE = re.compile(r""" 1249 (?P<blog>blog:(?P<blog_id>\w*)) 1250 |(?P<new_fields>[#][?].*) 1251 |(?P<reply>[#][\d]+:) 1252 |(?P<reply_fields>[#][\d]+\?.*?:) 1253 """, re.VERBOSE) 1254 1255 # Find out if this is a ticket or a blog 1256 # 1257 result = TICKET_RE.search(subject) 1258 1452 blog_regex = '''|(?P<blog>blog:(?P<blog_id>\w*))''' 1453 1454 1455 # Check if DiscussionPlugin is installed 1456 # 1457 discussion_enabled = None 1458 discussion_regex = '' 1459 if self.get_config('components', 'tracdiscussion.api.*') in ['enabled']: 1460 discussion_enabled = True 1461 discussion_regex = r''' 1462 |(?P<forum>Forum[ ][#](?P<forum_id>\d+)[ ]-[ ]?) 1463 |(?P<topic>Topic[ ][#](?P<topic_id>\d+)[ ]-[ ]?) 1464 |(?P<message>Message[ ][#](?P<message_id>\d+)[ ]-[ ]?) 1465 ''' 1466 1467 1468 regex_str = ticket_regex + blog_regex + discussion_regex 1469 SYSTEM_RE = re.compile(regex_str, re.VERBOSE) 1470 1471 # Find out if this is a ticket, a blog or a discussion 1472 # 1473 result = SYSTEM_RE.search(subject) 1259 1474 if result: 1260 if result.group('blog'): 1261 if blog_enabled: 1475 # update ticket + fields 1476 # 1477 if result.group('reply') and self.TICKET_UPDATE: 1478 self.system = 'ticket' 1479 self.ticket_update(m, result.group('reply'), spam_msg) 1480 1481 # New ticket + fields 1482 # 1483 elif result.group('new_fields'): 1484 self.system = 'ticket' 1485 self.new_ticket(m, subject[:result.start('new_fields')], spam_msg, result.group('new_fields')) 1486 1487 if blog_enabled: 1488 if result.group('blog'): 1489 self.system = 'blog' 1262 1490 self.blog(result.group('blog_id')) 1263 else: 1264 if self.DEBUG: 1265 print "Fullblog plugin is not installed" 1266 return 1267 1268 # update ticket + fields 1269 # 1270 if result.group('reply_fields') and self.TICKET_UPDATE: 1271 self.ticket_update(m, result.group('reply_fields'), spam_msg) 1272 1273 # Update ticket 1274 # 1275 elif result.group('reply') and self.TICKET_UPDATE: 1276 self.ticket_update(m, result.group('reply'), spam_msg) 1277 1278 # New ticket + fields 1279 # 1280 elif result.group('new_fields'): 1281 self.new_ticket(m, subject[:result.start('new_fields')], spam_msg, result.group('new_fields')) 1282 1283 else: 1491 1492 if discussion_enabled: 1493 # New topic. 1494 # 1495 if result.group('forum'): 1496 self.system = 'discussion' 1497 self.id = int(result.group('forum_id')) 1498 self.discussion_topic(m, subject[result.end('forum'):]) 1499 1500 # Reply to topic. 1501 # 1502 elif result.group('topic'): 1503 self.system = 'discussion' 1504 self.id = int(result.group('topic_id')) 1505 self.discussion_topic_reply(m, subject[result.end('topic'):]) 1506 1507 # Reply to topic message. 1508 # 1509 elif result.group('message'): 1510 self.system = 'discussion' 1511 self.id = int(result.group('message_id')) 1512 self.discussion_message_reply(m, subject[result.end('message'):]) 1513 1514 else: 1515 self.system = 'ticket' 1284 1516 result = self.ticket_update_by_subject(subject) 1285 1517 if result: … … 1601 1833 1602 1834 if self.DEBUG: 1603 s = 'TD: attachment already exists: Ticket id : '1835 s = 'TD: attachment already exists: Id : ' 1604 1836 try: 1605 print "%s%s, Filename : %s" % (s, self.id, filename)1837 print "%s%s, Filename : %s" % (s, self.id, filename) 1606 1838 except UnicodeEncodeError, detail: 1607 1839 print "%s%s, Filename : Can not be printed due to non-ascii characters" %(s, self.id) … … 1613 1845 1614 1846 try: 1615 att = attachment.Attachment(self.env, 'ticket', self.id, filename) 1847 if self.system == 'discussion': 1848 att = attachment.Attachment(self.env, 'discussion', 'ticket/%s' 1849 % (self.id,), filename) 1850 else: 1851 att = attachment.Attachment(self.env, 'ticket', self.id, 1852 filename) 1616 1853 return True 1617 1854 except attachment.ResourceNotFound: … … 1634 1871 1635 1872 if part.get_content_maintype() == 'image' and inline: 1636 body_text.append('[[Image(%s)]]' % filename) 1873 if self.system != 'discussion': 1874 body_text.append('[[Image(%s)]]' % filename) 1637 1875 body_text.append("") 1638 1876 else: 1639 body_text.append('[attachment:"%s"]' % filename) 1877 if self.system != 'discussion': 1878 body_text.append('[attachment:"%s"]' % filename) 1640 1879 body_text.append("") 1641 1880 … … 1749 1988 1750 1989 ENABLE_SYSLOG = 0 1751 1752 1990 1753 1991 SHORT_OPT = 'chf:np:t:v' … … 1823 2061 from trac.ticket.notification import TicketNotifyEmail 1824 2062 from trac import config as trac_config 2063 from trac.core import TracError 2064 1825 2065 elif version == '0.11': 1826 2066 from trac import attachment … … 1830 2070 from trac import config as trac_config 1831 2071 from trac import util 2072 from trac.core import TracError 1832 2073 1833 2074 … … 1852 2093 os.environ['PYTHON_EGG_CACHE'] = python_egg_cache 1853 2094 2095 2096 if int(settings['debug']) > 0: 2097 print 'Loading environment', settings['project'] 2098 1854 2099 env = Environment(settings['project'], create=0) 1855 2100
Note: See TracChangeset
for help on using the changeset viewer.