Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
    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()
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
    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('*****@*****.**'))
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
 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é <*****@*****.**>'))
Ejemplo n.º 8
0
 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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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'))
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
    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'))
Ejemplo n.º 15
0
    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('*****@*****.**'))
Ejemplo n.º 16
0
 def test_match_recipient_anonymous(self):
     matcher = RecipientMatcher(self.env)
     self.assertEqual(None, matcher.match_recipient('anonymous'))
Ejemplo n.º 17
0
 def test_match_recipient_empty(self):
     matcher = RecipientMatcher(self.env)
     self.assertEqual(None, matcher.match_recipient(None))
     self.assertEqual(None, matcher.match_recipient(u''))