def setUp(self):
     super(ListMembersOptionsTest, self).setUp()
     self.domain = get_mailman_client().create_domain('example.com')
     self.foo_list = self.domain.create_list('foo')
     self.user = User.objects.create_user('testuser', '*****@*****.**',
                                          'testpass')
     self.superuser = User.objects.create_superuser('testsu',
                                                    '*****@*****.**',
                                                    'testpass')
     self.owner = User.objects.create_user('testowner', '*****@*****.**',
                                           'testpass')
     self.moderator = User.objects.create_user('testmoderator',
                                               '*****@*****.**',
                                               'testpass')
     for user in (self.user, self.superuser, self.owner, self.moderator):
         EmailAddress.objects.create(user=user,
                                     email=user.email,
                                     verified=True)
     self.foo_list.add_owner('*****@*****.**')
     self.foo_list.add_moderator('*****@*****.**')
     self.mm_user = get_mailman_client().create_user('*****@*****.**', '')
     self.mm_user.addresses[0].verify()
     self.foo_list.subscribe('*****@*****.**',
                             pre_verified=True,
                             pre_confirmed=True,
                             pre_approved=True)
     self.url = reverse('list_member_options',
                        args=(
                            self.foo_list.list_id,
                            '*****@*****.**',
                        ))
Exemple #2
0
 def all(self):
     try:
         return getattr(get_mailman_client(), self.resource_name_plural)
     except AttributeError:
         raise MailmanApiError
     except MailmanConnectionError as e:
         raise MailmanApiError(e)
    def update_from_mailman(self):
        try:
            client = get_mailman_client()
            mm_list = client.get_list(self.name)
        except MailmanConnectionError:
            return
        except HTTPError:
            return  # can't update at this time
        if not mm_list:
            return

        def convert_date(value):
            value = dateutil.parser.parse(value)
            if value.tzinfo is None:
                value = value.replace(tzinfo=utc)
            return value
        converters = {
            "created_at": convert_date,
            "archive_policy": lambda p: ArchivePolicy[p].value,
        }
        for propname in self.MAILMAN_ATTRIBUTES:
            try:
                value = getattr(mm_list, propname)
            except AttributeError:
                value = mm_list.settings[propname]
            if propname in converters:
                value = converters[propname](value)
            setattr(self, propname, value)
        self.save()
Exemple #4
0
 def setUp(self):
     self.mm_client = get_mailman_client()
     if self.use_vcr:
         cm = self._mm_vcr.use_cassette('.'.join([
             self.__class__.__name__, self._testMethodName, 'yaml']))
         self.cassette = cm.__enter__()
         self.addCleanup(cm.__exit__, None, None, None)
def bans_view(request, template, list_id=None):
    """Ban or unban email addresses.

    This is a reusable view which works for both global and list specific bans.
    Whether a MailingList ban is updated or a Global one depends on list_id
    being passed in.

    :list_id: MailingList Id if this is a List ban, None otherwise.

    """
    if list_id:
        m_list = List.objects.get_or_404(fqdn_listname=list_id)
        url = reverse('list_bans', args=[list_id])
        ban_list = m_list.bans
    else:
        ban_list = get_mailman_client().bans
        url = reverse('global_bans')
        m_list = None

    # Process form submission.
    if request.method == 'POST':
        if 'add' in request.POST:
            addban_form = AddBanForm(request.POST)
            if addban_form.is_valid():
                try:
                    ban_list.add(addban_form.cleaned_data['email'])
                    messages.success(request, _(
                        'The email {} has been banned.'.format(
                            addban_form.cleaned_data['email'])))
                except HTTPError as e:
                    messages.error(
                        request, _('An error occurred: %s') % e.reason)
                except ValueError as e:
                    messages.error(request, _('Invalid data: %s') % e)
                return redirect(url)
        elif 'del' in request.POST:
            try:
                ban_list.remove(request.POST['email'])
                messages.success(request, _(
                    'The email {} has been un-banned'.format(
                        request.POST['email'])))
            except HTTPError as e:
                messages.error(request, _('An error occurred: %s') % e.reason)
            except ValueError as e:
                messages.error(request, _('Invalid data: %s') % e)
            return redirect(url)
    else:
        addban_form = AddBanForm(initial=request.GET)
    banned_addresses = paginate(
        list(ban_list), request.GET.get('page'), request.GET.get('count'))

    context = {
        'addban_form': addban_form,
        'banned_addresses': banned_addresses,
    }

    if list_id:
        context['list'] = m_list

    return render(request, template, context)
