Exemplo n.º 1
0
 def _setValue(self, mlist, property, val, doc):
     # Do value conversion from web representation to internal
     # representation.
     try:
         if property == 'bounce_processing':
             val = int(val)
         elif property == 'bounce_score_threshold':
             val = float(val)
         elif property == 'bounce_info_stale_after':
             val = days(int(val))
         elif property == 'bounce_you_are_disabled_warnings':
             val = int(val)
         elif property == 'bounce_you_are_disabled_warnings_interval':
             val = days(int(val))
         elif property == 'bounce_notify_owner_on_disable':
             val = int(val)
         elif property == 'bounce_notify_owner_on_removal':
             val = int(val)
     except ValueError:
         doc.addError(
             _("""Bad value for <a href="?VARHELP=bounce/%(property)s"
             >%(property)s</a>: %(val)s"""),
             tag = _('Error: '))
         return
     GUIBase._setValue(self, mlist, property, val, doc)
Exemplo n.º 2
0
 def _setValue(self, mlist, property, val, doc):
     # Do value conversion from web representation to internal
     # representation.
     try:
         if property == 'bounce_processing':
             val = int(val)
         elif property == 'bounce_score_threshold':
             val = float(val)
         elif property == 'bounce_info_stale_after':
             val = days(int(val))
         elif property == 'bounce_you_are_disabled_warnings':
             val = int(val)
         elif property == 'bounce_you_are_disabled_warnings_interval':
             val = days(int(val))
         elif property == 'bounce_notify_owner_on_disable':
             val = int(val)
         elif property == 'bounce_notify_owner_on_removal':
             val = int(val)
     except ValueError:
         doc.addError(
             _("""Bad value for <a href="?VARHELP=bounce/%(property)s"
             >%(property)s</a>: %(val)s"""),
             tag=_('Error: '))
         return
     GUIBase._setValue(self, mlist, property, val, doc)
Exemplo n.º 3
0
def process(res, args):
    mlist = res.mlist
    if len(args) <> 1:
        res.results.append(_('Usage:'))
        res.results.append(gethelp(mlist))
        return STOP
    cookie = args[0]
    try:
        results = mlist.ProcessConfirmation(cookie, res.msg)
    except Errors.MMBadConfirmation, e:
        # Express in approximate days
        days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
        res.results.append(_("""\
Invalid confirmation string.  Note that confirmation strings expire
approximately %(days)s days after the initial subscription request.  If your
confirmation has expired, please try to re-submit your original request or
message."""))
Exemplo n.º 4
0
def process(res, args):
    mlist = res.mlist
    if len(args) <> 1:
        res.results.append(_('Usage:'))
        res.results.append(gethelp(mlist))
        return STOP
    cookie = args[0]
    try:
        results = mlist.ProcessConfirmation(cookie, res.msg)
    except Errors.MMBadConfirmation, e:
        # Express in approximate days
        days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
        res.results.append(
            _("""\
Invalid confirmation string.  Note that confirmation strings expire
approximately %(days)s days after the initial subscription request.  If your
confirmation has expired, please try to re-submit your original request or
message."""))
Exemplo n.º 5
0
        return

    if not cookie and len(parts) == 2:
        cookie = parts[1]

    if len(parts) > 2:
        bad_confirmation(doc)
        doc.AddItem(mlist.GetMailmanFooter())
        print doc.Format()
        return

    if not cookie:
        ask_for_cookie(mlist, doc)
        return

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
    confirmurl = mlist.GetScriptURL('confirm', absolute=1)
    # Avoid cross-site scripting attacks
    safecookie = Utils.websafe(cookie)
    badconfirmstr = _('''<b>Invalid confirmation string:</b>
    %(safecookie)s.

    <p>Note that confirmation strings expire approximately
    %(days)s days after the initial subscription request.  If your
    confirmation has expired, please try to re-submit your subscription.
    Otherwise, <a href="%(confirmurl)s">re-enter</a> your confirmation
    string.''')

    content = mlist.pend_confirm(cookie, expunge=False)
    if content is None:
        bad_confirmation(doc, badconfirmstr)
