def __init__(self, env): NotifyEmail.__init__(self, env) self.prev_cc = [] ambiguous_char_width = env.config.get('notification', 'ambiguous_char_width', 'single') self.ambiwidth = 2 if ambiguous_char_width == 'double' else 1
def notify_unreachable_milestone(self, tickets): """ Send a digest mail listing all tickets still opened in the milestone """ self.populate_unreachable_tickets_data(tickets) NotifyEmail.notify(self, self.milestone, "Milestone %s still has opened ticket" % self.milestone)
def __init__(self, env): NotifyEmail.__init__(self, env) self.prev_cc = [] self.ambiguous_char_width = env.config.get('notification', 'ambiguous_char_width', 'single') self.text_widths = {}
def send(self, to_recipients, cc_recipients): header = {} # Add item specific e-mail header fields. if self.message: # ID of the message. header["Message-ID"] = self.get_message_email_id(self.message["id"]) header["X-Trac-Message-ID"] = to_unicode(self.message["id"]) header["X-Trac-Discussion-URL"] = self.message["link"] # ID of replied message. if self.message["replyto"] != -1: reply_id = self.get_message_email_id(self.message["replyto"]) else: reply_id = self.get_topic_email_id(self.message["topic"]) header["In-Reply-To"] = reply_id header["References"] = reply_id elif self.topic: # ID of the message. header["Message-ID"] = self.get_topic_email_id(self.topic["id"]) header["X-Trac-Topic-ID"] = to_unicode(self.topic["id"]) header["X-Trac-Discussion-URL"] = self.topic["link"] elif self.forum: # ID of the message. header["Message-ID"] = self.get_forum_email_id(self.forum["id"]) header["X-Trac-Forum-ID"] = to_unicode(self.forum["id"]) header["X-Trac-Discussion-URL"] = self.forum["link"] else: # Should not happen. raise TracError("DiscussionPlugin internal error.") # Send e-mail. self.template = Chrome(self.env).load_template(self.template_name, method="text") self.env.log.debug("to_recipients: %s cc_recipients: %s" % (to_recipients, cc_recipients)) NotifyEmail.send(self, to_recipients, cc_recipients, header)
def invite(self, context, forum = None, topic = None, recipients = []): # Store link to currently notifying forum. self.forum = forum self.topic = topic # Initialize template data. data = {} data['forum'] = self.forum data['topic'] = self.topic data['prefix'] = self.config.get('notification', 'smtp_subject_prefix') if data['prefix'] == '__default__': data['prefix'] = self.env.project_name self.data.update({'discussion' : data}) # Which item notify about? if self.topic: self.topic['link'] = self.env.abs_href.discussion('topic', self.topic['id']) self.template_name = 'topic-invite-body.txt' elif self.forum: self.forum['link'] = self.env.abs_href.discussion('forum', self.forum['id']) self.template_name = 'forum-invite-body.txt' # Send e-mail to all subscribers. self.cc_recipients = recipients # Render subject template and send notification. subject = (to_unicode(Chrome(self.env).render_template(context.req, self.topic and 'topic-invite-subject.txt' or 'forum-invite-subject.txt', self.data, 'text/plain'))).strip() NotifyEmail.notify(self, id, subject)
def notifyTaskEvent(self, task_event_list): """ Send task event by mail if recipients is defined in trac.ini """ self.env.log.debug("notifying task event...") if self.cronconf.get_email_notifier_task_recipient() : # prepare the data for the email content generation mess = "" start = True for event in task_event_list: if start: mess = mess + "task[%s]" % (event.task.getId(),) mess = mess + "\nstarted at %d h %d" % (event.time.tm_hour, event.time.tm_min) mess = mess + "\n" else: mess = mess + "ended at %d h %d" % (event.time.tm_hour, event.time.tm_min) if (event.success): mess = mess + "\nsuccess" else: mess = mess + "\nFAILURE" mess = mess + "\n\n" start = not start self.data.update({ "notify_body": mess, }) NotifyEmail.notify(self, None, "task event notification") else: self.env.log.debug("no recipient for task event, aborting")
def send(self, torcpts, ccrcpts): header = {} # Add item specific e-mail header fields. if self.message: # Get this messge ID. header['Message-ID'] = self.get_message_id(self.forum['id'], self.topic['id'], self.message['id']) header['X-Trac-Message-ID'] = to_unicode(self.message['id']) header['X-Trac-Discussion-URL'] = self.message['link'] # Get replied message ID. reply_id = self.get_message_id(self.forum['id'], self.topic['id'], self.message['replyto']) header['In-Reply-To'] = reply_id header['References'] = reply_id else: # Get this message ID. header['Message-ID'] = self.get_message_id(self.forum['id'], self.topic['id'], 0) header['X-Trac-Topic-ID'] = to_unicode(self.topic['id']) header['X-Trac-Discussion-URL'] = self.topic['link'] # Send e-mail. NotifyEmail.send(self, torcpts, ccrcpts, header)
def notify_opened_ticket(self, owner, tickets): """ Send a digest mail to ticket owner about ticket still opened """ self.populate_unreachable_tickets_data(tickets) NotifyEmail.notify(self, owner, "Milestone %s still has opened ticket" % self.milestone)
def __init__(self, env, subject=None, data=None): NotifyEmail.__init__(self, env) self.to = [] self.cc = [] self.from_email = env.config.get("notification", "smtp_from") self.subject = subject or "" # If string given, place it into body variable, otherwise use dict or empty dict self.data = {"body": data} if isinstance(data, basestring) else data or {}
def notify(self, build): self.build = build self.data.update(self.template_data()) subject = '[%s Build] %s [%s] %s' % (self.readable_states[build.status], self.env.project_name, self.build.rev, self.build.config) NotifyEmail.notify(self, self.build.id, subject)
def __init__(self, env): NotifyEmail.__init__(self, env) self.from_name = self.config.get('fullblog-notification', 'from_name') self.from_email = self.config.get('fullblog-notification', 'from_email') self.reply_to_email = self.config.get('fullblog-notification', 'reply_to_email') or self.from_email self.notification_actions = self.config.getlist('fullblog-notification', 'notification_actions') self.no_notification_categories = self.config.getlist('fullblog-notification', 'no_notification_categories')
def __init__(self, env, recipient, body, link): NotifyEmail.__init__(self, env) self.recipient = recipient self.data = { 'body': body, 'link': link, 'project_name': env.project_name, 'project_url': env.project_url or self.env.abs_href(), }
def notify(self, username, subject): # save the username for use in `get_smtp_address` self._username = username old_public_cc = self.config.getbool('notification', 'use_public_cc') # override public cc option so that the user's email is included in the To: field self.config.set('notification', 'use_public_cc', 'true') try: NotifyEmail.notify(self, username, subject) finally: self.config.set('notification', 'use_public_cc', old_public_cc)
def notify(self, username, password): # save the username for use in `get_smtp_address` self._username = username self.hdf['account.username'] = username self.hdf['account.password'] = password self.hdf['login.link'] = self.env.abs_href.login() projname = self.config.get('project', 'name') subject = '[%s] Trac password reset for user: %s' % (projname, username) NotifyEmail.notify(self, username, subject)
def __init__(self, env, data, template_name=None): NotifyEmail.__init__(self, env) locale_dir = pkg_resources.resource_filename(__name__, 'locale') add_domain(self.env.path, locale_dir) if template_name: self.template_name = template_name self._data = data if self._data and self._data['user_data']: # self._locale_string = self._data['user_data']['language'] # not used at the moment self._email_adr = self._data['user_data']['email']
def send(self, torcpts, ccrcpts): dest = self.reporter or 'anonymous' hdrs = {} hdrs['Message-ID'] = self.get_message_id(dest, self.modtime) hdrs['X-Trac-Ticket-ID'] = str(self.ticket.id) hdrs['X-Trac-Ticket-URL'] = self.ticket['link'] if not self.newticket: msgid = self.get_message_id(dest) hdrs['In-Reply-To'] = msgid hdrs['References'] = msgid NotifyEmail.send(self, torcpts, ccrcpts, hdrs)
def notify(self, build_info): self.build_info = build_info self.data = self.build_info subject = '[%s Build] %s [%s] %s' % (self.build_info.status, self.env.project_name, self.build_info.changeset, self.build_info.config) stream = self.template.generate(**self.data) body = stream.render('text') self.env.log.debug('notification: %s' % body ) NotifyEmail.notify(self, self.build_info.id, subject)
def send(self, torcpts, ccrcpts): dest = self.reporter or "anonymous" hdrs = {} hdrs["Message-ID"] = self.get_message_id(dest, self.modtime) hdrs["X-Trac-Ticket-ID"] = str(self.ticket.id) hdrs["X-Trac-Ticket-URL"] = self.data["ticket"]["link"] if not self.newticket: msgid = self.get_message_id(dest) hdrs["In-Reply-To"] = msgid hdrs["References"] = msgid NotifyEmail.send(self, torcpts, ccrcpts, hdrs)
def __init__(self, env, project, message, authname): NotifyEmail.__init__(self, env) self.from_email = env.config.get('notification', 'smtp_from') add_auth_url = project.get_url() + "admin/general/permissions" self.project = project self.env = env self.data = {'project_name': project.project_name, 'message': message, 'authname': authname, 'add_auth_url': add_auth_url}
def remind(self, tiketsByReporter): """ Send a digest mail to the reporter to remind them of those orphaned tickets """ for reporter in tiketsByReporter.keys(): # prepare the data for the email content generation self.data.update({ "ticket_count": len(tiketsByReporter[owner]), "delay": delay }) NotifyEmail.notify(self, reporter, "orphaned ticket notification")
def remind(self, tiketsByOwner): """ Send a digest mail to ticket owner to remind him of those sleeping tickets """ for owner in tiketsByOwner.keys(): # prepare the data for the email content generation self.data.update({ "ticket_count": len(tiketsByOwner[owner]), "delay": delay }) NotifyEmail.notify(self, owner, "Sleeping ticket notification")
def notify(self, to, key): addr = self.get_smtp_address(to) if addr is None: raise TracError('Invalid email address %s'%to) self.hdf['to'] = addr self.hdf['key'] = key subject = 'TracBL API key for %s'%addr NotifyEmail.notify(self, addr, subject)
def notify(self, username, subject): # save the username for use in `get_smtp_address` self._username = username old_public_cc = self.config.getbool('notification', 'use_public_cc') # override public cc option so that the user's email is included in the To: field self.config.set('notification', 'use_public_cc', 'true') try: NotifyEmail.notify(self, username, subject) # DEVEL: Better use new 'finally' statement here, but # still need to care for Python 2.4 (RHEL5.x) for now except: pass self.config.set('notification', 'use_public_cc', old_public_cc)
def notify_attachment(self, ticket, author, filename, modtime, body): """Send ticket attachment notification (untranslated)""" t = deactivate() translated_fields = ticket.fields try: ticket.fields = TicketSystem(self.env).get_ticket_fields() self.ticket = ticket self.modtime = modtime self.newticket = False self.reporter = '' self.owner = '' link = self.env.abs_href.ticket(ticket.id) summary = self.ticket['summary'] ticket_values = ticket.values.copy() ticket_values['id'] = ticket.id wrap_kargs = { 'initial_indent': ' ', 'subsequent_indent': ' ', 'linesep': CRLF } if 'ambiwidth' in getargspec(wrap)[0]: wrap_kargs['ambiwidth'] = self.ambiwidth ticket_values['description'] = wrap( ticket_values.get('description', ''), self.COLS, **wrap_kargs ) ticket_values['new'] = self.newticket ticket_values['link'] = link subject = 'Re: ' + self.format_subj(summary) author = obfuscate_email_address(author) change = { 'author': author } self.data.update({ 'ticket_props': self.format_props(), 'ticket_body_hdr': self.format_hdr(), 'subject': subject, 'ticket': ticket_values, 'change': change, 'changes_body': body, }) NotifyEmail.notify(self, ticket.id, subject) finally: ticket.fields = translated_fields reactivate(t)
def notify(self, username, action): self.data.update({ 'account': { 'username': username, 'action': action }, 'login': { 'link': self.env.abs_href.login(), } }) projname = self.config.get('project', 'name') subject = '[%s] %s: %s' % (projname, action, username) NotifyEmail.notify(self, username, subject)
def get_smtp_address(self, addr): """Overrides `get_smtp_address` in order to prevent CCing users other than the user whose password is being reset. """ if addr == self._username: return NotifyEmail.get_smtp_address(self, addr) else: return None
def get_smtp_address(self, addr): """Overrides `get_smtp_address` in order to prevent CCing users other than those in the account_changes_notify_addresses option. """ if addr in self._recipients: return NotifyEmail.get_smtp_address(self, addr) else: return
def notify(self, comment): self.comment_author = self._get_author_name(comment) self.data.update({ "comment": comment, "comment_url": self.env.abs_href() + comment.href(), "project_url": self.env.project_url or self.env.abs_href(), }) projname = self.config.get("project", "name") subject = "Re: [%s] %s" % (projname, comment.link_text()) try: NotifyEmail.notify(self, comment, subject) except Exception, e: self.env.log.error("Failure sending notification on creation of " "comment #%d: %s", comment.id, e)
def notify(self, username, action): self.data.update({ 'account': { 'username': username, 'action': action }, 'login': { 'link': self.env.abs_href.login(), } }) projname = self.config.get('project', 'name') subject = '[%s] %s: %s' % (projname, action, username) try: NotifyEmail.notify(self, username, subject) except Exception, e: # Enable dedicated, graceful handling of notification issues. raise NotificationError(e)
def _notify(self, tickets, new_values, comment, action, author): self.tickets = tickets changes_body = '' self.reporter = '' self.owner = '' changes_descr = '\n'.join(['%s to %s' % (prop, val) for (prop, val) in new_values.iteritems()]) tickets_descr = ', '.join(['#%s' % t for t in tickets]) subject = self.format_subj(tickets_descr) link = self.env.abs_href.query(id=','.join([str(t) for t in tickets])) self.data.update({ 'tickets_descr': tickets_descr, 'changes_descr': changes_descr, 'comment': comment, 'action': action, 'author': author, 'subject': subject, 'ticket_query_link': link, }) NotifyEmail.notify(self, tickets, subject, author)
def notify(self, blog, action, version=None, time=None, comment=None, author=None): # Don't notify if action is explicitly omitted from notification_actions if self.notification_actions != [] and \ action not in self.notification_actions: self.env.log.info('No notification sent because action is omitted ' \ 'from notification_actions option list') return # Don't notify if post has one of the specified categories for category in blog.category_list: if category in self.no_notification_categories: self.env.log.info('No notification sent because there are one ' \ 'or more matches between post\'s categories list ' \ 'and no_notification_categories option list') return self.blog = blog self.change_author = author self.time = time self.action = action self.version = version self.data['name']= blog.name self.data['title']= blog.title self.data['body']= blog.body self.data['comment']= comment self.data['version']= version self.data['author']= author self.data['action']= action self.data['time'] = format_datetime(time, '%Y-%m-%d %H:%M') self.data['url']= self.env.abs_href.blog(blog.name) self.data['project'] = {'name': self.env.project_name, 'url': self.env.project_url, 'description': self.env.project_description} subject = self.format_subject() NotifyEmail.notify(self, blog.name, subject)
def notify(self, comment): self.comment_author = self._get_author_name(comment) parsed_uri = urlparse(self.env.abs_href()) domain = '{uri.scheme}://{uri.netloc}'.format(uri=parsed_uri) self.data.update({ "comment": comment, "comment_url": domain + comment.href(), "project_url": self.env.project_url or self.env.abs_href(), }) projname = self.config.get("project", "name") subject = "Re: [%s] %s" % (projname, comment.link_text()) try: NotifyEmail.notify(self, comment, subject) except Exception, e: self.env.log.error( "Failure sending notification on creation of " "comment #%d: %s", comment.id, e)
def send(self, to_recipients, cc_recipients): header = {} # Add item specific e-mail header fields. if self.message: # ID of the message. header['Message-ID'] = self.get_message_email_id(self.message['id']) header['X-Trac-Message-ID'] = to_unicode(self.message['id']) header['X-Trac-Discussion-URL'] = self.message['link'] # ID of replied message. if self.message['replyto'] != -1: reply_id = self.get_message_email_id(self.message['replyto']) else: reply_id = self.get_topic_email_id(self.message['topic']) header['In-Reply-To'] = reply_id header['References'] = reply_id elif self.topic: # ID of the message. header['Message-ID'] = self.get_topic_email_id(self.topic['id']) header['X-Trac-Topic-ID'] = to_unicode(self.topic['id']) header['X-Trac-Discussion-URL'] = self.topic['link'] elif self.forum: # ID of the message. header['Message-ID'] = self.get_forum_email_id(self.forum['id']) header['X-Trac-Forum-ID'] = to_unicode(self.forum['id']) header['X-Trac-Discussion-URL'] = self.forum['link'] else: # Should not happen. raise TracError('DiscussionPlugin internal error.') # Send e-mail. self.template = Chrome(self.env).load_template(self.template_name, method = 'text') self.env.log.debug('to_recipients: %s cc_recipients: %s' % ( to_recipients, cc_recipients)) NotifyEmail.send(self, to_recipients, cc_recipients, header)
def notify(self): if not self.queueid or not self.build: return False NotifyEmail.notify(self, self.queueid, self.subject) return True
def send(self, torcpts, ccrcpts): if self.imitate_ticket_notification: TicketNotifyEmail.send(self, torcpts, ccrcpts) else: NotifyEmail.send(self, torcpts, ccrcpts)
def __init__(self, env): NotifyEmail.__init__(self, env)
def send(self, torcpts, ccrcpts): mime_headers = { 'X-Trac-Build-ID': str(self.build.id), 'X-Trac-Build-URL': self.build_link(), } NotifyEmail.send(self, torcpts, ccrcpts, mime_headers)
def notify(self, req, cursor, action, forum=None, topic=None, message=None, torcpts=[], ccrcpts=[]): self.env.log.debug("action: %s" % action) self.env.log.debug("forum: %s" % forum) self.env.log.debug("topic: %s" % topic) self.env.log.debug("message: %s" % message) self.env.log.debug("torcpts: %s" % torcpts) self.env.log.debug("ccrcpts: %s" % ccrcpts) # Store link to currently notifying forum, topic and message. self.forum = forum self.topic = topic self.message = message self.torcpts = torcpts self.ccrcpts = ccrcpts # Get action and item of action. index = action.find('-') item = action[:index] action = action[index + 1:] # Which item notify about: if item == 'topic': # Prepare topic specific fields. re = '' title = 'Topic' id = self.topic['id'] author = " Author: %s" % self.topic['author'] time = " Time: %s" % format_datetime(self.topic['time']) body = self.topic['body'] link = req.abs_href.discussion(self.forum['id'], self.topic['id']) # Save link for bad times. topic['link'] = link elif item == 'message': # Prepare message specific fields re = 'Re: ' title = 'Message' id = self.message['id'] author = " Author: %s" % self.message['author'] time = " Time: %s" % format_datetime(self.message['time']) body = self.message['body'] link = req.abs_href.discussion( self.forum['id'], self.topic['id'], self.message['id']) + '#%s' % self.message['id'] # Save link for bad times. message['link'] = link else: return prefix = self.config.get('notification', 'smtp_subject_prefix') if prefix == '__default__': prefix = self.env.project_name moderators = "Moderators: %s" % ' '.join(self.forum['moderators']) subject = self.topic['subject'] # Set set e-mail template values. self.hdf.set_unescaped('discussion.re', re) self.hdf.set_unescaped('discussion.prefix', prefix) self.hdf.set_unescaped('discussion.title', title) self.hdf.set_unescaped('discussion.id', id) self.hdf.set_unescaped('discussion.author', author) self.hdf.set_unescaped('discussion.time', time) self.hdf.set_unescaped('discussion.moderators', moderators) self.hdf.set_unescaped('discussion.subject', subject) self.hdf.set_unescaped('discussion.body', body) self.hdf.set_unescaped('discussion.link', link) self.hdf.set_unescaped('discussion.project_name', self.env.project_name) self.hdf.set_unescaped('discussion.project_description', self.env.project_description) self.hdf.set_unescaped('discussion.project_url', self.env.project_url) # Render body and send notification. subject = to_unicode(self.hdf.render('discussion-notify-subject.cs')) NotifyEmail.notify(self, id, subject)
def __init__(self, env): NotifyEmail.__init__(self, env) self.cronconf = CronConfig(self.env)
def __init__(self, env): NotifyEmail.__init__(self, env) # Override the template type to always use NewTextTemplate if not isinstance(self.template, NewTextTemplate): self.template = Chrome(env).templates.load(self.template.filepath, cls=NewTextTemplate)
def __init__(self, env): NotifyEmail.__init__(self, env) self.prev_cc = []
def __init__(self, env, project, authname): NotifyEmail.__init__(self, env) self.from_email = env.config.get('notification', 'smtp_from') self.user = get_userstore().getUser(authname) self.data = {'_project_': project}
def __init__(self, env, milestone): NotifyEmail.__init__(self, env) self.milestone = milestone
def notify(self, ticket, newticket=True, modtime=0): self.ticket = ticket self.modtime = modtime self.newticket = newticket self.ticket['description'] = wrap(self.ticket.values.get( 'description', ''), self.COLS, initial_indent=' ', subsequent_indent=' ', linesep=CRLF) self.reporter = '' self.owner = '' self.hdf.set_unescaped('email.ticket_props', self.format_props()) self.hdf.set_unescaped('email.ticket_body_hdr', self.format_hdr()) self.hdf['ticket.new'] = self.newticket subject = self.format_subj() link = self.env.abs_href.ticket(ticket.id) if not self.newticket: subject = 'Re: ' + subject self.hdf.set_unescaped('email.subject', subject) changes = '' if not self.newticket and modtime: # Ticket change from trac.ticket.web_ui import TicketModule for change in TicketModule(self.env).grouped_changelog_entries( ticket, self.db, when=modtime): if not change['permanent']: # attachment with same time... continue self.hdf.set_unescaped('ticket.change.author', change['author']) self.hdf.set_unescaped( 'ticket.change.comment', wrap(change['comment'], self.COLS, ' ', ' ', CRLF)) link += '#comment:%s' % str(change.get('cnum', '')) for field, values in change['fields'].iteritems(): old = values['old'] new = values['new'] pfx = 'ticket.change.%s' % field newv = '' if field == 'description': new_descr = wrap(new, self.COLS, ' ', ' ', CRLF) old_descr = wrap(old, self.COLS, '> ', '> ', CRLF) old_descr = old_descr.replace(2 * CRLF, CRLF + '>' + CRLF) cdescr = CRLF cdescr += 'Old description:' + 2 * CRLF + old_descr + 2 * CRLF cdescr += 'New description:' + 2 * CRLF + new_descr + CRLF self.hdf.set_unescaped('email.changes_descr', cdescr) elif field == 'cc': (addcc, delcc) = self.diff_cc(old, new) chgcc = '' if delcc: chgcc += wrap( " * cc: %s (removed)" % ', '.join(delcc), self.COLS, ' ', ' ', CRLF) chgcc += CRLF if addcc: chgcc += wrap( " * cc: %s (added)" % ', '.join(addcc), self.COLS, ' ', ' ', CRLF) chgcc += CRLF if chgcc: changes += chgcc self.prev_cc += old and self.parse_cc(old) or [] else: newv = new l = 7 + len(field) chg = wrap('%s => %s' % (old, new), self.COLS - l, '', l * ' ', CRLF) changes += ' * %s: %s%s' % (field, chg, CRLF) if newv: self.hdf.set_unescaped('%s.oldvalue' % pfx, old) self.hdf.set_unescaped('%s.newvalue' % pfx, newv) if changes: self.hdf.set_unescaped('email.changes_body', changes) self.ticket['link'] = link self.hdf.set_unescaped('ticket', self.ticket.values) NotifyEmail.notify(self, ticket.id, subject)
def __init__(self, env): NotifyEmail.__init__(self, env) self.hdf = HDFWrapper(loadpaths=self.get_templates_dirs()) populate_hdf(self.hdf, env)
def _generic_notify(self, relation, deleted): self.data.update(dict( created=not deleted, relation=relation, )) NotifyEmail.notify(self, '', '', '')
def __init__(self, env, template_name, recipients, data): self.template_name = template_name self._recipients = recipients NotifyEmail.__init__(self, env) self.data.update(data)
def __init__(self, env): NotifyEmail.__init__(self, env) self.from_name = self.config.get('wiki-notification', 'from_name') self.banned_addresses = self.config.getlist('wiki-notification', 'banned_addresses')
def send(self, torcpts, ccrcpts): return NotifyEmail.send(self, torcpts, ccrcpts)
def send(self, torcpts, ccrcpts): """ Override NotifyEmail.send() so we can provide from_name. """ self.from_name = self.comment_author NotifyEmail.send(self, torcpts, ccrcpts)
def _notify(self, ticket, newticket=True, modtime=None): self.ticket = ticket self.modtime = modtime self.newticket = newticket changes_body = '' self.reporter = '' self.owner = '' changes_descr = '' change_data = {} link = self.env.abs_href.ticket(ticket.id) summary = self.ticket['summary'] author = None if not self.newticket and modtime: # Ticket change from trac.ticket.web_ui import TicketModule for change in TicketModule(self.env).grouped_changelog_entries( ticket, when=modtime): if not change['permanent']: # attachment with same time... continue author = change['author'] change_data.update({ 'author': self.obfuscate_email(author), 'comment': wrap(change['comment'], self.COLS, ' ', ' ', '\n', self.ambiwidth) }) link += '#comment:%s' % str(change.get('cnum', '')) for field, values in change['fields'].iteritems(): old = values['old'] new = values['new'] newv = '' if field == 'description': new_descr = wrap(new, self.COLS, ' ', ' ', '\n', self.ambiwidth) old_descr = wrap(old, self.COLS, '> ', '> ', '\n', self.ambiwidth) old_descr = old_descr.replace(2 * '\n', '\n' + '>' + \ '\n') cdescr = '\n' cdescr += 'Old description:' + 2 * '\n' + old_descr + \ 2 * '\n' cdescr += 'New description:' + 2 * '\n' + new_descr + \ '\n' changes_descr = cdescr elif field == 'summary': summary = "%s (was: %s)" % (new, old) elif field == 'cc': (addcc, delcc) = self.diff_cc(old, new) chgcc = '' if delcc: chgcc += wrap( " * cc: %s (removed)" % ', '.join(delcc), self.COLS, ' ', ' ', '\n', self.ambiwidth) + '\n' if addcc: chgcc += wrap( " * cc: %s (added)" % ', '.join(addcc), self.COLS, ' ', ' ', '\n', self.ambiwidth) + '\n' if chgcc: changes_body += chgcc self.prev_cc += self.parse_cc(old) if old else [] else: if field in ['owner', 'reporter']: old = self.obfuscate_email(old) new = self.obfuscate_email(new) newv = new length = 7 + len(field) spacer_old, spacer_new = ' ', ' ' if len(old + new) + length > self.COLS: length = 5 if len(old) + length > self.COLS: spacer_old = '\n' if len(new) + length > self.COLS: spacer_new = '\n' chg = '* %s: %s%s%s=>%s%s' % (field, spacer_old, old, spacer_old, spacer_new, new) chg = chg.replace('\n', '\n' + length * ' ') chg = wrap(chg, self.COLS, '', length * ' ', '\n', self.ambiwidth) changes_body += ' %s%s' % (chg, '\n') if newv: change_data[field] = {'oldvalue': old, 'newvalue': new} if newticket: author = ticket['reporter'] ticket_values = ticket.values.copy() ticket_values['id'] = ticket.id ticket_values['description'] = wrap(ticket_values.get( 'description', ''), self.COLS, initial_indent=' ', subsequent_indent=' ', linesep='\n', ambiwidth=self.ambiwidth) ticket_values['new'] = self.newticket ticket_values['link'] = link subject = self.format_subj(summary) if not self.newticket: subject = 'Re: ' + subject self.data.update({ 'ticket_props': self.format_props(), 'ticket_body_hdr': self.format_hdr(), 'subject': subject, 'ticket': ticket_values, 'changes_body': changes_body, 'changes_descr': changes_descr, 'change': change_data }) NotifyEmail.notify(self, ticket.id, subject, author)