def public_profile(request, user_id):
    class FakeMailmanUser(object):
        display_name = None
        created_on = None
        addresses = []
        subscription_list_ids = []
        user_id = None

    try:
        client = get_mailman_client()
        mm_user = client.get_user(user_id)
    except HTTPError:
        raise Http404("No user with this ID: %s" % user_id)
    except mailmanclient.MailmanConnectionError:
        mm_user = FakeMailmanUser()
        mm_user.user_id = user_id
    # XXX: don't list subscriptions, there's a privacy issue here.
    # # Subscriptions
    # subscriptions = get_subscriptions(mm_user, db_user)
    all_votes = Vote.objects.filter(email__sender__mailman_id=user_id)
    likes = all_votes.filter(value=1).count()
    dislikes = all_votes.filter(value=-1).count()
    likestatus = "neutral"
    if likes - dislikes >= 10:
        likestatus = "likealot"
    elif likes - dislikes > 0:
        likestatus = "like"
    # This is only used for the Gravatar. No email display on the public
    # profile, we have enough spam as it is, thank you very much.
    try:
        addresses = [str(addr) for addr in mm_user.addresses]
    except (KeyError, IndexError):
        addresses = []
    fullname = mm_user.display_name
    if not fullname:
        fullname = Email.objects.filter(sender__mailman_id=user_id).exclude(
            sender_name="",
            sender_name__isnull=True).values_list("sender_name",
                                                  flat=True).first()
    if mm_user.created_on is not None:
        creation = dateutil.parser.parse(mm_user.created_on)
    else:
        creation = None
    posts_count = Email.objects.filter(sender__mailman_id=user_id).count()
    is_user = request.user.is_authenticated and bool(
        set([str(a) for a in mm_user.addresses])
        & set(request.user.hyperkitty_profile.addresses))
    context = {
        "fullname": fullname,
        "creation": creation,
        "posts_count": posts_count,
        "likes": likes,
        "dislikes": dislikes,
        "likestatus": likestatus,
        "addresses": addresses,
        "is_user": is_user,
    }
    return render(request, "hyperkitty/user_public_profile.html", context)
Exemple #7
0
 def all(self, advertised=False):
     try:
         method = getattr(get_mailman_client(),
                          'get_' + self.resource_name_plural)
         return method(advertised=advertised)
     except AttributeError:
         raise MailmanApiError
     except MailmanConnectionError as e:
         raise MailmanApiError(e)
Exemple #8
0
 def get(self, *args, **kwargs):
     try:
         method = getattr(get_mailman_client(), 'get_' + self.resource_name)
         return method(*args, **kwargs)
     except AttributeError as e:
         raise MailmanApiError(e)
     except HTTPError as e:
         if e.code == 404:
             raise Mailman404Error('Mailman resource could not be found.')
         else:
             raise
     except MailmanConnectionError as e:
         raise MailmanApiError(e)
Exemple #9
0
def system_information(request):
    client = get_mailman_client()
    all_configs = client.system

    configs = []
    for key, name in SYSTEM_INFO_KEYS:
        configs.append((name, all_configs.get(key)))

    return render(
        request,
        'postorius/system_information.html',
        {'configs': configs},
    )
Exemple #10
0
def import_list_from_mailman(list_id):
    from hyperkitty.models import MailingList
    mmclient = get_mailman_client()
    try:
        mm_list = mmclient.get_list(list_id)
    except (MailmanConnectionError, HTTPError):
        return
    mlist, created = MailingList.objects.get_or_create(
        name=mm_list.fqdn_listname)
    if created:
        logger.info("Imported the new list %s from Mailman",
                    mm_list.fqdn_listname)
    mlist.update_from_mailman()
Exemple #11
0
    def _get_list_page(count, page):
        filtering = settings.MAILMAN_LIST_INDEX_FILTERING
        client = get_mailman_client()

        if filtering == 'owner-only' and not request.user.is_superuser:
            return client.get_list_page(owner=request.user.email,
                                        count=count,
                                        page=page)

        advertised = not request.user.is_superuser
        return client.get_list_page(advertised=advertised,
                                    count=count,
                                    page=page)