Exemplo n.º 6
0
def options_page(mlist, doc, user, cpuser, userlang, message=''):
    # The bulk of the document will come from the options.html template, which
    # includes it's own html armor (head tags, etc.).  Suppress the head that
    # Document() derived pages get automatically.
    doc.suppress_head = 1

    if mlist.obscure_addresses:
        presentable_user = Utils.ObscureEmail(user, for_text=1)
        if cpuser is not None:
            cpuser = Utils.ObscureEmail(cpuser, for_text=1)
    else:
        presentable_user = user

    fullname = Utils.uncanonstr(mlist.getMemberName(user), userlang)
    if fullname:
        presentable_user += ', %s' % Utils.websafe(fullname)

    # Do replacements
    replacements = mlist.GetStandardReplacements(userlang)
    replacements['<mm-results>'] = Bold(FontSize('+1', message)).Format()
    replacements['<mm-digest-radio-button>'] = mlist.FormatOptionButton(
        mm_cfg.Digests, 1, user)
    replacements['<mm-undigest-radio-button>'] = mlist.FormatOptionButton(
        mm_cfg.Digests, 0, user)
    replacements['<mm-plain-digests-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableMime, 1, user)
    replacements['<mm-mime-digests-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableMime, 0, user)
    replacements['<mm-global-mime-button>'] = (CheckBox('mime-globally',
                                                        1,
                                                        checked=0).Format())
    replacements['<mm-delivery-enable-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableDelivery, 0, user)
    replacements['<mm-delivery-disable-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableDelivery, 1, user)
    replacements['<mm-disabled-notice>'] = mlist.FormatDisabledNotice(user)
    replacements['<mm-dont-ack-posts-button>'] = mlist.FormatOptionButton(
        mm_cfg.AcknowledgePosts, 0, user)
    replacements['<mm-ack-posts-button>'] = mlist.FormatOptionButton(
        mm_cfg.AcknowledgePosts, 1, user)
    replacements['<mm-receive-own-mail-button>'] = mlist.FormatOptionButton(
        mm_cfg.DontReceiveOwnPosts, 0, user)
    replacements['<mm-dont-receive-own-mail-button>'] = (
        mlist.FormatOptionButton(mm_cfg.DontReceiveOwnPosts, 1, user))
    replacements['<mm-dont-get-password-reminder-button>'] = (
        mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 1, user))
    replacements['<mm-get-password-reminder-button>'] = (
        mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 0, user))
    replacements['<mm-public-subscription-button>'] = (
        mlist.FormatOptionButton(mm_cfg.ConcealSubscription, 0, user))
    replacements['<mm-hide-subscription-button>'] = mlist.FormatOptionButton(
        mm_cfg.ConcealSubscription, 1, user)
    replacements['<mm-dont-receive-duplicates-button>'] = (
        mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 1, user))
    replacements['<mm-receive-duplicates-button>'] = (mlist.FormatOptionButton(
        mm_cfg.DontReceiveDuplicates, 0, user))
    replacements['<mm-unsubscribe-button>'] = (
        mlist.FormatButton('unsub', _('Unsubscribe')) + '<br>' +
        CheckBox('unsubconfirm', 1, checked=0).Format() +
        _('<em>Yes, I really want to unsubscribe</em>'))
    replacements['<mm-new-pass-box>'] = mlist.FormatSecureBox('newpw')
    replacements['<mm-confirm-pass-box>'] = mlist.FormatSecureBox('confpw')
    replacements['<mm-change-pass-button>'] = (mlist.FormatButton(
        'changepw', _("Change My Password")))
    replacements['<mm-other-subscriptions-submit>'] = (mlist.FormatButton(
        'othersubs', _('List my other subscriptions')))
    replacements['<mm-form-start>'] = (mlist.FormatFormStart(
        'options', user, mlist=mlist, contexts=AUTH_CONTEXTS, user=user))
    replacements['<mm-user>'] = user
    replacements['<mm-presentable-user>'] = presentable_user
    replacements['<mm-email-my-pw>'] = mlist.FormatButton(
        'emailpw', (_('Email My Password To Me')))
    replacements['<mm-umbrella-notice>'] = (mlist.FormatUmbrellaNotice(
        user, _("password")))
    replacements['<mm-logout-button>'] = (mlist.FormatButton(
        'logout', _('Log out')))
    replacements['<mm-options-submit-button>'] = mlist.FormatButton(
        'options-submit', _('Submit My Changes'))
    replacements['<mm-global-pw-changes-button>'] = (CheckBox(
        'pw-globally', 1, checked=0).Format())
    replacements['<mm-global-deliver-button>'] = (CheckBox('deliver-globally',
                                                           1,
                                                           checked=0).Format())
    replacements['<mm-global-remind-button>'] = (CheckBox('remind-globally',
                                                          1,
                                                          checked=0).Format())
    replacements['<mm-global-nodupes-button>'] = (CheckBox('nodupes-globally',
                                                           1,
                                                           checked=0).Format())

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1))
    if days > 1:
        units = _('days')
    else:
        units = _('day')
    replacements['<mm-pending-days>'] = _('%(days)d %(units)s')

    replacements['<mm-new-address-box>'] = mlist.FormatBox('new-address')
    replacements['<mm-confirm-address-box>'] = mlist.FormatBox(
        'confirm-address')
    replacements['<mm-change-address-button>'] = mlist.FormatButton(
        'change-of-address', _('Change My Address and Name'))
    replacements['<mm-global-change-of-address>'] = CheckBox(
        'changeaddr-globally', 1, checked=0).Format()
    replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname',
                                                        value=fullname)

    # Create the topics radios.  BAW: what if the list admin deletes a topic,
    # but the user still wants to get that topic message?
    usertopics = mlist.getMemberTopics(user)
    if mlist.topics:
        table = Table(border="0")
        for name, pattern, description, emptyflag in mlist.topics:
            if emptyflag:
                continue
            quotedname = urllib.parse.quote_plus(name)
            details = Link(
                mlist.GetScriptURL('options') + '/%s/?VARHELP=%s' %
                (user, quotedname), ' (Details)')
            if name in usertopics:
                checked = 1
            else:
                checked = 0
            table.AddRow([
                CheckBox('usertopic', quotedname, checked=checked),
                name + details.Format()
            ])
        topicsfield = table.Format()
    else:
        topicsfield = _('<em>No topics defined</em>')
    replacements['<mm-topics>'] = topicsfield
    replacements['<mm-suppress-nonmatching-topics>'] = (
        mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 0, user))
    replacements['<mm-receive-nonmatching-topics>'] = (
        mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 1, user))

    if cpuser is not None:
        replacements['<mm-case-preserved-user>'] = _('''
You are subscribed to this list with the case-preserved address
<em>%(cpuser)s</em>.''')
    else:
        replacements['<mm-case-preserved-user>'] = ''

    page_text = mlist.ParseTags('options.html', replacements, userlang)
    if not (mlist.digestable or mlist.getMemberOption(user, mm_cfg.Digests)):
        page_text = DIGRE.sub('', page_text)
    doc.AddItem(page_text)
