def test_post_to_private_list_accepted_members(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="MEMBERS")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=True)
     PermissionCache(self.env, 'sparrowj',
                     mailinglist.resource).assert_permission('MAILINGLIST_POST')
 def test_post_to_private_list_denied_restricted_nonmember(self):
     """Non-posting member of this list."""        
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="RESTRICTED")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=False)
     PermissionCache(self.env, 'smithj',
                     mailinglist.resource).assert_permission('MAILINGLIST_POST')
 def test_adding_lists(self):
     for i in range(0,10):
         mailinglist = Mailinglist(self.env,
                                   emailaddress="list%s" % i, name="Sample List", private=True,
                                   postperm="OPEN")
         mailinglist.insert()
         assert mailinglist.addr()
         assert mailinglist.addr(bounce=True)            
 def test_post_to_private_list_accepted_members_group(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="MEMBERS")
     mailinglist.insert()
     PermissionSystem(self.env).grant_permission('sparrowj', 'group1')
     PermissionSystem(self.env).grant_permission('smithj', 'group1')        
     mailinglist.subscribe(group="group1", poster=True)
     PermissionCache(self.env, 'sparrowj',
                     mailinglist.resource).assert_permission('MAILINGLIST_POST')
 def test_load_list(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="list", name="Sample List", private=True,
                               postperm="OPEN")
     assert mailinglist.id is None
     mailinglist.insert()
     assert mailinglist.id is not None
     found = Mailinglist(self.env, mailinglist.id)
     assert found.id is mailinglist.id
 def test_update_private(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="list", name="Sample List", private=True,
                               postperm="OPEN")
     assert mailinglist.private == True
     newid = mailinglist.insert()
     mailinglist.private = False
     mailinglist.save_changes()
     assert Mailinglist(self.env, newid).private is False
 def test_removing_lists(self):
     l = []
     for i in range(0,10):
         mailinglist = Mailinglist(self.env,
                                   emailaddress="list%s" % i, name="Sample List", private=True,
                                   postperm="OPEN")
         mailinglist.insert()
         l.append(mailinglist.id)
         
     for i in l:
         Mailinglist(self.env, i).delete()
    def import_mailinglist(self, template_path):
        """Creates project mailing lists from mailinglist.xml template file."""

        path = os.path.join(template_path, 'mailinglist.xml')
        try:
            tree = ET.ElementTree(file=path)
            for ml in tree.getroot():
                mailinglist = Mailinglist(self.env, emailaddress=ml.attrib['email'],
                                               name=ml.attrib['name'],
                                               description=ml.text,
                                               private=ml.attrib['private'],
                                               postperm=ml.attrib['postperm'],
                                               replyto=ml.attrib['replyto'])
                mailinglist.insert()
        except IOError as exception:
            if exception.errno == errno.ENOENT:
                self.log.info("Path to mailinglist.xml at %s does not exist. "
                              "Unable to import mailing lists from template.", path)
 def test_post_to_private_list_accepted_restricted(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="RESTRICTED")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=False)        
     mailinglist.subscribe(user="******", poster=True)
     PermissionCache(self.env, 'sparrowj',
                     mailinglist.resource).assert_permission('MAILINGLIST_POST')
 def test_read_private_list_denied(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="RESTRICTED")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=False)        
     mailinglist.subscribe(user="******", poster=True)
     PermissionCache(self.env, 'randomuser',
                     mailinglist.resource).assert_permission('MAILINGLIST_VIEW')
 def test_read_nonprivate_list_denied(self):
     # not a private list, but in general the user isn't allowed to
     # view mailing lists (e.g., not a member of this project at all.)
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=False, postperm="RESTRICTED")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=False)        
     mailinglist.subscribe(user="******", poster=True)
     PermissionCache(self.env, 'randomuser',
                     mailinglist.resource).assert_permission('MAILINGLIST_VIEW')
 def test_read_nonprivate_list_accepted(self):
     PermissionSystem(self.env).grant_permission('members', 'MAILINGLIST_VIEW')
     PermissionSystem(self.env).grant_permission('randomuser', 'members')
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=False, postperm="RESTRICTED")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=False)        
     mailinglist.subscribe(user="******", poster=True)
     PermissionCache(self.env, 'randomuser',
                     mailinglist.resource).assert_permission('MAILINGLIST_VIEW')
 def read_file(self, mbox_file, metadata=None):
     mailinglist_name = os.path.basename(mbox_file).rstrip('mbox.gz')
     if not metadata:
         metadata = dict(emailaddress=mailinglist_name,
                         name='%s (Imported)' % mailinglist_name,
                         private=True,
                         postperm='MEMBERS',
                         replyto='LIST',
                         date=datetime.utcnow(),
                         individuals=[],
                         groups=[],
                         declines=[])
     individuals = metadata.pop('individuals')
     groups = metadata.pop('groups')
     declines = metadata.pop('declines')
     try:
         mailinglist = Mailinglist.select_by_address(self.env, mailinglist_name, localpart=True)
     except ResourceNotFound:
         mailinglist = Mailinglist(self.env, **metadata)
         try:
             mailinglist.insert()
         except Exception, e:
             self.log.exception(metadata)
             raise
 def do_update(db):
     mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                 localpart=True, db=db)
     if req.args.get('updatepostergroups'):
         current_statuses =  mailinglist.groups()
     else:
         current_statuses =  mailinglist.individuals()
     for subname, poster in current_statuses:
         if req.args.get('updatepostergroups'):                            
             updater = partial(mailinglist.update_poster, group=subname)
         else:
             updater = partial(mailinglist.update_poster, user=subname)                            
         if poster and subname not in sel:
             updater(poster=False)
         elif not poster and subname in sel:
             updater(poster=True)
 def get_instance_for_resource(self, resource):
     if resource.realm != "mailinglist":
         return None
     parts = resource.id.split("/")
     if len(parts) == 0:
         return None
     elif len(parts) == 1:
         from mailinglistplugin.model import Mailinglist
         return Mailinglist.select_by_address(self.env, parts[0], localpart=True)
     elif len(parts) == 2:
         from mailinglistplugin.model import MailinglistConversation
         return MailinglistConversation(self.env, int(parts[1]))
     elif len(parts) == 3:
         if parts[2] == "raw":
             from mailinglistplugin.model import MailinglistRawMessage
             return MailinglistRawMessage(self.env, int(parts[2]))
         else:
             from mailinglistplugin.model import MailinglistMessage
             return MailinglistMessage(self.env, int(parts[2]))
    def get_timeline_events(self, req, start, stop, filters):
        if 'mailinglist' in filters:
            mailinglist_realm = Resource('mailinglist')

            lists = {}
            for mailinglist in Mailinglist.select(self.env):
                if "MAILINGLIST_VIEW" in req.perm(mailinglist.resource):         
                    lists[mailinglist.id] = mailinglist

            if not lists:
                self.log.debug("This user can't view any lists, so not listing timeline events.")
                return

            self.log.debug("Searching for timeline events in %s", lists)

            db = self.env.get_read_db()

            cursor = db.cursor()
            cursor.execute("SELECT id, subject, body, from_name, from_email, date, list, conversation "
                           "FROM mailinglistmessages "
                           "WHERE date>=%%s AND date<=%%s AND list IN (%s)" % ",".join(map(str,lists.keys())),
                           (to_timestamp(start), to_timestamp(stop)))
            # 
            for mid, subject, body, from_name, from_email, date, mlist, conversation in cursor:
                # build resource ourself to speed things up
                m = mailinglist_realm(id="%s/%d/%d" % (lists[mlist].emailaddress,
                                                       conversation,
                                                       mid))
                if 'MAILINGLIST_VIEW' in req.perm(m):
                    yield ('mailinglist', 
                           datetime.fromtimestamp(date, utc),
                           "%s" % (from_name,),
                           (mid,
                            subject, 
                            body.lstrip()[:200],
                            lists[mlist].name, 
                            lists[mlist].emailaddress, 
                            conversation))

            # Attachments
            for event in AttachmentModule(self.env).get_timeline_events(
                req, mailinglist_realm, start, stop):
                yield event
    def get_search_results(self, req, terms, filters):
        if not 'mailinglist' in filters:
            return
        mailinglist_realm = Resource('mailinglist')

        lists = {}
        for mailinglist in Mailinglist.select(self.env):
            if "MAILINGLIST_VIEW" in req.perm(mailinglist.resource):         
                lists[mailinglist.id] = mailinglist
                
        if not lists:
            self.log.debug("This user can't view any lists, so not searching.")
            return
        
        db = self.env.get_read_db()
        sql, args = search_to_sql(db, ['subject','body','from_email','from_name'], terms)

        cursor = db.cursor()
        query = """
            SELECT id, subject, body, from_name, from_email, date, list, conversation
            FROM mailinglistmessages
            WHERE list IN (%s) AND %s
            """ % (",".join(map(str,lists.keys())), sql,)
        self.log.debug("Search query: %s", query)
        cursor.execute(query, args)
        for mid, subject, body, from_name, from_email, date, mlist, conversation in cursor:
            # build resource ourself to speed things up
            m = mailinglist_realm(id="%s/%d/%d" % (lists[mlist].emailaddress,
                                                   conversation,
                                                   mid))
            if 'MAILINGLIST_VIEW' in req.perm(m):
                yield (req.href.mailinglist(m.id),
                       tag("%s: %s" % (lists[mlist].name, subject)),
                       datetime.fromtimestamp(date, utc),
                       "%s <%s>" % (from_name, from_email),
                       shorten_result(body, terms))
        
        # Attachments
        for result in AttachmentModule(self.env).get_search_results(
            req, mailinglist_realm, terms):
            yield result        
    def export_mailinglists(self, template_path):
        """Exports project mailing lists into mailinglist.xml"""

        # a list to return to the template with info about transaction
        successful_exports = list()

        self.log.info("Creating mailing list XML file for template archive")
        root = ET.Element("lists", project=self.env.project_name, date=datetime.date.today().isoformat())
        for ml in Mailinglist.select(self.env):
            ET.SubElement(root, "list_info", name=ml.name,
                                             email=ml.emailaddress,
                                             private=str(ml.private),
                                             postperm=ml.postperm,
                                             replyto=ml.replyto).text = ml.description
            successful_exports.append(ml.name)

        # save the xml file
        filename = os.path.join(template_path, 'mailinglist.xml')
        ET.ElementTree(root).write(filename)
        self.log.info("File %s has been created at %s" % (filename, template_path))

        return successful_exports
 def test_add_message_with_attachment(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", name="Sample List 1", private=True,
                               postperm="OPEN")
     mailinglist.insert()
     
     mailinglist.insert_raw_email(raw_message_with_attachment % dict(sender="Jack Sparrow",
                                                                     email="*****@*****.**",
                                                                     list="list1",
                                                                     domain="example.com",
                                                                     subject="Boats",
                                                                     asctime=time.asctime(),
                                                                     id="asdfasdf",
                                                                     body="Need images of boats."))
     
     message = mailinglist.conversations().next().messages().next()
     attachment_path = Attachment.select(self.env, message.resource.realm, message.resource.id).next().path
     assert os.path.exists(attachment_path)        
     message.delete()
     assert not os.path.exists(attachment_path)
    def import_project(self, sourcepath, destinationpath, name=None, **kwargs):

        if name is None:
            raise KeyError("This importer requires a Trac project to already exist. Use --name to specify its dir name.")
        
        env_path = os.path.join(destinationpath, name)
        mailinglist_name = os.path.basename(sourcepath.rstrip("/"))
        env = open_environment(env_path)

        #mailinglist = Mailinglist.select_by_address(env, mailinglist_name, localpart=True)
        #mailinglist.delete()

        try:
            mailinglist = Mailinglist.select_by_address(env, mailinglist_name, localpart=True)
        except ResourceNotFound:
            mailinglist = Mailinglist(env, emailaddress=mailinglist_name, name="Imported list",
                                      private=True, postperm="MEMBERS", replyto="LIST")
            mailinglist.insert()

        mbox = mailbox.Maildir(sourcepath)

        for mail in mbox:
            mail.fp.seek(0)
            mailinglist.insert_raw_email(mail.fp.read())
 def do_remove(db):
     mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                 localpart=True, db=db)
     for username in sel:
         mailinglist.unsubscribe(group=username, db=db)
 def do_subscribe(db):
     mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                 localpart=True, db=db)
     mailinglist.subscribe(group=req.args['groupname'], db=db)
    def render_admin_panel(self, req, cat, page, mailinglist_emailpart):
        req.perm.require('MAILINGLIST_ADMIN')

        if mailinglist_emailpart:
            mailinglist = Mailinglist.select_by_address(self.env,
                                                        mailinglist_emailpart,
                                                        localpart=True)
            if req.method == 'POST':
                if req.args.get('save'):
                    mailinglist.name = req.args.get('name')
                    mailinglist.private = req.args.get('private') == 'PRIVATE'
                    mailinglist.postperm = req.args.get('postperm')
                    mailinglist.replyto = req.args.get('replyto')
                    mailinglist.description = req.args.get('description')
                    if 'TRAC_ADMIN' in req.perm:
                        mailinglist.emailaddress = req.args.get('emailaddress')
                    mailinglist.save_changes()
                    add_notice(req, _('Your changes have been saved.'))
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('cancel'):
                    req.redirect(req.href.admin(cat, page))
                elif req.args.get('subscribeuser'):
                    @self.env.with_transaction()
                    def do_subscribe(db):
                        mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                                    localpart=True, db=db)
                        mailinglist.subscribe(user=req.args['username'], db=db)
                    add_notice(req, _('The user %s has been subscribed.') % req.args['username'])
                    
                    req.redirect(req.href.admin(cat, page, mailinglist_emailpart))
                elif req.args.get('removeusers'):
                    sel = req.args.get('sel')
                    if not sel:
                        raise TracError(_('No users selected'))
                    if not isinstance(sel, list):
                        sel = [sel]
                    @self.env.with_transaction()
                    def do_remove(db):
                        mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                                    localpart=True, db=db)
                        for username in sel:
                            mailinglist.unsubscribe(user=username, db=db)
                    add_notice(req, _('The selected users have been unsubscribed.'))
                    
                    req.redirect(req.href.admin(cat, page, mailinglist_emailpart))
                elif req.args.get('subscribegroup'):
                    @self.env.with_transaction()
                    def do_subscribe(db):
                        mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                                    localpart=True, db=db)
                        mailinglist.subscribe(group=req.args['groupname'], db=db)
                    add_notice(req, _('The group %s has been subscribed.') % req.args['groupname'])
                    
                    req.redirect(req.href.admin(cat, page, mailinglist_emailpart))                    
                elif req.args.get('removegroups'):
                    sel = req.args.get('sel')
                    if not sel:
                        raise TracError(_('No groups selected'))
                    if not isinstance(sel, list):
                        sel = [sel]
                    @self.env.with_transaction()
                    def do_remove(db):
                        mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                                    localpart=True, db=db)
                        for username in sel:
                            mailinglist.unsubscribe(group=username, db=db)
                    add_notice(req, _('The selected groups have been unsubscribed.'))
                    
                    req.redirect(req.href.admin(cat, page, mailinglist_emailpart))
                elif req.args.get('updatepostergroups') or req.args.get('updateposterusers'):
                    sel = req.args.get('sel')
                    if not sel:
                        sel = []
                    if not isinstance(sel, list):
                        sel = [sel]
                    @self.env.with_transaction()
                    def do_update(db):
                        mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                                    localpart=True, db=db)
                        if req.args.get('updatepostergroups'):
                            current_statuses =  mailinglist.groups()
                        else:
                            current_statuses =  mailinglist.individuals()
                        for subname, poster in current_statuses:
                            if req.args.get('updatepostergroups'):                            
                                updater = partial(mailinglist.update_poster, group=subname)
                            else:
                                updater = partial(mailinglist.update_poster, user=subname)                            
                            if poster and subname not in sel:
                                updater(poster=False)
                            elif not poster and subname in sel:
                                updater(poster=True)
                            
                    add_notice(req, _('Posters have been updated.'))
                    
                    req.redirect(req.href.admin(cat, page, mailinglist_emailpart))
                    

            Chrome(self.env).add_wiki_toolbars(req)

            if self.env.is_component_enabled('simplifiedpermissionsadminplugin.simplifiedpermissions.SimplifiedPermissions'):
                from simplifiedpermissionsadminplugin.simplifiedpermissions import SimplifiedPermissions
                # groups is used for subscription, so it should not have subscribed groups in it
                groups = set(SimplifiedPermissions(self.env).groups) - set([subscribed_group for subscribed_group, group_poster in mailinglist.groups()])
            else:
                groups = None
            
            data = {'view': 'detail',
                    'mailinglist': mailinglist,
                    'groups': groups,
                    'email_domain': MailinglistSystem(self.env).email_domain}
        else:
            if req.method == 'POST':
                if req.args.get('add') and req.args.get('emailaddress'):
                    emailaddress = req.args['emailaddress'].lower()
                    try:
                        mailinglist = Mailinglist.select_by_address(self.env, emailaddress, localpart=True)
                    except ResourceNotFound:
                        mailinglist = Mailinglist(self.env, name=req.args['name'])
                        mailinglist.private = req.args.get('private') == 'PRIVATE'
                        mailinglist.postperm = req.args.get('postperm')
                        mailinglist.replyto = req.args.get('replyto')
                        mailinglist.emailaddress = req.args.get('emailaddress')
                        mailinglist.insert()
                        add_notice(req, _('The mailinglist "%(addr)s" has been '
                                          'added.', addr=mailinglist.addr()))
                        req.redirect(req.href.admin(cat, page))
                    else:
                        raise TracError(_('Mailinglist with email address %(emailaddress)s already exists.',
                                          emailaddress=emailaddress))
                # Remove mailinglists
                elif req.args.get('remove'):
                    req.perm.require('TRAC_ADMIN')
                    sel = req.args.get('sel')
                    if not sel:
                        raise TracError(_('No mailinglist selected'))
                    if not isinstance(sel, list):
                        sel = [sel]
                    @self.env.with_transaction()
                    def do_remove(db):
                        for email in sel:
                            mailinglist = Mailinglist.select_by_address(self.env, email,
                                                                        localpart=True, db=db)
                            mailinglist.delete(db=db)
                    add_notice(req, _('The selected mailinglists have been '
                                      'removed.'))
                    req.redirect(req.href.admin(cat, page))
                    
                    
            mailinglists = Mailinglist.select(self.env)
            
            data = {'view': 'list',
                    'mailinglists': mailinglists,
                    'email_domain': MailinglistSystem(self.env).email_domain}                    
            
        return ('mailinglist_admin.html', data)
 def do_remove(db):
     for email in sel:
         mailinglist = Mailinglist.select_by_address(self.env, email,
                                                     localpart=True, db=db)
         mailinglist.delete(db=db)
    def test_add_messages(self):
        mailinglist = Mailinglist(self.env,
                                  emailaddress="LIST1", name="Sample List 1", private=True,
                                  postperm="OPEN")
        mailinglist.insert()
        mailinglist = Mailinglist(self.env,
                                  emailaddress="list2", name="Sample List 2", private=True,
                                  postperm="OPEN")
        mailinglist.insert()

        for rawmsg in rawmsgs:
            for listname in ("list1", "list2"):
                bytes = rawmsg % dict(sender="Jack Sparrow",
                                      email="*****@*****.**",
                                      list=listname,
                                      domain="example.com",
                                      subject="Boats",
                                      asctime=time.asctime(),
                                      id="asdfasdf",
                                      body="Need boats.")

                mailinglist = Mailinglist.select_by_address(self.env,
                                                            "*****@*****.**" % listname)
                message = mailinglist.insert_raw_email(bytes)
                
        assert len(list(Mailinglist.select(self.env))) == 2
        
        for mailinglist in Mailinglist.select(self.env):
            for conversation in mailinglist.conversations():
                assert conversation.get_first() is not None
                for message in conversation.messages():
                    assert message
                    #for attachment in Attachment.select(self.env, 'mailinglistmessage', message.id):
                    #    assert attachment

            mailinglist.delete()
            
        assert len(list(Mailinglist.select(self.env))) == 0
 def test_add_list_member(self):
     mailinglist = Mailinglist(self.env,
                               emailaddress="LIST1", private=True, postperm="MEMBERS")
     mailinglist.insert()
     mailinglist.subscribe(user="******", poster=True)
     assert "sparrowj" in mailinglist.subscribers()
    def test_subscribers(self):
        mailinglist = Mailinglist(self.env,
                                  emailaddress="LIST1", private=True, postperm="MEMBERS")
        mailinglist.insert()
        PermissionSystem(self.env).grant_permission('sparrowj', 'group1')
        PermissionSystem(self.env).grant_permission('smithj', 'group1')
        PermissionSystem(self.env).grant_permission('pipern', 'group2')
        mailinglist.subscribe(group="group1", poster=True)
        mailinglist.subscribe(group="group2", poster=True)
        mailinglist.unsubscribe(user="******")

        assert mailinglist.subscribers()["smithj"]['decline'] == True
        assert "sparrowj" in mailinglist.subscribers()
        assert "pipern" in mailinglist.subscribers()

        mailinglist.unsubscribe(group="group1")
        assert "sparrowj" not in mailinglist.subscribers()        
    def render_macro(self, req, name, content):
        args,kwargs = parse_args(content)
        if len(args) == 0:
            ul = tag.ul(class_="mailinglistlist")

            for mailinglist in Mailinglist.select(self.env):
                if "MAILINGLIST_VIEW" in req.perm(mailinglist.resource):         
                    ul.append(tag.li(tag.a(mailinglist.name,
                                           href=get_resource_url(self.env, mailinglist.resource, req.href))))
                        
            return ul
        if kwargs.has_key('limit'):
            limit = int(kwargs['limit'])
        elif len(args) > 1:
            limit = int(args[1])
        else:
            limit = 10
        resource = Resource("mailinglist",args[0])
        instance = MailinglistSystem(self.env).get_instance_for_resource(resource)

        if isinstance(instance, Mailinglist):
            if not req.perm(instance.resource).has_permission('MAILINGLIST_VIEW'):
                return system_message("Permission denied viewing mailinglist: %s" % instance.name)
            ul = tag.ul()
            for message in instance.messages(limit=limit, insubject=kwargs.get('insubject', None),desc=True):
                ul.append(tag.li(
                    tag.a(tag.span(message.subject, class_="messagesubject"),
                          href=get_resource_url(self.env, message.resource, req.href)),
                    " (",
                    dateinfo(message.date),
                    ")",
                    ))
            ul.append(tag.li(tag.a("(%d messages...)" % instance.count_messages(insubject=kwargs.get('insubject', None)),
                                   href=get_resource_url(self.env, instance.resource, req.href))))
            return tag.div("Mailinglist: ",
                           tag.a(instance.name,
                                 href=get_resource_url(self.env, instance.resource, req.href)),
                           ul,
                           class_="mailinglistfeed")
        elif isinstance(instance, MailinglistMessage):
            if not req.perm(instance.resource).has_permission('MAILINGLIST_VIEW'):
                return system_message("Permission denied viewing mail.")


            else:
                limit = None
            text = wrap_and_quote(instance.body, 78)[0]
            if limit:
                text = "\n".join(text.split("\n")[0:limit])
                textelement = tag.pre(text) + tag.a(tag.pre("(More...)"),
                                                    href=get_resource_url(self.env, instance.resource, req.href))
            else:
                textelement = tag.pre(text)                
            return tag.div(
                tag.div("Mailinglist: ",
                        tag.a(instance.conversation.mailinglist.name,
                              href=get_resource_url(self.env, instance.conversation.mailinglist.resource, req.href))),
                tag.div("Subject: ",
                        tag.a(instance.subject, href=get_resource_url(self.env, instance.resource, req.href))),
                tag.div("From: ",
                        tag.a(instance.from_name, href="mailto:%s" % instance.from_email)),
                tag.div("To: ", instance.to_header),
                tag.div("Date: ", dateinfo(instance.date)),
                tag.div(textelement),
                class_="mailinglistmessage")            
            
        return system_message("Unknown Mailinglist: %s" % content)
    def process_request(self, req):
        offset = req.args.get("offset",0)
        page = req.args.get('page', 1)
        try:
            offset = int(offset)
        except:
            raise TracError(_('Invalid offset used: %(offset)s', offset=offset))        
        
        try:
            page = int(page)
        except:
            raise TracError(_('Invalid page used: %(page)s', page=page))
                
        offset = (page - 1) * self.limit
        
        add_stylesheet(req, 'mailinglist/css/mailinglist.css')
        add_javascript(req, 'mailinglist/mailinglist.js')
            
        mailinglists = [m for m in Mailinglist.select(self.env)
                        if "MAILINGLIST_VIEW" in req.perm(m.resource)]

        data = {"mailinglists": mailinglists,
                "offset": offset,
                "limit": self.limit}

        if req.method == 'POST':

            if 'subscribe' in req.args:
                subscribe = True
                unsubscribe = False
                mailinglist_email = req.args.get('subscribe')
            elif 'unsubscribe' in req.args:
                subscribe = False
                unsubscribe = True
                mailinglist_email = req.args.get('unsubscribe')
            else:
                # at the moment we only post subscription info to
                # mailing list page - so if there is none in req.args we 
                # can just redirect to mailing list page
                req.redirect(req.href.mailinglist())

            # get mailing list object and check permissions
            mailinglist = Mailinglist.select_by_address(self.env,
                                                    mailinglist_email, localpart=True)
            req.perm(mailinglist.resource).require("MAILINGLIST_VIEW")

            if subscribe:
                mailinglist.subscribe(user=req.authname)
                # subscribe does not return a value to indicate if it 
                # was successful, so we have to explicitly check
                if mailinglist.is_subscribed(req.authname):
                    add_notice(req, _('You have been subscribed to %s.' % mailinglist.name))
                else:
                    add_notice(req, _('Unable to subscribe to %s.' % mailinglist.name))
            elif unsubscribe:
                mailinglist.unsubscribe(user=req.authname)
                # unsubscribe does not return a value to indicate if it 
                # was successful, so we have to explicitly check
                if not mailinglist.is_subscribed(req.authname):
                    add_notice(req, _('You have been unsubscribed from %s.' % mailinglist.name))
                else:
                    add_notice(req, _('Unable to unsubscribe from %s.' % mailinglist.name))

            if req.path_info.endswith('/mailinglist'):
                 # overview mailing list page
                req.redirect(req.href.mailinglist())
            elif 'conversationid' in req.args:
                # individual mailing list conversation log
                req.redirect(req.href.mailinglist(mailinglist_email, req.args['conversationid']))
            else:
                # individual mailing list homepage
                req.redirect(req.href.mailinglist(mailinglist_email))

        #for mailinglist in mailinglists:
        #    add_ctxtnav(req,
        #                _("List: %s") % mailinglist.name,
        #                req.href.mailinglist(mailinglist.emailaddress))
		
        if 'messageid' in req.args:
            message = MailinglistMessage(self.env, req.args['messageid'])
            # leaks the subject of the email in the error, wonder if
            # that's a problem...
            req.perm(message.resource).require("MAILINGLIST_VIEW")
            if req.args.get('format') == "raw":
                req.send_header('Content-Disposition', 'attachment')
                req.send_response(200)
                content = message.raw.bytes
                req.send_header('Content-Type', 'application/mbox')
                req.send_header('Content-Length', len(content))
                req.end_headers()
                if req.method != 'HEAD':
                    req.write(content)
                return

            context = Context.from_request(req, message.resource)
            
            data['message'] = message
            data['attachments'] = AttachmentModule(self.env).attachment_data(context)

            add_link(req, 'up', get_resource_url(self.env, message.conversation.resource, req.href,
                                                 offset=data['offset']),
                     _("Back to conversation"))

            prevnext_nav(req, _("Newer message"), _("Older message"), 
                         _("Back to conversation"))

            raw_href = get_resource_url(self.env, message.resource,
                                        req.href, format='raw')
            add_link(req, 'alternate', raw_href, _('mbox'), "application/mbox")

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', message.conversation.mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % message.conversation.mailinglist.name))

            return 'mailinglist_message.html', data, None
            
        if 'conversationid' in req.args:
            conversation = MailinglistConversation(self.env, req.args['conversationid'])
            # also leaks the subject of the first email in the error message
            req.perm(conversation.resource).require("MAILINGLIST_VIEW")
            data['conversation'] = conversation
            data['attachmentselect'] = partial(Attachment.select, self.env)
            
            results = Paginator(conversation.messages(), page - 1, self.limit)
            if results.has_next_page:
                next_href = get_resource_url(self.env, conversation.resource, req.href, page=page + 1) 
                add_link(req, 'next', next_href, _('Next Page'))

            if results.has_previous_page:
                prev_href = get_resource_url(self.env, conversation.resource, req.href, page=page - 1) 
                add_link(req, 'prev', prev_href, _('Previous Page'))
            
            shown_pages = results.get_shown_pages()
            pagedata = [{'href': get_resource_url(self.env,
                                                  conversation.resource,
                                                  req.href, page=page),
                         'class': None, 'string': str(page),
                         'title': _('Page %(num)d', num=page)}
                        for page in shown_pages]
            results.shown_pages = pagedata
            results.current_page = {'href': None, 'class': 'current',
                                    'string': str(results.page + 1),
                                    'title': None}
            data['paginator'] = results
            add_link(req, 'up', get_resource_url(self.env, conversation.mailinglist.resource, req.href,
                                                 offset=data['offset']),
                     _("List of conversations"))

            prevnext_nav(req, _("Newer conversation"), _("Older conversation"), 
                         _("Back to list of conversations"))

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', conversation.mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % conversation.mailinglist.name))


            # Check if user is already subscribed to mailing list 
            # and add the appropriate subscribe / unsubscribe ribbon option
            if conversation.mailinglist.is_subscribed(req.authname):
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye-slash'),
                ' Unsubscribe', title='Unsubscribe from the %s mailing list' % conversation.mailinglist.name, id='subscribe-link'),
                name='unsubscribe', value=conversation.mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))
            else:
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye'),
                ' Subscribe', title='Subscribe to the %s mailing list' % conversation.mailinglist.name, id='subscribe-link'),
                name='subscribe', value=conversation.mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))

            return 'mailinglist_conversation.html', data, None

        elif 'listname' in req.args:
            mailinglist = Mailinglist.select_by_address(self.env,
                                                        req.args['listname'], localpart=True)
            # leaks the name of the mailinglist
            req.perm(mailinglist.resource).require("MAILINGLIST_VIEW")

            data['mailinglist'] = mailinglist

            results = Paginator(mailinglist.conversations(),
                            page - 1,
                            self.limit)

            if results.has_next_page:
                next_href = get_resource_url(self.env, mailinglist.resource, req.href, page=page + 1) 
                add_link(req, 'next', next_href, _('Next Page'))

            if results.has_previous_page:
                prev_href = get_resource_url(self.env, mailinglist.resource, req.href, page=page - 1) 
                add_link(req, 'prev', prev_href, _('Previous Page'))

            shown_pages = results.get_shown_pages()
            pagedata = [{'href': get_resource_url(self.env,
                                                  mailinglist.resource,
                                                  req.href, page=page),
                         'class': None, 'string': str(page),
                         'title': _('Page %(num)d', num=page)}
                        for page in shown_pages]
            results.shown_pages = pagedata
            results.current_page = {'href': None, 'class': 'current',
                                    'string': str(results.page + 1),
                                    'title': None}
            data['paginator'] = results

            if data['offset'] + data['limit'] < mailinglist.count_conversations():
                add_link(req, 'next',
                         get_resource_url(self.env, mailinglist.resource, req.href,
                                          offset=data['offset']+data['limit']),
                         _("Older conversations"))

            if offset > 0:
                add_link(req, 'prev',
                         get_resource_url(self.env, mailinglist.resource, req.href,
                                          offset=data['offset']-data['limit']),
                         _("Newer conversations"))

            add_link(req, 'up', req.href.mailinglist(), _("List of mailinglists"))

            prevnext_nav(req, _("Newer conversations"), _("Older conversations"), ("Back to Mailinglists"))

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % mailinglist.name))

            # Check if user is already subscribed to mailing list 
            # and add the appropriate subscribe / unsubscribe ribbon option
            if mailinglist.is_subscribed(req.authname):
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye-slash'),
                ' Unsubscribe', title='Unsubscribe from the %s mailing list' % mailinglist.name, id='subscribe-link'),
                name='unsubscribe', value=mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))
            else:
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye'),
                ' Subscribe', title='Subscribe to the %s mailing list' % mailinglist.name, id='subscribe-link'),
                name='subscribe', value=mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))

            return 'mailinglist_conversations.html', data, None

        else:
            return 'mailinglist_list.html', data, None