Exemple #12
0
 def create(self, *args, **kwargs):
     try:
         method = getattr(get_mailman_client(),
                          'create_' + self.resource_name)
         return method(*args, **kwargs)
     except AttributeError as e:
         raise MailmanApiError(e)
     except HTTPError as e:
         if e.code == 409:
             raise MailmanApiError
         else:
             raise
     except MailmanConnectionError:
         raise MailmanApiError
Exemple #13
0
 def all(self, only_public=False):
     try:
         objects = getattr(get_mailman_client(), self.resource_name_plural)
     except AttributeError:
         raise MailmanApiError
     except MailmanConnectionError as e:
         raise MailmanApiError(e)
     if only_public:
         public = []
         for obj in objects:
             if obj.settings.get('advertised', False):
                 public.append(obj)
         return public
     else:
         return objects
Exemple #14
0
 def handle(self, *args, **options):
     # choose an interpreter
     try:
         import IPython
         console_fn = IPython.embed
     except ImportError:
         import code
         shell = code.InteractiveConsole(globals())
         console_fn = shell.interact
     # connect to mailmanclient
     client = get_mailman_client()
     # Putting client back in the global scope
     globals()['client'] = client
     # run the interpreter
     console_fn()
Exemple #15
0
    def _get_combined_preferences(self):
        # Get layers of default preferences to match how they are applied
        # We ignore self_link as we don't want to over-write it
        defaultpreferences = get_mailman_client().preferences
        combinedpreferences = {}
        for key in defaultpreferences:
            if key != u"self_link":
                combinedpreferences[key] = defaultpreferences[key]

        # Clobber defaults with any preferences already set
        for key in self.mm_user.preferences:
            if key != u"self_link":
                combinedpreferences[key] = self.mm_user.preferences[key]

        return (combinedpreferences)
Exemple #16
0
def subscribe(list_id, user, email=None, display_name=None):
    if email is None:
        email = user.email
    if display_name is None:
        display_name = "%s %s" % (user.first_name, user.last_name)
    client = get_mailman_client()
    rest_list = client.get_list(list_id)
    subscription_policy = rest_list.settings.get("subscription_policy",
                                                 "moderate")
    # Add a flag to return that would tell the user they have been subscribed
    # to the current list.
    subscribed_now = False
    try:
        member = rest_list.get_member(email)
    except ValueError:
        # We don't want to bypass moderation, don't subscribe. Instead
        # raise an error so that it can be caught to show the user
        if subscription_policy in ("moderate", "confirm_then_moderate"):
            raise ModeratedListException(
                "This list is moderated, please subscribe"
                " to it before posting.")

        # not subscribed yet, subscribe the user without email delivery
        try:
            member = rest_list.subscribe(email,
                                         display_name,
                                         pre_verified=True,
                                         pre_confirmed=True)
        except HTTPError as e:
            if e.code == 409:
                logger.info("Subscription for %s to %s is already pending",
                            email, list_id)
                return subscribed_now
            else:
                raise
        # The result can be a Member object or a dict if the subscription can't
        # be done directly, or if it's pending, or something else.
        # Broken API :-(
        if isinstance(member, dict):
            logger.info("Subscription for %s to %s is pending", email, list_id)
            return subscribed_now
        member.preferences["delivery_status"] = "by_user"
        member.preferences.save()
        subscribed_now = True
        cache.delete("User:%s:subscriptions" % user.id, version=2)
        logger.info("Subscribing %s to %s on first post", email, list_id)

    return subscribed_now
Exemple #17
0
 def set_mailman_id(self):
     try:
         client = get_mailman_client()
         mm_user = client.get_user(self.address)
     except HTTPError as e:
         if e.code == 404:
             return  # User not found in Mailman
         # normalize all possible error types
         raise MailmanConnectionError(e)
     except ValueError as e:
         # This smells like a badly formatted email address (saw it in the
         # wild)
         logger.warning(
             "Invalid response when getting user %s from Mailman",
             self.address)
         return  # Ignore it
     self.mailman_id = mm_user.user_id
     self.save()