Exemplo n.º 7
0
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Message
from Mailman import MemberAdaptor
from Mailman import Pending
from Mailman.Errors import MMUnknownListError
from Mailman.Logging.Syslog import syslog
from Mailman import i18n

EMPTYSTRING = ""

# This constant is supposed to represent the day containing the first midnight
# after the epoch.  We'll add (0,)*6 to this tuple to get a value appropriate
# for time.mktime().
ZEROHOUR_PLUSONEDAY = time.localtime(mm_cfg.days(1))[:3]


def _(s):
    return s


REASONS = {
    MemberAdaptor.BYBOUNCE: _("due to excessive bounces"),
    MemberAdaptor.BYUSER: _("by yourself"),
    MemberAdaptor.BYADMIN: _("by the list administrator"),
    MemberAdaptor.UNKNOWN: _("for unknown reasons"),
}

_ = i18n._
Exemplo n.º 8
0
def reenable_prompt(mlist, doc, cookie, list, member):
    title = _('Re-enable mailing list membership')
    doc.SetTitle(title)
    form = Form(mlist.GetScriptURL('confirm', 1))
    table = Table(border=0, width='100%')
    table.AddRow([Center(Bold(FontAttr(title, size='+1')))])
    table.AddCellInfo(table.GetCurrentRowIndex(),
                      0,
                      colspan=2,
                      bgcolor=mm_cfg.WEB_HEADER_COLOR)

    lang = mlist.getMemberLanguage(member)
    i18n.set_language(lang)
    doc.set_language(lang)

    realname = mlist.real_name
    info = mlist.getBounceInfo(member)
    if not info:
        listinfourl = mlist.GetScriptURL('listinfo', absolute=1)
        # They've already be unsubscribed
        table.AddRow([
            _("""We're sorry, but you have already been unsubscribed
        from this mailing list.  To re-subscribe, please visit the
        <a href="%(listinfourl)s">list information page</a>.""")
        ])
        return

    date = time.strftime('%A, %B %d, %Y',
                         time.localtime(time.mktime(info.date + (0, ) * 6)))
    daysleft = int(info.noticesleft *
                   mlist.bounce_you_are_disabled_warnings_interval /
                   mm_cfg.days(1))
    # BAW: for consistency this should be changed to 'fullname' or the above
    # 'fullname's should be changed to 'username'.  Don't want to muck with
    # the i18n catalogs though.
    username = mlist.getMemberName(member)
    if username is None:
        username = _('<em>not available</em>')
    else:
        username = Utils.websafe(Utils.uncanonstr(username, lang))

    table.AddRow([
        _("""Your membership in the %(realname)s mailing list is
    currently disabled due to excessive bounces.  Your confirmation is
    required in order to re-enable delivery to your address.  We have the
    following information on file:

    <ul><li><b>Member address:</b> %(member)s
        <li><b>Member name:</b> %(username)s
        <li><b>Last bounce received on:</b> %(date)s
        <li><b>Approximate number of days before you are permanently removed
               from this list:</b> %(daysleft)s
    </ul>

    Hit the <em>Re-enable membership</em> button to resume receiving postings
    from the mailing list.  Or hit the <em>Cancel</em> button to defer
    re-enabling your membership.
    """)
    ])

    table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2)
    table.AddRow([Hidden('cookie', cookie)])
    table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2)
    table.AddRow([
        SubmitButton('submit', _('Re-enable membership')),
        SubmitButton('cancel', _('Cancel'))
    ])

    form.AddItem(table)
    doc.AddItem(form)
Exemplo n.º 9
0
        return

    if not cookie and len(parts) == 2:
        cookie = parts[1]

    if len(parts) > 2:
        bad_confirmation(doc)
        doc.AddItem(mlist.GetMailmanFooter())
        print doc.Format()
        return

    if not cookie:
        ask_for_cookie(mlist, doc)
        return

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
    confirmurl = mlist.GetScriptURL('confirm', absolute=1)
    # Avoid cross-site scripting attacks
    safecookie = Utils.websafe(cookie)
    badconfirmstr = _('''<b>Invalid confirmation string:</b>
    %(safecookie)s.

    <p>Note that confirmation strings expire approximately
    %(days)s days after the initial subscription request.  If your
    confirmation has expired, please try to re-submit your subscription.
    Otherwise, <a href="%(confirmurl)s">re-enter</a> your confirmation
    string.''')

    content = mlist.pend_confirm(cookie, expunge=False)
    if content is None:
        bad_confirmation(doc, badconfirmstr)
