= Notification Customizations [[PageOutline(2)]] TracNotification customizations can often be implemented with a short plugin. Some custom examples are given on this page. Trac >= 1.2 is needed for all of these examples. == Add or change email header Some projects like to add or change special email headers to notification emails. For example by default Trac sends notifications with email header `Precedence: bulk`, but some projects prefer to use `Precedence: list`: 1. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailDecorator IEmailDecorator]: {{{#!python # -*- coding: utf-8 -*- # # Copyright (C) 2017 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. from trac.core import Component, implements from trac.notification.api import IEmailDecorator from trac.notification.mail import set_header class ListPrecedenceEmailDecorator(Component): implements(IEmailDecorator) # IEmailDecorator methods def decorate_message(self, event, message, charset): set_header(message, 'Precedence', 'list', charset) }}} See also: #7499 == Add ticket fields to email headers Some projects need email headers with the current or changed values of ticket fields: 1. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailDecorator IEmailDecorator]: {{{#!python # -*- coding: utf-8 -*- # # Copyright (C) 2017 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. from trac.config import ListOption from trac.core import Component, implements from trac.notification.api import IEmailDecorator from trac.notification.mail import set_header class TicketFieldEmailDecorator(Component): implements(IEmailDecorator) smtp_x_trac_ticket_headers = ListOption('notification', 'smtp_x_trac_ticket_headers', 'CHANGED', doc="""Possible values: ''ALL'', ''CHANGED'' or comma-separated list of ticket properties. Those properties are put into the e-mail headers when notifying about ticket updates.""") # IEmailDecorator methods def decorate_message(self, event, message, charset): if event.realm != 'ticket' or event.category == 'batchmodify': return def header(value, *parts): name = '-'.join(part.capitalize() for part in parts) set_header(message, name, value, charset) fields = list(self.smtp_x_trac_ticket_headers) prefix = 'X-Trac-Ticket' if fields == ['CHANGED']: for item, change in event.changes['fields'].iteritems(): for type, value in change.iteritems(): header(value, prefix, item, type) elif fields == ['ALL']: for item in event.target.values: header(event.target.values[item], prefix, item) else: for item in fields: if item in event.target.values: header(event.target.values[item], prefix, item) }}} 1. Set the configuration `[notification] smtp_x_trac_ticket_headers` to `ALL` or to a list of ticket field names. See also: #6516 == Attachments in Notification Emails This email decorator can be used to send new ticket attachments as email attachments with the notification emails. 1. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailDecorator IEmailDecorator]: {{{#!python # -*- coding: utf-8 -*- # # Copyright (C) 2017 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. from email.mime.application import MIMEApplication from trac.core import Component, implements from trac.notification.api import IEmailDecorator class AttachmentEmailDecorator(Component): implements(IEmailDecorator) # IEmailDecorator methods def decorate_message(self, event, message, charset): if event.category == 'attachment added': attachment = event.attachment filename = attachment.filename with attachment.open() as fd: part = MIMEApplication(fd.read(), Name=filename) part['Content-Disposition'] = 'attachment; filename="%s"' % filename message.attach(part) }}} See also: #3054 == Reply-To Ticket Owner Some projects want to replies to ticket email notifications to be directly sent to the ticket owner's email address. 1. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailDecorator IEmailDecorator]: {{{#!python # -*- coding: utf-8 -*- # # Copyright (C) 2017 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. from trac.core import Component, implements from trac.notification.api import IEmailDecorator from trac.notification.mail import RecipientMatcher, set_header class ReplyToTicketOwnerEmailDecorator(Component): """Use the ticket owner in the Reply-To header in notification emails.""" implements(IEmailDecorator) def decorate_message(self, event, message, charset): if event.realm != 'ticket': return owner = event.target['owner'] matcher = RecipientMatcher(self.env) owner = matcher.match_from_author(owner) if owner: set_header(message, 'Reply-To', owner, charset) }}} ==== Variations * Reply to ticket ''updater'' by changing `event.target['owner']` to `event.author`. ---- See also: #6789, #10578 == Reply-To Ticket Notification Emails th:EmailtoTracScript and a small plugin to change the Reply-To address allow users to reply directly to notification emails to append comments to a ticket. The Reply-To header is changed depending on the ticket id so replies are sent to for example `10044@trac-hacks.org` and can be appended to ticket [th:ticket:10044 #10044]: 1. Create a [TracDev/PluginDevelopment#Singlefileplugins single file plugin] that implements [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailDecorator IEmailDecorator]: {{{#!python # -*- coding: utf-8 -*- # # Copyright (C) 2017 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. from trac.core import Component, implements from trac.config import Option from trac.notification.api import IEmailDecorator from trac.notification.mail import set_header class ReplyToTicketDecorator(Component): """Replaces the 'Reply-To' header for tickets with a dynamic email address. Uses a new config option 'ticket_smtp_replyto'. """ implements(IEmailDecorator) ticket_smtp_replyto = Option('notification', 'ticket_smtp_replyto', '__id__@localhost', """Reply-To address for ticket notification emails. ` __id__` is replaced with the ticket id.""") def decorate_message(self, event, message, charset): if event.realm == 'ticket': replyto = self.ticket_email_replyto.replace('__id__', str(event.target.id)) set_header(message, 'Reply-To', replyto, charset) }}} 1. Install and configure th:EmailtoTracScript. See also: th:EmailtoTracScript, th:comment:4:ticket:10044