Exemple #18
0
    def _get_combined_preferences(self):
        # grab the default preferences
        defaultpreferences = get_mailman_client().preferences

        # grab your global preferences
        globalpreferences = self.mm_user.preferences

        # start a new combined preferences object
        combinedpreferences = []

        for sub in self.subscriptions:
            # make a per-address prefs object
            prefs = {}

            # initialize with default preferences
            for key in defaultpreferences:
                if key != u"self_link":
                    prefs[key] = defaultpreferences[key]

            # overwrite with user's global preferences
            for key in globalpreferences:
                if key != u"self_link":
                    prefs[key] = globalpreferences[key]

            # overwrite with address-based preferences
            # There is currently no better way to do this,
            # we may consider revisiting.
            addresspreferences = {}
            for address in self.mm_user.addresses:
                if sub.email == address.email:
                    addresspreferences = address.preferences

            for key in addresspreferences:
                if key != u"self_link":
                    prefs[key] = addresspreferences[key]

            # overwrite with subscription-specific preferences
            for key in sub.preferences:
                if key != u"self_link":
                    prefs[key] = sub.preferences[key]

            combinedpreferences.append(prefs)

        return combinedpreferences
Exemple #19
0
def list_index_authenticated(request):
    """Index page for authenticated users.

    Index page for authenticated users is slightly different than
    un-authenticated ones. Authenticated users will see all their memberships
    in the index page.

    This view is not paginated and will show all the lists.

    """
    role = request.GET.get('role', None)
    client = get_mailman_client()
    choosable_domains = _get_choosable_domains(request)

    # Get all the verified addresses of the user.
    user_emails = EmailAddress.objects.filter(
        user=request.user, verified=True).order_by(
            "email").values_list("email", flat=True)

    # Get all the mailing lists for the current user.
    all_lists = []
    for user_email in user_emails:
        try:
            all_lists.extend(client.find_lists(user_email, role=role))
        except HTTPError:
            # No lists exist with the given role for the given user.
            pass
    # If the user has no list that they are subscriber/owner/moderator of, we
    # just redirect them to the index page with all lists.
    if len(all_lists) == 0 and role is None:
        return redirect(reverse('list_index') + '?all-lists')
    # Render the list index page.
    context = {
        'lists': _unique_lists(all_lists),
        'domain_count': len(choosable_domains),
        'role': role
    }
    return render(
        request,
        'postorius/index.html',
        context
    )
Exemple #20
0
def subscriptions(request):
    profile = request.user.hyperkitty_profile
    mm_user_id = get_mailman_user_id(request.user)
    subs = []
    for mlist_id in get_subscriptions(request.user):
        try:
            mlist = MailingList.objects.get(list_id=mlist_id)
        except MailingList.DoesNotExist:
            mlist = None  # no archived email yet
        posts_count = likes = dislikes = 0
        first_post = all_posts_url = None
        if mlist is not None:
            list_name = mlist.name
            posts_count = profile.emails.filter(
                mailinglist__name=mlist.name).count()
            likes, dislikes = profile.get_votes_in_list(mlist.name)
            first_post = profile.get_first_post(mlist)
            if mm_user_id is not None:
                all_posts_url = "%s?list=%s" % (
                    reverse("hk_user_posts", args=[mm_user_id]),
                    mlist.name)
        else:
            list_name = get_mailman_client().get_list(mlist_id).fqdn_listname
        likestatus = "neutral"
        if likes - dislikes >= 10:
            likestatus = "likealot"
        elif likes - dislikes > 0:
            likestatus = "like"
        subs.append({
            "list_name": list_name,
            "mlist": mlist,
            "posts_count": posts_count,
            "first_post": first_post,
            "likes": likes,
            "dislikes": dislikes,
            "likestatus": likestatus,
            "all_posts_url": all_posts_url,
        })
    return render(request, 'hyperkitty/user_profile/subscriptions.html', {
                "subscriptions": subs,
                "subpage": "subscriptions",
            })
Exemple #21
0
def get_new_lists_from_mailman():
    from hyperkitty.models import MailingList
    mmclient = get_mailman_client()
    page_num = 0
    while page_num < 10000:  # Just for security
        page_num += 1
        try:
            mlist_page = mmclient.get_list_page(count=10, page=page_num)
        except MailmanConnectionError:
            break
        except HTTPError:
            break  # can't update at this time
        for mm_list in mlist_page:
            if MailingList.objects.filter(name=mm_list.fqdn_listname).exists():
                continue
            if mm_list.settings["archive_policy"] == "never":
                continue  # Should we display those lists anyway?
            logger.info("Imported the new list %s from Mailman",
                        mm_list.fqdn_listname)
            mlist = MailingList.objects.create(name=mm_list.fqdn_listname)
            mlist.update_from_mailman()
        if not mlist_page.has_next:
            break