Exemplo n.º 10
0
def options_page(mlist, doc, user, cpuser, userlang, message=''):
    # The bulk of the document will come from the options.html template, which
    # includes it's own html armor (head tags, etc.).  Suppress the head that
    # Document() derived pages get automatically.
    doc.suppress_head = 1

    if mlist.obscure_addresses:
        presentable_user = Utils.ObscureEmail(user, for_text=1)
        if cpuser is not None:
            cpuser = Utils.ObscureEmail(cpuser, for_text=1)
    else:
        presentable_user = user

    fullname = Utils.uncanonstr(mlist.getMemberName(user), userlang)
    if fullname:
        presentable_user += ', %s' % Utils.websafe(fullname)

    # Do replacements
    replacements = mlist.GetStandardReplacements(userlang)
    replacements['<mm-results>'] = Bold(FontSize('+1', message)).Format()
    replacements['<mm-digest-radio-button>'] = mlist.FormatOptionButton(
        mm_cfg.Digests, 1, user)
    replacements['<mm-undigest-radio-button>'] = mlist.FormatOptionButton(
        mm_cfg.Digests, 0, user)
    replacements['<mm-plain-digests-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableMime, 1, user)
    replacements['<mm-mime-digests-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableMime, 0, user)
    replacements['<mm-global-mime-button>'] = (
        CheckBox('mime-globally', 1, checked=0).Format())
    replacements['<mm-delivery-enable-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableDelivery, 0, user)
    replacements['<mm-delivery-disable-button>'] = mlist.FormatOptionButton(
        mm_cfg.DisableDelivery, 1, user)
    replacements['<mm-disabled-notice>'] = mlist.FormatDisabledNotice(user)
    replacements['<mm-dont-ack-posts-button>'] = mlist.FormatOptionButton(
        mm_cfg.AcknowledgePosts, 0, user)
    replacements['<mm-ack-posts-button>'] = mlist.FormatOptionButton(
        mm_cfg.AcknowledgePosts, 1, user)
    replacements['<mm-receive-own-mail-button>'] = mlist.FormatOptionButton(
        mm_cfg.DontReceiveOwnPosts, 0, user)
    replacements['<mm-dont-receive-own-mail-button>'] = (
        mlist.FormatOptionButton(mm_cfg.DontReceiveOwnPosts, 1, user))
    replacements['<mm-dont-get-password-reminder-button>'] = (
        mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 1, user))
    replacements['<mm-get-password-reminder-button>'] = (
        mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 0, user))
    replacements['<mm-public-subscription-button>'] = (
        mlist.FormatOptionButton(mm_cfg.ConcealSubscription, 0, user))
    replacements['<mm-hide-subscription-button>'] = mlist.FormatOptionButton(
        mm_cfg.ConcealSubscription, 1, user)
    replacements['<mm-dont-receive-duplicates-button>'] = (
        mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 1, user))
    replacements['<mm-receive-duplicates-button>'] = (
        mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 0, user))
    replacements['<mm-unsubscribe-button>'] = (
        mlist.FormatButton('unsub', _('Unsubscribe')) + '<br>' +
        CheckBox('unsubconfirm', 1, checked=0).Format() +
        _('<em>Yes, I really want to unsubscribe</em>'))
    replacements['<mm-new-pass-box>'] = mlist.FormatSecureBox('newpw')
    replacements['<mm-confirm-pass-box>'] = mlist.FormatSecureBox('confpw')
    replacements['<mm-change-pass-button>'] = (
        mlist.FormatButton('changepw', _("Change My Password")))
    replacements['<mm-other-subscriptions-submit>'] = (
        mlist.FormatButton('othersubs',
                           _('List my other subscriptions')))
    replacements['<mm-form-start>'] = (
        mlist.FormatFormStart('options', user))
    replacements['<mm-user>'] = user
    replacements['<mm-presentable-user>'] = presentable_user
    replacements['<mm-email-my-pw>'] = mlist.FormatButton(
        'emailpw', (_('Email My Password To Me')))
    replacements['<mm-umbrella-notice>'] = (
        mlist.FormatUmbrellaNotice(user, _("password")))
    replacements['<mm-logout-button>'] = (
        mlist.FormatButton('logout', _('Log out')))
    replacements['<mm-options-submit-button>'] = mlist.FormatButton(
        'options-submit', _('Submit My Changes'))
    replacements['<mm-global-pw-changes-button>'] = (
        CheckBox('pw-globally', 1, checked=0).Format())
    replacements['<mm-global-deliver-button>'] = (
        CheckBox('deliver-globally', 1, checked=0).Format())
    replacements['<mm-global-remind-button>'] = (
        CheckBox('remind-globally', 1, checked=0).Format())
    replacements['<mm-global-nodupes-button>'] = (
        CheckBox('nodupes-globally', 1, checked=0).Format())

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1))
    if days > 1:
        units = _('days')
    else:
        units = _('day')
    replacements['<mm-pending-days>'] = _('%(days)d %(units)s')

    replacements['<mm-new-address-box>'] = mlist.FormatBox('new-address')
    replacements['<mm-confirm-address-box>'] = mlist.FormatBox(
        'confirm-address')
    replacements['<mm-change-address-button>'] = mlist.FormatButton(
        'change-of-address', _('Change My Address and Name'))
    replacements['<mm-global-change-of-address>'] = CheckBox(
        'changeaddr-globally', 1, checked=0).Format()
    replacements['<mm-fullname-box>'] = mlist.FormatBox(
        'fullname', value=fullname)

    gpgkey = mlist.getGPGKey(user)
    if gpgkey==None:
        gpgkey=""
    replacements['<mm-gpgkey-box>'] = (
        '<textarea name="gpgkey" rows=10 cols=80>%s</textarea>' % gpgkey)
    replacements['<mm-global-gpgkey-changes-button>'] = (
        CheckBox('gpgkey-globally', 1, checked=0).Format())
    replacements['<mm-change-gpgkey-button>'] = (
       mlist.FormatButton('submitgpgkey', _('Submit GPG key')))

    smimekey = mlist.getSMIMEKey(user)
    if not smimekey:
        smimekey=""
    replacements['<mm-smimekey-box>'] = (
        '<textarea name="smimekey" rows=10 cols=80>%s</textarea>' % smimekey)
    replacements['<mm-global-smimekey-changes-button>'] = (
        CheckBox('smimekey-globally', 1, checked=0).Format())
    replacements['<mm-change-smimekey-button>'] = (
       mlist.FormatButton('submitsmimekey', _('Submit S/MIME key')))

    # Create the topics radios.  BAW: what if the list admin deletes a topic,
    # but the user still wants to get that topic message?
    usertopics = mlist.getMemberTopics(user)
    if mlist.topics:
        table = Table(border="0")
        for name, pattern, description, emptyflag in mlist.topics:
            if emptyflag:
                continue
            quotedname = urllib.quote_plus(name)
            details = Link(mlist.GetScriptURL('options') +
                           '/%s/?VARHELP=%s' % (user, quotedname),
                           ' (Details)')
            if name in usertopics:
                checked = 1
            else:
                checked = 0
            table.AddRow([CheckBox('usertopic', quotedname, checked=checked),
                          name + details.Format()])
        topicsfield = table.Format()
    else:
        topicsfield = _('<em>No topics defined</em>')
    replacements['<mm-topics>'] = topicsfield
    replacements['<mm-suppress-nonmatching-topics>'] = (
        mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 0, user))
    replacements['<mm-receive-nonmatching-topics>'] = (
        mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 1, user))

    if cpuser is not None:
        replacements['<mm-case-preserved-user>'] = _('''
You are subscribed to this list with the case-preserved address
<em>%(cpuser)s</em>.''')
    else:
        replacements['<mm-case-preserved-user>'] = ''

    doc.AddItem(mlist.ParseTags('options.html', replacements, userlang))
