summaryrefslogtreecommitdiff
path: root/Mailman
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Handlers/Hold.py261
1 files changed, 0 insertions, 261 deletions
diff --git a/Mailman/Handlers/Hold.py b/Mailman/Handlers/Hold.py
deleted file mode 100644
index 96ed02c93..000000000
--- a/Mailman/Handlers/Hold.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Copyright (C) 1998-2007 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-"""Determine whether this message should be held for approval.
-
-This modules tests only for hold situations, such as messages that are too
-large, messages that have potential administrivia, etc. Definitive approvals
-or denials are handled by a different module.
-
-If no determination can be made (i.e. none of the hold criteria matches), then
-we do nothing. If the message must be held for approval, then the hold
-database is updated and any administrator notification messages are sent.
-Finally an exception is raised to let the pipeline machinery know that further
-message handling should stop.
-"""
-
-from __future__ import with_statement
-
-import email
-import logging
-import email.utils
-
-from email.mime.message import MIMEMessage
-from email.mime.text import MIMEText
-from types import ClassType
-from zope.interface import implements
-
-from Mailman import Errors
-from Mailman import Message
-from Mailman import Utils
-from Mailman import i18n
-from Mailman.app.moderator import hold_message
-from Mailman.app.replybot import autorespond_to_sender
-from Mailman.configuration import config
-from Mailman.interfaces import IPendable
-
-log = logging.getLogger('mailman.vette')
-
-# Play footsie with _ so that the following are marked as translated, but
-# aren't actually translated until we need the text later on.
-def _(s):
- return s
-
-__i18n_templates__ = True
-
-
-
-class ForbiddenPoster(Errors.HoldMessage):
- reason = _('Sender is explicitly forbidden')
- rejection = _('You are forbidden from posting messages to this list.')
-
-class ModeratedPost(Errors.HoldMessage):
- reason = _('Post to moderated list')
- rejection = _('Your message was deemed inappropriate by the moderator.')
-
-class NonMemberPost(Errors.HoldMessage):
- reason = _('Post by non-member to a members-only list')
- rejection = _('Non-members are not allowed to post messages to this list.')
-
-class NotExplicitlyAllowed(Errors.HoldMessage):
- reason = _('Posting to a restricted list by sender requires approval')
- rejection = _('This list is restricted; your message was not approved.')
-
-class TooManyRecipients(Errors.HoldMessage):
- reason = _('Too many recipients to the message')
- rejection = _('Please trim the recipient list; it is too long.')
-
-class ImplicitDestination(Errors.HoldMessage):
- reason = _('Message has implicit destination')
- rejection = _('''Blind carbon copies or other implicit destinations are
-not allowed. Try reposting your message by explicitly including the list
-address in the To: or Cc: fields.''')
-
-class Administrivia(Errors.HoldMessage):
- reason = _('Message may contain administrivia')
-
- def rejection_notice(self, mlist):
- listurl = mlist.script_url('listinfo')
- request = mlist.request_address
- return _("""Please do *not* post administrative requests to the mailing
-list. If you wish to subscribe, visit $listurl or send a message with the
-word `help' in it to the request address, $request, for further
-instructions.""")
-
-class SuspiciousHeaders(Errors.HoldMessage):
- reason = _('Message has a suspicious header')
- rejection = _('Your message had a suspicious header.')
-
-class MessageTooBig(Errors.HoldMessage):
- def __init__(self, msgsize, limit):
- Errors.HoldMessage.__init__(self)
- self.__msgsize = msgsize
- self.__limit = limit
-
- def reason_notice(self):
- size = self.__msgsize
- limit = self.__limit
- return _('''Message body is too big: $size bytes with a limit of
-$limit KB''')
-
- def rejection_notice(self, mlist):
- kb = self.__limit
- return _('''Your message was too big; please trim it to less than
-$kb KB in size.''')
-
-class ModeratedNewsgroup(ModeratedPost):
- reason = _('Posting to a moderated newsgroup')
-
-
-
-# And reset the translator
-_ = i18n._
-
-
-
-def ackp(msg):
- ack = msg.get('x-ack', '').lower()
- precedence = msg.get('precedence', '').lower()
- if ack <> 'yes' and precedence in ('bulk', 'junk', 'list'):
- return 0
- return 1
-
-
-
-class HeldMessagePendable(dict):
- implements(IPendable)
- PEND_KEY = 'held message'
-
-
-
-def process(mlist, msg, msgdata):
- if msgdata.get('approved'):
- return
- # Get the sender of the message
- listname = mlist.list_name
- adminaddr = listname + '-admin'
- sender = msg.get_sender()
- # Special case an ugly sendmail feature: If there exists an alias of the
- # form "owner-foo: bar" and sendmail receives mail for address "foo",
- # sendmail will change the envelope sender of the message to "bar" before
- # delivering. This feature does not appear to be configurable. *Boggle*.
- if not sender or sender[:len(listname)+6] == adminaddr:
- sender = msg.get_sender(use_envelope=0)
-
-
-
-def hold_for_approval(mlist, msg, msgdata, exc):
- # BAW: This should really be tied into the email confirmation system so
- # that the message can be approved or denied via email as well as the
- # web.
- if isinstance(exc, ClassType) or isinstance(exc, type):
- # Go ahead and instantiate it now.
- exc = exc()
- listname = mlist.list_name
- sender = msgdata.get('sender', msg.get_sender())
- usersubject = msg.get('subject')
- charset = Utils.GetCharSet(mlist.preferred_language)
- if usersubject:
- usersubject = Utils.oneline(usersubject, charset)
- else:
- usersubject = _('(no subject)')
- message_id = msg.get('message-id', 'n/a')
- owneraddr = mlist.owner_address
- adminaddr = mlist.bounces_address
- requestaddr = mlist.request_address
- # We need to send both the reason and the rejection notice through the
- # translator again, because of the games we play above
- reason = Utils.wrap(exc.reason_notice())
- msgdata['rejection_notice'] = Utils.wrap(exc.rejection_notice(mlist))
- id = hold_message(mlist, msg, msgdata, reason)
- # Now we need to craft and send a message to the list admin so they can
- # deal with the held message.
- d = {'listname' : listname,
- 'hostname' : mlist.host_name,
- 'reason' : _(reason),
- 'sender' : sender,
- 'subject' : usersubject,
- 'admindb_url': mlist.script_url('admindb'),
- }
- # We may want to send a notification to the original sender too
- fromusenet = msgdata.get('fromusenet')
- # Since we're sending two messages, which may potentially be in different
- # languages (the user's preferred and the list's preferred for the admin),
- # we need to play some i18n games here. Since the current language
- # context ought to be set up for the user, let's craft his message first.
- #
- # This message should appear to come from <list>-admin so as to handle any
- # bounce processing that might be needed.
- pendable = HeldMessagePendable(type=HeldMessagePendable.PEND_KEY, id=id)
- token = config.db.pendings.add(pendable)
- # Get the language to send the response in. If the sender is a member,
- # then send it in the member's language, otherwise send it in the mailing
- # list's preferred language.
- member = mlist.members.get_member(sender)
- lang = (member.preferred_language if member else mlist.preferred_language)
- if not fromusenet and ackp(msg) and mlist.respond_to_post_requests and \
- autorespond_to_sender(mlist, sender, lang):
- # Get a confirmation token
- d['confirmurl'] = '%s/%s' % (
- mlist.script_url('confirm'), token)
- lang = msgdata.get('lang', lang)
- subject = _('Your message to $listname awaits moderator approval')
- text = Utils.maketext('postheld.txt', d, lang=lang, mlist=mlist)
- nmsg = Message.UserNotification(sender, adminaddr, subject, text, lang)
- nmsg.send(mlist)
- # Now the message for the list owners. Be sure to include the list
- # moderators in this message. This one should appear to come from
- # <list>-owner since we really don't need to do bounce processing on it.
- if mlist.admin_immed_notify:
- # Now let's temporarily set the language context to that which the
- # admin is expecting.
- with i18n.using_language(mlist.preferred_language):
- lang = mlist.preferred_language
- charset = Utils.GetCharSet(lang)
- # We need to regenerate or re-translate a few values in d
- d['reason'] = _(reason)
- d['subject'] = usersubject
- # craft the admin notification message and deliver it
- subject = _('$listname post from $sender requires approval')
- nmsg = Message.UserNotification(owneraddr, owneraddr, subject,
- lang=lang)
- nmsg.set_type('multipart/mixed')
- text = MIMEText(
- Utils.maketext('postauth.txt', d, raw=1, mlist=mlist),
- _charset=charset)
- dmsg = MIMEText(Utils.wrap(_("""\
-If you reply to this message, keeping the Subject: header intact, Mailman will
-discard the held message. Do this if the message is spam. If you reply to
-this message and include an Approved: header with the list password in it, the
-message will be approved for posting to the list. The Approved: header can
-also appear in the first line of the body of the reply.""")),
- _charset=Utils.GetCharSet(lang))
- dmsg['Subject'] = 'confirm ' + token
- dmsg['Sender'] = requestaddr
- dmsg['From'] = requestaddr
- dmsg['Date'] = email.utils.formatdate(localtime=True)
- dmsg['Message-ID'] = email.utils.make_msgid()
- nmsg.attach(text)
- nmsg.attach(MIMEMessage(msg))
- nmsg.attach(MIMEMessage(dmsg))
- nmsg.send(mlist, **{'tomoderators': 1})
- # Log the held message
- log.info('%s post from %s held, message-id=%s: %s',
- listname, sender, message_id, reason)
- # raise the specific MessageHeld exception to exit out of the message
- # delivery pipeline
- raise exc