Exemple #22
0
    def _get_combined_preferences(self):
        # grab the default preferences
        defaultpreferences = get_mailman_client().preferences

        # grab your global preferences
        globalpreferences = self.mm_user.preferences

        # start a new combined preferences object
        combinedpreferences = []

        for address in self.mm_user.addresses:
            # make a per-address prefs object
            prefs = {}

            # initialize with default preferences
            for key in defaultpreferences:
                if key != u"self_link":
                    prefs[key] = defaultpreferences[key]

            # overwrite with user's global preferences
            for key in globalpreferences:
                if key != u"self_link":
                    prefs[key] = globalpreferences[key]

            # overwrite with address-specific preferences
            for key in address.preferences:
                if key != u"self_link":
                    prefs[key] = address.preferences[key]
            combinedpreferences.append(prefs)

            # put the combined preferences back on the original object
            for key in prefs:
                if key != u"self_link":
                    address.preferences[key] = prefs[key]

        return combinedpreferences
Exemple #23
0
 def handle(self, *args, **kwargs):
     client = get_mailman_client()
     for user in self._get_all_users(client):
         self._reset_password(user)
Exemple #24
0
def list_member_options(request, list_id, email):
    template_name = 'postorius/lists/memberoptions.html'
    client = get_mailman_client()
    mm_list = List.objects.get_or_404(fqdn_listname=list_id)
    try:
        mm_member = client.get_member(list_id, email)
        member_prefs = mm_member.preferences
    except ValueError:
        raise Http404(_('Member does not exist'))
    except Mailman404Error:
        return render(request, template_name, {'nolists': 'true'})
    initial_moderation = dict([
        (key, getattr(mm_member, key)) for key in MemberModeration.base_fields
        ])
    if request.method == 'POST':
        if request.POST.get("formname") == 'preferences':
            moderation_form = MemberModeration(initial=initial_moderation)
            preferences_form = UserPreferences(
                request.POST, initial=member_prefs)
            if preferences_form.is_valid():
                if not preferences_form.has_changed():
                    messages.info(request,
                                  _("No change to the member's preferences."))
                    return redirect('list_member_options', list_id, email)
                for key in preferences_form.fields.keys():
                    member_prefs[key] = preferences_form.cleaned_data[key]
                try:
                    member_prefs.save()
                except HTTPError as e:
                    messages.error(request, e.msg)
                else:
                    messages.success(request, _("The member's preferences have"
                                                " been updated."))
                    return redirect('list_member_options', list_id, email)
        elif request.POST.get("formname") == 'moderation':
            preferences_form = UserPreferences(initial=member_prefs)
            moderation_form = MemberModeration(
                request.POST, initial=initial_moderation)
            if moderation_form.is_valid():
                if not moderation_form.has_changed():
                    messages.info(request,
                                  _("No change to the member's moderation."))
                    return redirect('list_member_options', list_id, email)
                for key in moderation_form.fields.keys():
                    setattr(mm_member, key, moderation_form.cleaned_data[key])
                try:
                    mm_member.save()
                except HTTPError as e:
                    messages.error(request, e.msg)
                else:
                    messages.success(request, _("The member's moderation "
                                                "settings have been updated."))
                    return redirect('list_member_options', list_id, email)
    else:
        preferences_form = UserPreferences(initial=member_prefs)
        moderation_form = MemberModeration(initial=initial_moderation)
    return render(request, template_name, {
        'mm_member': mm_member,
        'list': mm_list,
        'preferences_form': preferences_form,
        'moderation_form': moderation_form,
        })
Exemple #25
0
 def client(self):
     if getattr(self, '_client', None) is None:
         self._client = get_mailman_client()
     return self._client
 def setUp(self):
     self.mm_client = get_mailman_client()
