#! /usr/bin/env python
#
# Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

"""Accept posts to a list and handle them properly.

This script is invoked via the mail wrapper.

Stdin is the mail message, and argv[1] is the name of the target mailing
list.  If there's an argv[2], then this post was gated from news, and
thus should not be re-posted to news if the list gates to a newsgroup.
"""


# Todo: check size of To: list < 100
# Send back why the post was rejected.

import sys
import paths
from Mailman import MailList
from Mailman import Message
from Mailman import Errors
from Mailman import Utils
from Mailman.Logging.Utils import LogStdErr

LogStdErr("error", "post")

# Only let one program run at once per list.

# TODO: This can fail, and should send back an error message when it does.
mlist = MailList.MailList(sys.argv[1])
if len(sys.argv) > 2:
    # assert sys.argv[1] == 'fromusenet'
    fromusenet = 1
else:
    fromusenet = 0
try:
    prog = mlist.filter_prog
    if prog:
	import os, __main__
	file = os.path.join(paths.prefix, 'filters', prog)
	try:
	    execfile(file)
	    text = __main__.mailman_text
	except:
	    text = sys.stdin.read()
    else:
	text = sys.stdin.read()
    msg = Message.IncomingMessage(text)
    # this attribute is a flag to both the GatewayManager and the approval
    # mechanism.  When a message originates from Usenet, we do not want to
    # post it back there again.  Also, such messages are never held for
    # approval.  It makes no sense to send an acknowledgement to the author --
    # who may not even know of the mailing list's existance.  It *might* still
    # make sense to hold the message for approval, but I suspect that's just
    # more of a PITA for the list owner.
    msg.fromusenet = fromusenet
    try:
	mlist.Post(msg, approved=fromusenet)
    except Errors.MMLoopingPost:
        # let the list admin know this happened, but don't otherwise hold the
        # message for approval.
        sys.stderr.write('Message already came through this list\n')
        map(sys.stderr.write, msg.headers)
        sys.stderr.write('[body of message suppressed]\n')
        mlist.SendTextToUser(
            subject='Message loop detected [message discarded]',
            text=Utils.SnarfMessage(msg)[1],
            recipient=mlist.GetAdminEmail())
    except Errors.MMNeedApproval, err_msg:
	if (mlist.dont_respond_to_post_requests
            or err_msg == Errors.MODERATED_LIST_MSG):
            # Do not send hold-for-approval notices for moderated messages.
            mlist.Unlock()
	    sys.exit(0)
	the_sender = msg.GetSender()
	subj = msg.getheader('subject')
	if not subj:
	    subj = '[no subject]'
        body = Utils.maketext(
            'postheld.txt',
            {'list_name': mlist.real_name,
             'subject'  : subj,
             'reason'   : err_msg,
             })
	mlist.SendTextToUser(
            subject = 'Mail sent to %s' % mlist.real_name,
            recipient = the_sender,
            text = body)
# Let another process run.
finally:
    mlist.Unlock()