Exemplo n.º 11
0
def options_page(mlist, doc, user, cpuser, userlang, message=""):
    # The bulk of the document will come from the options.html template, which
    # includes it's own html armor (head tags, etc.).  Suppress the head that
    # Document() derived pages get automatically.
    doc.suppress_head = 1

    if mlist.obscure_addresses:
        presentable_user = Utils.ObscureEmail(user, for_text=1)
        if cpuser is not None:
            cpuser = Utils.ObscureEmail(cpuser, for_text=1)
    else:
        presentable_user = user

    fullname = Utils.uncanonstr(mlist.getMemberName(user), userlang)
    if fullname:
        presentable_user += ", %s" % Utils.websafe(fullname)

    # Do replacements
    replacements = mlist.GetStandardReplacements(userlang)
    replacements["<mm-results>"] = Bold(FontSize("+1", message)).Format()
    replacements["<mm-digest-radio-button>"] = mlist.FormatOptionButton(mm_cfg.Digests, 1, user)
    replacements["<mm-undigest-radio-button>"] = mlist.FormatOptionButton(mm_cfg.Digests, 0, user)
    replacements["<mm-plain-digests-button>"] = mlist.FormatOptionButton(mm_cfg.DisableMime, 1, user)
    replacements["<mm-mime-digests-button>"] = mlist.FormatOptionButton(mm_cfg.DisableMime, 0, user)
    replacements["<mm-global-mime-button>"] = CheckBox("mime-globally", 1, checked=0).Format()
    replacements["<mm-delivery-enable-button>"] = mlist.FormatOptionButton(mm_cfg.DisableDelivery, 0, user)
    replacements["<mm-delivery-disable-button>"] = mlist.FormatOptionButton(mm_cfg.DisableDelivery, 1, user)
    replacements["<mm-disabled-notice>"] = mlist.FormatDisabledNotice(user)
    replacements["<mm-dont-ack-posts-button>"] = mlist.FormatOptionButton(mm_cfg.AcknowledgePosts, 0, user)
    replacements["<mm-ack-posts-button>"] = mlist.FormatOptionButton(mm_cfg.AcknowledgePosts, 1, user)
    replacements["<mm-receive-own-mail-button>"] = mlist.FormatOptionButton(mm_cfg.DontReceiveOwnPosts, 0, user)
    replacements["<mm-dont-receive-own-mail-button>"] = mlist.FormatOptionButton(mm_cfg.DontReceiveOwnPosts, 1, user)
    replacements["<mm-dont-get-password-reminder-button>"] = mlist.FormatOptionButton(
        mm_cfg.SuppressPasswordReminder, 1, user
    )
    replacements["<mm-get-password-reminder-button>"] = mlist.FormatOptionButton(
        mm_cfg.SuppressPasswordReminder, 0, user
    )
    replacements["<mm-public-subscription-button>"] = mlist.FormatOptionButton(mm_cfg.ConcealSubscription, 0, user)
    replacements["<mm-hide-subscription-button>"] = mlist.FormatOptionButton(mm_cfg.ConcealSubscription, 1, user)
    replacements["<mm-dont-receive-duplicates-button>"] = mlist.FormatOptionButton(
        mm_cfg.DontReceiveDuplicates, 1, user
    )
    replacements["<mm-receive-duplicates-button>"] = mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 0, user)
    replacements["<mm-unsubscribe-button>"] = (
        mlist.FormatButton("unsub", _("Unsubscribe"))
        + "<br>"
        + CheckBox("unsubconfirm", 1, checked=0).Format()
        + _("<em>Yes, I really want to unsubscribe</em>")
    )
    replacements["<mm-new-pass-box>"] = mlist.FormatSecureBox("newpw")
    replacements["<mm-confirm-pass-box>"] = mlist.FormatSecureBox("confpw")
    replacements["<mm-change-pass-button>"] = mlist.FormatButton("changepw", _("Change My Password"))
    replacements["<mm-other-subscriptions-submit>"] = mlist.FormatButton("othersubs", _("List my other subscriptions"))
    replacements["<mm-form-start>"] = mlist.FormatFormStart("options", user)
    replacements["<mm-user>"] = user
    replacements["<mm-presentable-user>"] = presentable_user
    replacements["<mm-email-my-pw>"] = mlist.FormatButton("emailpw", (_("Email My Password To Me")))
    replacements["<mm-umbrella-notice>"] = mlist.FormatUmbrellaNotice(user, _("password"))
    replacements["<mm-logout-button>"] = mlist.FormatButton("logout", _("Log out"))
    replacements["<mm-options-submit-button>"] = mlist.FormatButton("options-submit", _("Submit My Changes"))
    replacements["<mm-global-pw-changes-button>"] = CheckBox("pw-globally", 1, checked=0).Format()
    replacements["<mm-global-deliver-button>"] = CheckBox("deliver-globally", 1, checked=0).Format()
    replacements["<mm-global-remind-button>"] = CheckBox("remind-globally", 1, checked=0).Format()
    replacements["<mm-global-nodupes-button>"] = CheckBox("nodupes-globally", 1, checked=0).Format()

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1))
    if days > 1:
        units = _("days")
    else:
        units = _("day")
    replacements["<mm-pending-days>"] = _("%(days)d %(units)s")

    replacements["<mm-new-address-box>"] = mlist.FormatBox("new-address")
    replacements["<mm-confirm-address-box>"] = mlist.FormatBox("confirm-address")
    replacements["<mm-change-address-button>"] = mlist.FormatButton(
        "change-of-address", _("Change My Address and Name")
    )
    replacements["<mm-global-change-of-address>"] = CheckBox("changeaddr-globally", 1, checked=0).Format()
    replacements["<mm-fullname-box>"] = mlist.FormatBox("fullname", value=fullname)

    # Create the topics radios.  BAW: what if the list admin deletes a topic,
    # but the user still wants to get that topic message?
    usertopics = mlist.getMemberTopics(user)
    if mlist.topics:
        table = Table(border="0")
        for name, pattern, description, emptyflag in mlist.topics:
            if emptyflag:
                continue
            quotedname = urllib.quote_plus(name)
            details = Link(mlist.GetScriptURL("options") + "/%s/?VARHELP=%s" % (user, quotedname), " (Details)")
            if name in usertopics:
                checked = 1
            else:
                checked = 0
            table.AddRow([CheckBox("usertopic", quotedname, checked=checked), name + details.Format()])
        topicsfield = table.Format()
    else:
        topicsfield = _("<em>No topics defined</em>")
    replacements["<mm-topics>"] = topicsfield
    replacements["<mm-suppress-nonmatching-topics>"] = mlist.FormatOptionButton(
        mm_cfg.ReceiveNonmatchingTopics, 0, user
    )
    replacements["<mm-receive-nonmatching-topics>"] = mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 1, user)

    if cpuser is not None:
        replacements["<mm-case-preserved-user>"] = _(
            """
You are subscribed to this list with the case-preserved address
<em>%(cpuser)s</em>."""
        )
    else:
        replacements["<mm-case-preserved-user>"] = ""

    doc.AddItem(mlist.ParseTags("options.html", replacements, userlang))
