def save_ticket(self, tckt, msg): # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(tckt, None): if change['permanent']: cnum += 1 nowdt = self.now nowdt = to_datetime(nowdt) tckt.save_changes(self.authname, msg, nowdt, cnum=str(cnum + 1)) ## Often the time overlaps and causes a db error, ## especially when the trac integration post-commit hook is used. ## NOTE TO SELF. I DON'T THINK THIS IS NECESSARY RIGHT NOW... #count = 0 #while count < 10: # try: # tckt.save_changes(self.authname, msg, self.now, cnum=cnum+1) # count = 42 # except Exception, e: # self.now += 1 # count += 1 tn = TicketNotifyEmail(self.env) tn.notify(tckt, newticket=0, modtime=nowdt) # We fudge time as it has to be unique self.now += 1
def _validate_mimebody(self, mime, ticket, newtk): """Body of a ticket notification message""" (mime_decoder, mime_name, mime_charset) = mime tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=newtk) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf('MIME-Version' not in headers) self.failIf('Content-Type' not in headers) self.failIf('Content-Transfer-Encoding' not in headers) self.failIf(not re.compile(r"1.\d").match(headers['MIME-Version'])) type_re = re.compile(r'^text/plain;\scharset="([\w\-\d]+)"$') charset = type_re.match(headers['Content-Type']) self.failIf(not charset) charset = charset.group(1) self.assertEqual(charset, mime_charset) self.assertEqual(headers['Content-Transfer-Encoding'], mime_name) # checks the width of each body line for line in body.splitlines(): self.failIf(len(line) > MAXBODYWIDTH) # attempts to decode the body, following the specified MIME endoding # and charset try: if mime_decoder: body = mime_decoder.decodestring(body) body = unicode(body, charset) except Exception, e: raise AssertionError, e
def apply_action_side_effects(self, req, ticket, action): """Add a cross-reference comment to the other ticket""" # TODO: This needs a lot more error checking. id = 'action_%s_xref' % action ticketnum = req.args.get(id).strip('#') actions = self.get_configurable_workflow().actions author = req.authname # Add a comment to the "remote" ticket to indicate this ticket is # related to it. format_string = actions[action].get( 'xref', 'Ticket %s is related to this ticket') comment = format_string % ('#%s' % ticket.id) # FIXME: we need a cnum to avoid messing up xticket = model.Ticket(self.env, ticketnum) # FIXME: We _assume_ we have sufficient permissions to comment on the # other ticket. now = datetime.now(utc) xticket.save_changes(author, comment, now) #Send notification on the other ticket try: tn = TicketNotifyEmail(self.env) tn.notify(xticket, newticket=False, modtime=now) except Exception, e: self.log.exception("Failure sending notification on change to " "ticket #%s: %s" % (ticketnum, e))
def _test_updater(disable): if disable: self.env.config.set('notification', 'always_notify_updater', 'false') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = u'This is a súmmäry' ticket['cc'] = '*****@*****.**' ticket.insert() ticket['component'] = 'dummy' now = datetime.now(utc) ticket.save_changes('*****@*****.**', 'This is a change', when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] if disable: self.failIf('*****@*****.**' in tolist) else: self.failIf('*****@*****.**' not in tolist)
def execute(self): """Execute the parsed commands""" #print "Commands: %s" % self.commands # Now parse the command in the ticket, and react accordingly # Cannnot produce error messages, as the pre-commit-hook would have failed already parser = CommitMessageCommandParser(self.env, self.changeset.message) parsed_commands = parser.validate_and_parse_commit_message() self.commands = dict() for command, ticket_id, remaining_time in parsed_commands: # REFACT: the parser should give the ids as ints already ticket_id = int(ticket_id) self.commands.setdefault(ticket_id, list()) self.commands.get(ticket_id).append( self.findCommand(command, remaining=remaining_time[:-1])) # Sort the ticket in reverse order by id, it will be most likely # that a task is existing after a User Story has been created, # in which case it will be possible to execute multiple command in # a hierarchy. TODO: Check hierarchy, but very expensive keys = self.commands.keys() keys.sort(reverse=True) for t_id, cmds in [(key, self.commands[key]) for key in keys]: ticket = self.tm.get(tkt_id=t_id) for cmd in cmds: cmd(ticket) self.tm.save(ticket, author=self.author, comment=self.message) from trac.ticket.notification import TicketNotifyEmail tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket.time_changed) # We need to invalidate the chart cache here because some tickets may # have been closed through commit comments. Unfortunately there is # no way to access the shared memory right now, see #565 return True
def _implementation(db): for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) new_changetime = datetime.now(utc) log_msg = "" if not modify_changetime: original_changetime = to_utimestamp(t.time_changed) _values = new_values.copy() for field in [f for f in new_values.keys() \ if f in self._fields_as_list]: _values[field] = self._merge_keywords( t.values[field], new_values[field], log) t.populate(_values) t.save_changes(req.authname, comment, when=new_changetime) if send_notifications: tn = TicketNotifyEmail(env) tn.notify(t, newticket=0, modtime=new_changetime) if not modify_changetime: self._reset_changetime(env, original_changetime, t) log_msg = "(changetime not modified)" log.debug('BatchModifyPlugin: saved changes to #%s %s' % (id, log_msg))
def create(self, req, summary, description, attributes={}, notify=False, when=None): """ Create a new ticket, returning the ticket ID. Overriding 'when' requires admin permission. """ t = model.Ticket(self.env) t['summary'] = summary t['description'] = description t['reporter'] = req.authname for k, v in attributes.iteritems(): t[k] = v t['status'] = 'new' t['resolution'] = '' # custom create timestamp? if when and not 'TICKET_ADMIN' in req.perm: self.log.warn( "RPC ticket.create: %r not allowed to create with " "non-current timestamp (%r)", req.authname, when) when = None t.insert(when=when) if notify: try: tn = TicketNotifyEmail(self.env) tn.notify(t, newticket=True) except Exception, e: self.log.exception("Failure sending notification on creation " "of ticket #%s: %s" % (t.id, e))
def test_email_map(self): """Login-to-email mapping""" self.env.config.set('notification', 'always_notify_owner', 'true') self.env.config.set('notification', 'always_notify_reporter', 'true') self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') self.env.known_users = [ ('joeuser', 'Joe User', '*****@*****.**'), ('jim@domain', 'Jim User', '*****@*****.**') ] ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['owner'] = 'jim@domain' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] # 'To' list should have been resolved to the real email address self.failIf('*****@*****.**' not in tolist) self.failIf('*****@*****.**' not in tolist) self.failIf('joeuser' in tolist) self.failIf('jim@domain' in tolist)
def create(self, req, summary, description, attributes={}, notify=False): """ Create a new ticket, returning the ticket ID. PS: Borrowed from XmlRpcPlugin. """ if 'product' in attributes: env = self.env.parent or self.env if attributes['product']: env = ProductEnvironment(env, attributes['product']) else: env = self.env t = Ticket(env) t['summary'] = summary t['description'] = description t['reporter'] = req.authname for k, v in attributes.iteritems(): t[k] = v t['status'] = 'new' t['resolution'] = '' t.insert() if notify: try: tn = TicketNotifyEmail(env) tn.notify(t, newticket=True) except Exception, e: self.log.exception("Failure sending notification on creation " "of ticket #%s: %s" % (t.id, e))
def post_to_ticket(msg, author, tkt_id, env): """Post the message to the ticket and send a notify email.""" from trac.ticket.notification import TicketNotifyEmail from trac.ticket import Ticket from trac.ticket.web_ui import TicketModule from trac.util.datefmt import utc now = datetime.now(utc) try: db = env.get_db_cnx() # Get the related trac ticket object ticket = Ticket(env, tkt_id, db) # determine sequence number... cnum = 0 tm = TicketModule(env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, msg, now, db, cnum + 1) db.commit() tn = TicketNotifyEmail(env) tn.notify(ticket, newticket=0, modtime=now) except Exception, e: msg = 'Unexpected error processing ticket ID %s: %s' % (tkt_id, e) print >>sys.stderr, msg
def test_ignore_domains(self): """Non-SMTP domain exclusion""" self.env.config.set('notification', 'ignore_domains', 'example.com, example.org') self.env.known_users = \ [('*****@*****.**', 'No Email', ''), ('*****@*****.**', 'With Email', '*****@*****.**')] ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['owner'] = '*****@*****.**' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] # 'To' list should not contain addresses with non-SMTP domains self.failIf('*****@*****.**' in tolist) self.failIf('*****@*****.**' in tolist) # 'To' list should have been resolved to the actual email address self.failIf('*****@*****.**' not in tolist) self.failIf(len(tolist) != 1)
def _test_default_domain(enabled): self.env.config.set('notification', 'always_notify_owner', 'false') self.env.config.set('notification', 'always_notify_reporter', 'false') self.env.config.set('notification', 'smtp_always_cc', '') ticket = Ticket(self.env) ticket['cc'] = 'joenodom, [email protected]' ticket['summary'] = 'This is a summary' ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') if enabled: self.env.config.set('notification', 'smtp_default_domain', 'example.org') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'Cc' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] self.failIf('*****@*****.**' not in cclist) self.failIf('*****@*****.**' not in cclist) if not enabled: self.failIf(len(cclist) != 2) self.failIf('joenodom' in cclist) else: self.failIf(len(cclist) != 3) self.failIf('*****@*****.**' not in cclist)
def _test_short_login(enabled): ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['summary'] = 'This is a summary' ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') if enabled: self.env.config.set('notification', 'use_short_addr', 'true') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should not have a 'To' header if not enabled: self.failIf('To' in headers) else: tolist = [addr.strip() for addr in headers['To'].split(',')] # Msg should have a 'Cc' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] if enabled: # Msg should be delivered to the reporter self.failIf(ticket['reporter'] not in tolist) else: # Msg should not be delivered to joeuser self.failIf(ticket['reporter'] in cclist) # Msg should still be delivered to the always_cc list self.failIf( self.env.config.get('notification', 'smtp_always_cc') not in cclist)
def test_date(self): """Date format compliance (RFC822) we do not support 'military' format""" date_str = r"^((?P<day>\w{3}),\s*)*(?P<dm>\d{2})\s+" \ r"(?P<month>\w{3})\s+(?P<year>\d{4})\s+" \ r"(?P<hour>\d{2}):(?P<min>[0-5][0-9])" \ r"(:(?P<sec>[0-5][0-9]))*\s" \ r"((?P<tz>\w{2,3})|(?P<offset>[+\-]\d{4}))$" date_re = re.compile(date_str) # python time module does not detect incorrect time values days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] tz = [ 'UT', 'GMT', 'EST', 'EDT', 'CST', 'CDT', 'MST', 'MDT', 'PST', 'PDT' ] ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf('Date' not in headers) mo = date_re.match(headers['Date']) self.failIf(not mo) if mo.group('day'): self.failIf(mo.group('day') not in days) self.failIf(int(mo.group('dm')) not in range(1, 32)) self.failIf(mo.group('month') not in months) self.failIf(int(mo.group('hour')) not in range(0, 24)) if mo.group('tz'): self.failIf(mo.group('tz') not in tz)
def attachment_added(self, attachment): # Check whether we're dealing with a ticket resource resource = attachment.resource while resource: if resource.realm == 'ticket': break resource = resource.parent if (resource and resource.realm == 'ticket' and resource.id is not None): with self.env.db_transaction as db: ticket = Ticket(attachment.env, resource.id, db) if (attachment.author == ticket['reporter'] and ticket['status'] == 'pending'): self.env.log.info('Removing Pending status for ticket %s due to attachment' % (ticket.id)) comment = 'Attachment (%s) added by ticket reporter.' % (attachment.filename) ticket['status'] = self.config.get('ticket', 'pending_removal_status') # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): c_cnum = change.get('cnum', None) if c_cnum and int(c_cnum) > cnum: cnum = int(c_cnum) #We can't just use attachment.date as it screws up event sequencing now = datetime.now(utc) ticket.save_changes(attachment.author, comment, now, db, str(cnum + 1)) #trigger notification since we've changed the ticket tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now)
def test_recipients(self): """To/Cc recipients""" ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" < *****@*****.** >' ticket['owner'] = '*****@*****.**' ticket['cc'] = '[email protected], [email protected], ' \ '*****@*****.**' ticket['summary'] = 'Foo' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) recipients = notifysuite.smtpd.get_recipients() # checks there is no duplicate in the recipient list rcpts = [] for r in recipients: self.failIf(r in rcpts) rcpts.append(r) # checks that all cc recipients have been notified cc_list = self.env.config.get('notification', 'smtp_always_cc') cc_list = "%s, %s" % (cc_list, ticket['cc']) for r in cc_list.replace(',', ' ').split(): self.failIf(r not in recipients) # checks that owner has been notified self.failIf(smtp_address(ticket['owner']) not in recipients) # checks that reporter has been notified self.failIf(smtp_address(ticket['reporter']) not in recipients)
def process(self, commit, status, branch): self.closestatus = status milestones = [ m.name for m in Milestone.select(self.env) if m.name != 'unknown' ] if branch.startswith('fixes/'): branch = branch[6:] milestones = [m for m in milestones if m.startswith(branch)] self.milestone = sorted(milestones)[-1] msg = commit['message'] self.env.log.debug("Processing Commit: %s", msg) msg = "%s \n Branch: %s \n Changeset: %s" % (msg, branch, commit['id']) # author = commit['author']['name'] author = 'Github' timestamp = datetime.now(utc) cmd_groups = command_re.findall(msg) self.env.log.debug("Function Handlers: %s" % cmd_groups) tickets = {} for cmd, tkts in cmd_groups: funcname = self.__class__._supported_cmds.get(cmd.lower(), '') self.env.log.debug("Function Handler: %s" % funcname) if funcname: for tkt_id in ticket_re.findall(tkts): if (branch == "master") or branch.startswith("fixes/"): tickets.setdefault(tkt_id, []).append(getattr(self, funcname)) # disable this stuff for now, it causes duplicates on merges # proper implementation of this will require tracking commit hashes # else: # tickets.setdefault(tkt_id, []).append(self._cmdRefs) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, msg, timestamp, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=timestamp) except Exception, e: import traceback traceback.print_exc(file=sys.stderr)
def _do_save(self, req, db, ticket): if req.perm.has_permission('TICKET_CHGPROP'): # TICKET_CHGPROP gives permission to edit the ticket if not req.args.get('summary'): raise TracError('Tickets must contain summary.') if req.args.has_key('description') or req.args.has_key('reporter'): req.perm.assert_permission('TICKET_ADMIN') ticket.populate(req.args) else: req.perm.assert_permission('TICKET_APPEND') # Mid air collision? if int(req.args.get('ts')) != ticket.time_changed: raise TracError("Sorry, can not save your changes. " "This ticket has been modified by someone else " "since you started", 'Mid Air Collision') # Do any action on the ticket? action = req.args.get('action') actions = TicketSystem(self.env).get_available_actions(ticket, req.perm) if action not in actions: raise TracError('Invalid action') # TODO: this should not be hard-coded like this if action == 'accept': ticket['status'] = 'assigned' ticket['owner'] = req.authname if action == 'resolve': ticket['status'] = 'closed' ticket['resolution'] = req.args.get('resolve_resolution') elif action == 'reassign': ticket['owner'] = req.args.get('reassign_owner') ticket['status'] = 'new' elif action == 'reopen': ticket['status'] = 'reopened' ticket['resolution'] = '' self._validate_ticket(req, ticket) now = int(time.time()) cnum = req.args.get('cnum') replyto = req.args.get('replyto') internal_cnum = cnum if cnum and replyto: # record parent.child relationship internal_cnum = '%s.%s' % (replyto, cnum) if ticket.save_changes(get_reporter_id(req, 'author'), req.args.get('comment'), when=now, db=db, cnum=internal_cnum): db.commit() try: tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) except Exception, e: self.log.exception("Failure sending notification on change to " "ticket #%s: %s" % (ticket.id, e))
def test_notification_get_message_id_unicode(self): ticket = Ticket(self.env) ticket['summary'] = 'My Summary' ticket['description'] = 'Some description' ticket.insert() self.env.config.set('project', 'url', u"пиво Müller ") tn = TicketNotifyEmail(self.env) tn.ticket = ticket tn.get_message_id('foo')
def __init__(self, project=options.project, author=AUTHOR, maxage=options.maxage, url=options.url): self.env = open_environment(project) db = self.env.get_db_cnx() cursor = db.cursor() if url is None: url = self.env.config.get('trac', 'base_url') self.env.href = Href(url) self.env.abs_href = Href(url) self.msg = MESSAGE % (maxage) self.now = int(time.time()) maxtime = int(time.time()) - (60 * 60 * 24 * maxage) cursor.execute("SELECT id FROM ticket t, ticket_custom c " \ "WHERE t.status <> %s " \ "AND t.changetime < %s " \ "AND t.id = c.ticket " \ "AND c.name = %s " \ "AND c.value = %s ", ('closed', maxtime, 'pending', '1')) rows = cursor.fetchall() for row in rows: id = row[0] try: ticket = Ticket(self.env, id, db) ticket['status'] = 'closed' ticket['pending'] = '0' # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, self.msg, self.now, db, cnum + 1) db.commit() print 'Closing Ticket %s (%s)\n' % (id, ticket['summary']) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=self.now) except Exception, e: import traceback traceback.print_exc(file=sys.stderr) print>>sys.stderr, 'Unexpected error while processing ticket ' \ 'ID %s: %s' % (id, e)
def __init__(self, project=options.project, author=options.user, rev=options.rev, url=options.url): self.env = open_environment(project) repos = self.env.get_repository() repos.sync() # Instead of bothering with the encoding, we'll use unicode data # as provided by the Trac versioncontrol API (#1310). try: chgset = repos.get_changeset(rev) except NoSuchChangeset: return # out of scope changesets are not cached self.author = chgset.author self.rev = rev self.msg = "(In [%s]) %s" % (rev, chgset.message) self.now = datetime.now(utc) cmd_groups = command_re.findall(self.msg) tickets = {} for cmd, tkts in cmd_groups: funcname = CommitHook._supported_cmds.get(cmd.lower(), '') if funcname: for tkt_id in ticket_re.findall(tkts): func = getattr(self, funcname) tickets.setdefault(tkt_id, []).append(func) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(self.author, self.msg, self.now, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=self.now) except Exception, e: # import traceback # traceback.print_exc(file=sys.stderr) print>>sys.stderr, 'Unexpected error while processing ticket ' \ 'ID %s: %s' % (tkt_id, e)
def notify(self, env, tkt, new=True, modtime=0): """ A Wrapper for TRAC notify function """ try: # create false {abs_}href properties, to trick Notify() # tn = TicketNotifyEmail(env) tn.notify(tkt, new, modtime) except Exception, e: print 'TD: Failure sending notification on creation of ticket #%s: %s' % ( tkt['id'], e)
def process_message(self, req, msgstr): project_list = get_project_list(self.env, req, return_self=True, include_errors=False) msg = email.message_from_string(msgstr) msg_from = parseaddr(msg.get("from"))[1] msg_subject = msg.get("subject") in_reply_to = msg.get("in-reply-to", "") msg_content = "" if not msg.is_multipart(): msg_content = msg.get_payload(decode=True) else: for part in msg.walk(): if part.get_content_type() == 'text/plain': msg_content = part.get_payload(decode=True) msg_content = to_unicode(msg_content) match = INREPLYTO_TICKET_EXPR.match(in_reply_to) if match: for project, project_path, project_url, project_env in project_list: if not project_env: continue if os.path.basename(project_path).lower() != match.group( 'base').lower(): continue ticket = Ticket(project_env, int(match.group('id'))) now = datetime.now(utc) ticket.save_changes(msg_from, msg_content, when=now) #----- Copiado de web_ui.py ----- try: tn = TicketNotifyEmail(project_env) tn.notify(ticket, newticket=False, modtime=now) except Exception, e: self.log.error( "Failure sending notification on change to " "ticket #%s: %s", ticket.id, exception_to_unicode(e)) ## After saving the changes, apply the side-effects. #for controller in controllers: # self.env.log.debug('Side effect for %s' % # controller.__class__.__name__) #----- Fin Copiado de web_ui.py ----- return (True, "Ticket reply match - %s#%s" % (match.group('base'), match.group('id')))
def _do_create(self, req, ticket): ticket.insert() # Notify try: tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) except Exception, e: self.log.error( """Failure sending notification on creation of ticket #%s: %s""", ticket.id, e)
def _notify(self, ticket, date): """Send a ticket update notification.""" if not self.notify: return try: tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=date) except Exception, e: self.log.error( "Failure sending notification on change to " "ticket #%s: %s", ticket.id, exception_to_unicode(e))
def process(self, commit, status, enable_revmap, reponame): self.closestatus = status msg = commit['message'] self.env.log.debug("Processing Commit: %s", msg) note = "Changeset: [/changeset/%s %s]" % (commit['id'], commit['id']) url = "URL: %s" % commit['url'] msg = "%s \n * %s \n * %s" % (msg, note, url) author = commit['author']['name'] timestamp = datetime.now(utc) if int(enable_revmap): self.env.log.debug("adding commit %s to revmap", commit['id']) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO svn_revmap (svn_rev, git_hash, commit_msg) VALUES (0, %s, %s);", (commit['id'], commit['message'])) db.commit() cmd_groups = command_re.findall(msg) self.env.log.debug("Function Handlers: %s" % cmd_groups) tickets = {} for cmd, tkts in cmd_groups: funcname = self.__class__._supported_cmds.get(cmd.lower(), '') self.env.log.debug("Function Handler: %s" % funcname) if funcname: for tkt_id in ticket_re.findall(tkts): func = getattr(self, funcname) tickets.setdefault(tkt_id, []).append(func) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, msg, timestamp, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=timestamp) except Exception, e: import traceback traceback.print_exc(file=sys.stderr)
def test_cc_only(self): """Notification w/o explicit recipients but Cc: (#3101)""" ticket = Ticket(self.env) ticket['summary'] = 'Foo' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) recipients = notifysuite.smtpd.get_recipients() # checks that all cc recipients have been notified cc_list = self.env.config.get('notification', 'smtp_always_cc') for r in cc_list.replace(',', ' ').split(): self.failIf(r not in recipients)
def test_notification_does_not_alter_ticket_instance(self): ticket = Ticket(self.env) ticket['summary'] = 'My Summary' ticket['description'] = 'Some description' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) self.assertNotEqual(None, notifysuite.smtpd.get_message()) self.assertEqual('My Summary', ticket['summary']) self.assertEqual('Some description', ticket['description']) valid_fieldnames = set([f['name'] for f in ticket.fields]) current_fieldnames = set(ticket.values.keys()) self.assertEqual(set(), current_fieldnames - valid_fieldnames)
def test_md5_digest(self): """MD5 digest w/ non-ASCII recipient address (#3491)""" self.env.config.set('notification', 'always_notify_owner', 'false') self.env.config.set('notification', 'always_notify_reporter', 'true') self.env.config.set('notification', 'smtp_always_cc', '') ticket = Ticket(self.env) ticket['reporter'] = u'"Jöe Usèr" <*****@*****.**>' ticket['summary'] = u'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message)
def send_notification(self, ticket, author): if TicketNotifyEmail: tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) else: event = TicketChangeEvent('changed', ticket, ticket['changetime'], author) try: NotificationSystem(self.env).notify(event) except Exception as e: self.log.error( "Failure sending notification on change to " "ticket #%s: %s", ticket.id, exception_to_unicode(e))