def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return ticket = event.target owners = [ticket['owner']] # Harvest previous owner if 'fields' in event.changes and 'owner' in event.changes['fields']: owners.append(event.changes['fields']['owner']['old']) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for owner in owners: recipient = matcher.match_recipient(owner) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category == 'batchmodify': for ticket_event in event.get_ticket_change_events(self.env): for m in self.matches(ticket_event): yield m return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return ticket = event.target matcher = RecipientMatcher(self.env) recipient = matcher.match_recipient(ticket['reporter']) if not recipient: return sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield (s[0], s[1], sid, auth, addr, s[2], s[3], s[4]) if sid: klass = self.__class__.__name__ for s in Subscription.find_by_sids_and_class( self.env, ((sid, auth), ), klass): yield s.subscription_tuple()
def _ticket_change_subscribers(subscriber, candidates): if not candidates: return if not isinstance(candidates, (list, set, tuple)): candidates = [candidates] # Get members of permission groups groups = PermissionSystem(subscriber.env).get_groups_dict() for cc in set(candidates): if cc in groups: candidates.remove(cc) candidates.update(groups[cc]) matcher = RecipientMatcher(subscriber.env) klass = subscriber.__class__.__name__ sids = set() for candidate in candidates: recipient = matcher.match_recipient(candidate) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in subscriber.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(subscriber.env, sids, klass): yield s.subscription_tuple()
def test_match_recipient_ignore_domains(self): self.config.set('notification', 'ignore_domains', 'example.net,example.com') with self.env.db_transaction: self._add_session('user1', email='*****@*****.**') self._add_session('user2', email='*****@*****.**') self._add_session('user3', email='*****@*****.**') self._add_session('*****@*****.**') self._add_session('*****@*****.**') self._add_session('*****@*****.**') matcher = RecipientMatcher(self.env) # authenticated users self.assertEqual(('user1', 1, '*****@*****.**'), matcher.match_recipient('user1')) self.assertEqual(None, matcher.match_recipient('user2')) self.assertEqual(None, matcher.match_recipient('user3')) self.assertEqual(('*****@*****.**', 1, '*****@*****.**'), matcher.match_recipient('*****@*****.**')) self.assertEqual(None, matcher.match_recipient('*****@*****.**')) self.assertEqual(None, matcher.match_recipient('*****@*****.**')) # anonymous users self.assertEqual((None, 0, '*****@*****.**'), matcher.match_recipient('*****@*****.**')) self.assertEqual(None, matcher.match_recipient('*****@*****.**')) self.assertEqual(None, matcher.match_recipient('*****@*****.**'))
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return updaters = [ row[0] for row in self.env.db_query( """ SELECT DISTINCT author FROM ticket_change WHERE ticket=%s """, (event.target.id, )) ] matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for previous_updater in updaters: if previous_updater == event.author: continue recipient = matcher.match_recipient(previous_updater) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return # CC field is stored as comma-separated string. Parse to set. chrome = Chrome(self.env) to_set = lambda cc: set(chrome.cc_list(cc)) cc_set = to_set(event.target['cc'] or '') # Harvest previous CC field if 'fields' in event.changes and 'cc' in event.changes['fields']: cc_set.update(to_set(event.changes['fields']['cc']['old'])) matcher = RecipientMatcher(self.env) klass = self.__class__.__name__ sids = set() for cc in cc_set: recipient = matcher.match_recipient(cc) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(self.env, sids, klass): yield s.subscription_tuple()
def test_match_recipient_address(self): matcher = RecipientMatcher(self.env) expected = (None, 0, '*****@*****.**') self.assertEqual(expected, matcher.match_recipient('*****@*****.**')) self.assertEqual(expected, matcher.match_recipient('<*****@*****.**>')) self.assertEqual(expected, matcher.match_recipient( 'Name name <*****@*****.**>')) self.assertEqual(expected, matcher.match_recipient( u'Námë ńämé <*****@*****.**>'))
def decorate_message(self, event, message, charset): if event.realm != 'ticket': return from_email = self._get_from_email(event) if event.category == 'batchmodify': tickets = sort_tickets_by_priority(self.env, event.target) subject = self._format_subj_batchmodify(tickets) targetid = ','.join(map(str, tickets)) msgid = self._get_message_id(targetid, from_email, event.time) else: subject = self._format_subj(event) ticket = event.target targetid = '%08d' % ticket.id more = ticket['reporter'] or '' msgid = self._get_message_id(targetid, from_email, None, more) url = self.env.abs_href.ticket(ticket.id) if event.category != 'created': set_header(message, 'In-Reply-To', msgid, charset) set_header(message, 'References', msgid, charset) msgid = self._get_message_id(targetid, from_email, event.time, more) cnum = ticket.get_comment_number(event.time) if cnum is not None: url += '#comment:%d' % cnum set_header(message, 'X-Trac-Ticket-ID', ticket.id, charset) set_header(message, 'X-Trac-Ticket-URL', url, charset) # When owner, reporter and updater are listed in the Cc header, # move the address to To header. if NotificationSystem(self.env).use_public_cc: to_addrs = set() matcher = RecipientMatcher(self.env) for rcpt in ticket['owner'], ticket['reporter'], event.author: rcpt = matcher.match_recipient(rcpt) if not rcpt: continue addr = rcpt[2] if addr: to_addrs.add(addr) if to_addrs: cc_addrs = get_message_addresses(message, 'Cc') to_addrs &= set(addr for name, addr in cc_addrs) if to_addrs: cc_header = ', '.join(create_header('Cc', (name, addr), charset) for name, addr in cc_addrs if addr not in to_addrs) if cc_header: set_header(message, 'Cc', cc_header, charset) elif 'Cc' in message: del message['Cc'] to_header = ', '.join(sorted(to_addrs)) set_header(message, 'To', to_header, charset) set_header(message, 'Subject', subject, charset) set_header(message, 'Message-ID', msgid, charset)
def __init__(self, env): super(NotifyEmail, self).__init__(env) self.recipient_matcher = RecipientMatcher(env) self.shortaddr_re = self.recipient_matcher.shortaddr_re self.longaddr_re = self.recipient_matcher.longaddr_re self._ignore_domains = self.recipient_matcher.ignore_domains self.name_map = self.recipient_matcher.name_map self.email_map = self.recipient_matcher.email_map notify_sys = NotificationSystem(self.env) self._charset = create_charset(notify_sys.mime_encoding)
def __init__(self, env): super(NotifyEmail, self).__init__(env) self.recipient_matcher = RecipientMatcher(env) self.shortaddr_re = self.recipient_matcher.shortaddr_re self.longaddr_re = self.recipient_matcher.longaddr_re self._ignore_domains = self.recipient_matcher.ignore_domains self.name_map = {} self.email_map = {} for username, name, email in self.env.get_known_users(): if name: self.name_map[username] = name if email: self.email_map[username] = email notify_sys = NotificationSystem(self.env) self._charset = create_charset(notify_sys.mime_encoding)
def test_match_recipient_use_short_addr(self): self.config.set('notification', 'use_short_addr', 'enabled') with self.env.db_transaction: self._add_session('user1') self._add_session('user2', email='user2-email') self._add_session('user3', email='*****@*****.**') self._add_session('*****@*****.**', email='user4') matcher = RecipientMatcher(self.env) self.assertEqual(('user1', 1, 'user1'), matcher.match_recipient('user1')) self.assertEqual(('user2', 1, 'user2-email'), matcher.match_recipient('user2')) self.assertEqual(('user3', 1, '*****@*****.**'), matcher.match_recipient('user3')) self.assertEqual(('*****@*****.**', 1, 'user4'), matcher.match_recipient('*****@*****.**')) self.assertEqual((None, 0, 'user9'), matcher.match_recipient('user9'))
def _ticket_change_subscribers(subscriber, candidates): if not candidates: return if not isinstance(candidates, (list, set, tuple)): candidates = [candidates] matcher = RecipientMatcher(subscriber.env) klass = subscriber.__class__.__name__ sids = set() for candidate in candidates: recipient = matcher.match_recipient(candidate) if not recipient: continue sid, auth, addr = recipient # Default subscription for s in subscriber.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: sids.add((sid, auth)) for s in Subscription.find_by_sids_and_class(subscriber.env, sids, klass): yield s.subscription_tuple()
def matches(self, event): if event.realm != 'ticket': return if event.category not in ('created', 'changed', 'attachment added', 'attachment deleted'): return matcher = RecipientMatcher(self.env) recipient = matcher.match_recipient(event.author) if not recipient: return sid, auth, addr = recipient # Default subscription for s in self.default_subscriptions(): yield s[0], s[1], sid, auth, addr, s[2], s[3], s[4] if sid: klass = self.__class__.__name__ for s in Subscription \ .find_by_sids_and_class(self.env, ((sid, auth),), klass): yield s.subscription_tuple()
def test_match_recipient_smtp_default_domain(self): self.config.set('notification', 'smtp_default_domain', 'default.example.net') with self.env.db_transaction: self._add_session('user1') self._add_session('user2', email='user2-email') self._add_session('user3', email='*****@*****.**') self._add_session('*****@*****.**', email='user4') self._add_session('*****@*****.**') matcher = RecipientMatcher(self.env) self.assertEqual(('user1', 1, '*****@*****.**'), matcher.match_recipient('user1')) self.assertEqual(('user2', 1, '*****@*****.**'), matcher.match_recipient('user2')) self.assertEqual(('user3', 1, '*****@*****.**'), matcher.match_recipient('user3')) self.assertEqual(('*****@*****.**', 1, '*****@*****.**'), matcher.match_recipient('*****@*****.**')) self.assertEqual(('*****@*****.**', 1, '*****@*****.**'), matcher.match_recipient('*****@*****.**')) self.assertEqual((None, 0, '*****@*****.**'), matcher.match_recipient('user9'))
def test_match_recipient_admit_domains(self): self.config.set('notification', 'admit_domains', 'LOCALDOMAIN') with self.env.db_transaction: self._add_session('user1', email='user1@localhost') self._add_session('user2', email='user2@localdomain') self._add_session('user3', email='*****@*****.**') self._add_session('user4@localhost') self._add_session('user5@localdomain') self._add_session('*****@*****.**') self._add_session('user7@localhost', email='*****@*****.**') self._add_session('user8@localdomain', email='user8@localhost') self._add_session('*****@*****.**', email='user9@localdomain') matcher = RecipientMatcher(self.env) # authenticated users self.assertEqual(None, matcher.match_recipient('user1')) self.assertEqual(('user2', 1, 'user2@localdomain'), matcher.match_recipient('user2')) self.assertEqual(('user3', 1, '*****@*****.**'), matcher.match_recipient('user3')) self.assertEqual(None, matcher.match_recipient('user4@localhost')) self.assertEqual(('user5@localdomain', 1, 'user5@localdomain'), matcher.match_recipient('user5@localdomain')) self.assertEqual(('*****@*****.**', 1, '*****@*****.**'), matcher.match_recipient('*****@*****.**')) self.assertEqual(('user7@localhost', 1, '*****@*****.**'), matcher.match_recipient('user7@localhost')) self.assertEqual(None, matcher.match_recipient('user8@localdomain')) self.assertEqual(('*****@*****.**', 1, 'user9@localdomain'), matcher.match_recipient('*****@*****.**')) # anonymous users self.assertEqual(None, matcher.match_recipient('foobar')) self.assertEqual(None, matcher.match_recipient('anon@localhost')) self.assertEqual((None, 0, 'anon@localdomain'), matcher.match_recipient('anon@localdomain')) self.assertEqual((None, 0, '*****@*****.**'), matcher.match_recipient('*****@*****.**'))
def test_match_recipient_anonymous(self): matcher = RecipientMatcher(self.env) self.assertEqual(None, matcher.match_recipient('anonymous'))
def test_match_recipient_empty(self): matcher = RecipientMatcher(self.env) self.assertEqual(None, matcher.match_recipient(None)) self.assertEqual(None, matcher.match_recipient(u''))