Exemplo n.º 12
0
def main():
    doc = Document()
    doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)

    parts = Utils.GetPathPieces()
    if not parts or len(parts) < 1:
        bad_confirmation(doc)
        doc.AddItem(MailmanLogo())
        print(doc.Format())
        return

    listname = parts[0].lower()
    try:
        mlist = MailList.MailList(listname, lock=0)
    except Errors.MMListError as e:
        # Avoid cross-site scripting attacks
        safelistname = Utils.websafe(listname)
        bad_confirmation(doc, _('No such list <em>%(safelistname)s</em>'))
        doc.AddItem(MailmanLogo())
        # Send this with a 404 status.
        print('Status: 404 Not Found')
        print(doc.Format())
        syslog('error', 'confirm: No such list "%s": %s', listname, e)
        return

    # Set the language for the list
    i18n.set_language(mlist.preferred_language)
    doc.set_language(mlist.preferred_language)

    # Get the form data to see if this is a second-step confirmation
    cgidata = cgi.FieldStorage(keep_blank_values=1)
    try:
        cookie = cgidata.getfirst('cookie')
    except TypeError:
        # Someone crafted a POST with a bad Content-Type:.
        doc.AddItem(Header(2, _("Error")))
        doc.AddItem(Bold(_('Invalid options to CGI script.')))
        # Send this with a 400 status.
        print('Status: 400 Bad Request')
        print(doc.Format())
        return

    if cookie == '':
        ask_for_cookie(mlist, doc, _('Confirmation string was empty.'))
        return

    if not cookie and len(parts) == 2:
        cookie = parts[1]

    if len(parts) > 2:
        bad_confirmation(doc)
        doc.AddItem(mlist.GetMailmanFooter())
        print(doc.Format())
        return

    if not cookie:
        ask_for_cookie(mlist, doc)
        return

    days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
    confirmurl = mlist.GetScriptURL('confirm', absolute=1)
    # Avoid cross-site scripting attacks
    safecookie = Utils.websafe(cookie)
    badconfirmstr = _('''<b>Invalid confirmation string:</b>
    %(safecookie)s.

    <p>Note that confirmation strings expire approximately
    %(days)s days after the initial request.  They also expire if the
    request has already been handled in some way.  If your confirmation
    has expired, please try to re-submit your request.
    Otherwise, <a href="%(confirmurl)s">re-enter</a> your confirmation
    string.''')

    content = mlist.pend_confirm(cookie, expunge=False)
    if content is None:
        bad_confirmation(doc, badconfirmstr)
        doc.AddItem(mlist.GetMailmanFooter())
        print(doc.Format())
        return

    try:
        if content[0] == Pending.SUBSCRIPTION:
            if cgidata.getfirst('cancel'):
                subscription_cancel(mlist, doc, cookie)
            elif cgidata.getfirst('submit'):
                subscription_confirm(mlist, doc, cookie, cgidata)
            else:
                subscription_prompt(mlist, doc, cookie, content[1])
        elif content[0] == Pending.UNSUBSCRIPTION:
            try:
                if cgidata.getfirst('cancel'):
                    unsubscription_cancel(mlist, doc, cookie)
                elif cgidata.getfirst('submit'):
                    unsubscription_confirm(mlist, doc, cookie)
                else:
                    unsubscription_prompt(mlist, doc, cookie, *content[1:])
            except Errors.NotAMemberError:
                doc.addError(
                    _("""The address requesting unsubscription is not
                a member of the mailing list.  Perhaps you have already been
                unsubscribed, e.g. by the list administrator?"""))
                # Expunge this record from the pending database.
                expunge(mlist, cookie)
        elif content[0] == Pending.CHANGE_OF_ADDRESS:
            if cgidata.getfirst('cancel'):
                addrchange_cancel(mlist, doc, cookie)
            elif cgidata.getfirst('submit'):
                addrchange_confirm(mlist, doc, cookie)
            else:
                # Watch out for users who have unsubscribed themselves in the
                # meantime!
                try:
                    addrchange_prompt(mlist, doc, cookie, *content[1:])
                except Errors.NotAMemberError:
                    doc.addError(
                        _("""The address requesting to be changed has
                    been subsequently unsubscribed.  This request has been
                    cancelled."""))
                    # Expunge this record from the pending database.
                    expunge(mlist, cookie)
        elif content[0] == Pending.HELD_MESSAGE:
            if cgidata.getfirst('cancel'):
                heldmsg_cancel(mlist, doc, cookie)
            elif cgidata.getfirst('submit'):
                heldmsg_confirm(mlist, doc, cookie)
            else:
                heldmsg_prompt(mlist, doc, cookie, *content[1:])
        elif content[0] == Pending.RE_ENABLE:
            if cgidata.getfirst('cancel'):
                reenable_cancel(mlist, doc, cookie)
            elif cgidata.getfirst('submit'):
                reenable_confirm(mlist, doc, cookie)
            else:
                reenable_prompt(mlist, doc, cookie, *content[1:])
        else:
            bad_confirmation(doc, _('System error, bad content: %(content)s'))
    except Errors.MMBadConfirmation:
        bad_confirmation(doc, badconfirmstr)

    doc.AddItem(mlist.GetMailmanFooter())
    print(doc.Format())