Exemple #27
0
class AlterMessagesForm(ListSettingsForm):
    """
    Alter messages list settings.
    """
    filter_content = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_('Filter content'),
        help_text=_('Should Mailman filter the content of list traffic '
                    'according to the settings below?'))
    collapse_alternatives = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_('Collapse alternatives'),
        help_text=_('Should Mailman collapse multipart/alternative to '
                    'its first part content?'))
    convert_html_to_plaintext = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_('Convert html to plaintext'),
        help_text=_('Should Mailman convert text/html parts to plain text? '
                    'This conversion happens after MIME attachments '
                    'have been stripped.'))
    anonymous_list = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_('Anonymous list'),
        help_text=_('Hide the sender of a message, '
                    'replacing it with the list address '
                    '(Removes From, Sender and Reply-To fields)'))
    include_rfc2369_headers = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_('Include RFC2369 headers'),
        help_text=_(
            'Yes is highly recommended. RFC 2369 defines a set of List-* '
            'headers that are normally added to every message sent to the '
            'list membership. These greatly aid end-users who are using '
            'standards compliant mail readers. They should normally always '
            'be enabled. However, not all mail readers are standards '
            'compliant yet, and if you have a large number of members who are '
            'using non-compliant mail readers, they may be annoyed at these '
            'headers. You should first try to educate your members as to why '
            'these headers exist, and how to hide them in their mail clients. '
            'As a last resort you can disable these headers, but this is not '
            'recommended (and in fact, your ability to disable these headers '
            'may eventually go away).'))
    allow_list_posts = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        label=_("Include the list post header"),
        help_text=_(
            "This can be set to no for announce lists that do not wish to "
            "include the List-Post header because posting to the list is "
            "discouraged."))
    reply_to_address = forms.CharField(
        label=_('Explicit reply-to address'),
        required=False,
        help_text=_(
            'This option allows admins to set an explicit Reply-to address. '
            'It is only used if the reply-to is set to use an explicitly set '
            'header'))
    first_strip_reply_to = forms.TypedChoiceField(
        choices=((True, _('Yes')), (False, _('No'))),
        widget=forms.RadioSelect,
        required=False,
        help_text=_(
            'Should any existing Reply-To: header found in the original '
            'message be stripped? If so, this will be done regardless of '
            'whether an explict Reply-To: header is added by Mailman or not.'))
    reply_goes_to_list = forms.ChoiceField(
        label=_('Reply goes to list'),
        widget=forms.Select(),
        required=False,
        error_messages={
            'required': _("Please choose a reply-to action.")},
        choices=(
            ('no_munging', _('No Munging')),
            ('point_to_list', _('Reply goes to list')),
            ('explicit_header', _('Explicit Reply-to header set')),
            ('explicit_header_only', _('Explicit Reply-to set; no Cc added'))),
        help_text=_(
            'Where are replies to list messages directed? No Munging is '
            'strongly recommended for most mailing lists. \nThis option '
            'controls what Mailman does to the Reply-To: header in messages '
            'flowing through this mailing list. When set to No Munging, no '
            'Reply-To: header is '
            'added by Mailman, although if one is present in the original '
            'message, it is not stripped. Setting this value to either Reply '
            'to List, Explicit Reply, or Reply Only causes Mailman to insert '
            'a specific Reply-To: header in all messages, overriding the '
            'header in the original message if necessary '
            '(Explicit Reply inserts the value of reply_to_address). '
            'Explicit Reply-to set; no Cc added is useful for'
            'announce-only lists where you want to avoid someone replying '
            'to the list address. There are many reasons not to introduce or '
            'override the Reply-To: header. One is that some posters depend '
            'on their own Reply-To: settings to convey their valid return '
            'address. Another is that modifying Reply-To: makes it much more '
            'difficult to send private replies. See `Reply-To\' Munging '
            'Considered Harmful for a general discussion of this issue. '
            'See Reply-To Munging Considered Useful for a dissenting opinion. '
            'Some mailing lists have restricted '
            'posting privileges, with a parallel list devoted to discussions. '
            'Examples are `patches\' or `checkin\' lists, where software '
            'changes are posted by a revision control system, but discussion '
            'about the changes occurs on a developers mailing list. To '
            'support these types of mailing lists, select Explicit Reply and '
            'set the Reply-To: address option to point to the parallel list.'))
    posting_pipeline = forms.ChoiceField(
        label=_('Pipeline'),
        widget=forms.Select(),
        required=False,
        choices=lambda: ((p, p) for p in get_mailman_client()
                         .pipelines['pipelines']),
        help_text=_('Type of pipeline you want to use for this mailing list'))
Exemple #28
0
 def _get_list_page(count, page):
     client = get_mailman_client()
     advertised = not request.user.is_superuser
     return client.get_list_page(
         advertised=advertised, count=count, page=page)