Exemplo n.º 13
0
 def getValue(self, mlist, kind, varname, params):
     if varname not in ('bounce_info_stale_after',
                        'bounce_you_are_disabled_warnings_interval'):
         return None
     return int(getattr(mlist, varname) / days(1))
Exemplo n.º 14
0
def reenable_prompt(mlist, doc, cookie, list, member):
    title = _('Re-enable mailing list membership')
    doc.SetTitle(title)
    form = Form(mlist.GetScriptURL('confirm', 1))
    table = Table(border=0, width='100%')
    table.AddRow([Center(Bold(FontAttr(title, size='+1')))])
    table.AddCellInfo(table.GetCurrentRowIndex(), 0,
                      colspan=2, bgcolor=mm_cfg.WEB_HEADER_COLOR)

    lang = mlist.getMemberLanguage(member)
    i18n.set_language(lang)
    doc.set_language(lang)

    realname = mlist.real_name
    info = mlist.getBounceInfo(member)
    if not info:
        listinfourl = mlist.GetScriptURL('listinfo', absolute=1)
        # They've already be unsubscribed
        table.AddRow([_("""We're sorry, but you have already been unsubscribed
        from this mailing list.  To re-subscribe, please visit the
        <a href="%(listinfourl)s">list information page</a>.""")])
        return

    date = time.strftime('%A, %B %d, %Y',
                         time.localtime(time.mktime(info.date + (0,)*6)))
    daysleft = int(info.noticesleft *
                   mlist.bounce_you_are_disabled_warnings_interval /
                   mm_cfg.days(1))
    # BAW: for consistency this should be changed to 'fullname' or the above
    # 'fullname's should be changed to 'username'.  Don't want to muck with
    # the i18n catalogs though.
    username = mlist.getMemberName(member)
    if username is None:
        username = _('<em>not available</em>')
    else:
        username = Utils.websafe(Utils.uncanonstr(username, lang))

    table.AddRow([_("""Your membership in the %(realname)s mailing list is
    currently disabled due to excessive bounces.  Your confirmation is
    required in order to re-enable delivery to your address.  We have the
    following information on file:

    <ul><li><b>Member address:</b> %(member)s
        <li><b>Member name:</b> %(username)s
        <li><b>Last bounce received on:</b> %(date)s
        <li><b>Approximate number of days before you are permanently removed
               from this list:</b> %(daysleft)s
    </ul>

    Hit the <em>Re-enable membership</em> button to resume receiving postings
    from the mailing list.  Or hit the <em>Cancel</em> button to defer
    re-enabling your membership.
    """)])

    table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2)
    table.AddRow([Hidden('cookie', cookie)])
    table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2)
    table.AddRow([SubmitButton('submit', _('Re-enable membership')),
                  SubmitButton('cancel', _('Cancel'))])

    form.AddItem(table)
    doc.AddItem(form)
Exemplo n.º 15
0
 def getValue(self, mlist, kind, varname, params):
     if varname not in ('bounce_info_stale_after',
                        'bounce_you_are_disabled_warnings_interval'):
         return None
     return int(getattr(mlist, varname) / days(1))
Exemplo n.º 16
0
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Message
from Mailman import MemberAdaptor
from Mailman import Pending
from Mailman.Errors import MMUnknownListError
from Mailman.Logging.Syslog import syslog
from Mailman import i18n

EMPTYSTRING = ''

# This constant is supposed to represent the day containing the first midnight
# after the epoch.  We'll add (0,)*6 to this tuple to get a value appropriate
# for time.mktime().
ZEROHOUR_PLUSONEDAY = time.localtime(mm_cfg.days(1))[:3]


def _(s):
    return s


REASONS = {
    MemberAdaptor.BYBOUNCE: _('due to excessive bounces'),
    MemberAdaptor.BYUSER: _('by yourself'),
    MemberAdaptor.BYADMIN: _('by the list administrator'),
    MemberAdaptor.UNKNOWN: _('for unknown reasons'),
}

_ = i18n._
def process(res, args):
    mlist = res.mlist
    if len(args) != 1:
        res.results.append(_('Usage:'))
        res.results.append(gethelp(mlist))
        return STOP
    cookie = args[0]
    try:
        results = mlist.ProcessConfirmation(cookie, res.msg)
    except Errors.MMBadConfirmation as e:
        # Express in approximate days
        days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5)
        res.results.append(_("""\
Invalid confirmation string.  Note that confirmation strings expire
approximately %(days)s days after the initial request.  They also expire if
the request has already been handled in some way.  If your confirmation has
expired, please try to re-submit your original request or message."""))
    except Errors.MMNeedApproval:
        res.results.append(_("""\
Your request has been forwarded to the list moderator for approval."""))
    except Errors.MMAlreadyAMember:
        # Some other subscription request for this address has
        # already succeeded.
        res.results.append(_('You are already subscribed.'))
    except Errors.NotAMemberError:
        # They've already been unsubscribed
        res.results.append(_("""\
You are not currently a member.  Have you already unsubscribed or changed
your email address?"""))
    except Errors.MembershipIsBanned:
        owneraddr = mlist.GetOwnerEmail()
        res.results.append(_("""\
You are currently banned from subscribing to this list.  If you think this
restriction is erroneous, please contact the list owners at
%(owneraddr)s."""))
    except Errors.HostileSubscriptionError:
        res.results.append(_("""\
You were not invited to this mailing list.  The invitation has been discarded,
and both list administrators have been alerted."""))
    except Errors.MMBadPasswordError:
        res.results.append(_("""\
Bad approval password given.  Held message is still being held."""))
    else:
        if ((results[0] == Pending.SUBSCRIPTION and mlist.send_welcome_msg)
            or
            (results[0] == Pending.UNSUBSCRIPTION and mlist.send_goodbye_msg)):
            # We don't also need to send a confirmation succeeded message
            res.respond = 0
        else:
            if results[0] == Pending.HELD_MESSAGE:
                if results[1] == mm_cfg.APPROVE:
                    res.results.append(_('Confirmation succeeded') + 
                               ' (' + _('Approve') + ')')
                else:
                    res.results.append(_('Confirmation succeeded') + 
                               ' (' + _('Discard') + ')')
            else:
                res.results.append(_('Confirmation succeeded'))
            # Consume any other confirmation strings with the same cookie so
            # the user doesn't get a misleading "unprocessed" message.
            # Also consume any Approve(d): line as it was processed.
            match = 'confirm ' + cookie
            unprocessed = []
            for line in res.commands:
                try:
                    if (line.lstrip() == match or
                            line.lstrip().lower().startswith('approved:') or
                            line.lstrip().lower().startswith('approve:')):
                        continue
                except UnicodeError:
                    pass
                unprocessed.append(line)
            res.commands = unprocessed
    # Process just one confirmation string per message
    return STOP