/usr/lib/mailman/Mailman/Handlers/Sendmail.py is in mailman 1:2.1.16-2ubuntu0.5.
This file is owned by root:list, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # Copyright (C) 1998,1999,2000,2001,2002 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.
"""Deliver a message via command-line drop-off.
WARNING WARNING WARNING: This module is provided for example purposes only.
It should not be used in a production environment for reasons described
below. Because of this, you must explicitly enable it with by editing the
code. See the WARN section in the process() function.
This module delivers the message via the command line interface to the
sendmail program. It should work for sendmail clones like Postfix. It is
expected that sendmail handles final delivery, message queueing, etc. The
recipient list is only trivially split so that the command line is less than
about 3k in size.
SECURITY WARNING: Because this module uses os.popen(), it goes through the
shell. This module does not scan the arguments for potential exploits and so
it should be considered unsafe for production use. For performance reasons,
it's not recommended either -- use the SMTPDirect delivery module instead,
even if you're using the sendmail MTA.
DUPLICATES WARNING: Using this module can cause duplicates to be delivered to
your membership, depending on your MTA! E.g. It is known that if you're using
the sendmail MTA, and if a message contains a single dot on a line by itself,
your list members will receive many duplicates.
"""
import string
import os
from Mailman import mm_cfg
from Mailman import Errors
from Mailman.Logging.Syslog import syslog
MAX_CMDLINE = 3000
def process(mlist, msg, msgdata):
"""Process the message object for the given list.
The message object is an instance of Mailman.Message and must be fully
prepared for delivery (i.e. all the appropriate headers must be set). The
message object can have the following attributes:
recips - the list of recipients for the message (required)
This function processes the message by handing off the delivery of the
message to a sendmail (or sendmail clone) program. It can raise a
SendmailHandlerError if an error status was returned by the sendmail
program.
"""
# WARN: If you've read the warnings above and /still/ insist on using this
# module, you must comment out the following line. I still recommend you
# don't do this!
assert 0, 'Use of the Sendmail.py delivery module is highly discouraged'
recips = msgdata.get('recips')
if not recips:
# Nobody to deliver to!
return
# Use -f to set the envelope sender
cmd = mm_cfg.SENDMAIL_CMD + ' -f ' + mlist.GetBouncesEmail() + ' '
# make sure the command line is of a manageable size
recipchunks = []
currentchunk = []
chunklen = 0
for r in recips:
currentchunk.append(r)
chunklen = chunklen + len(r) + 1
if chunklen > MAX_CMDLINE:
recipchunks.append(string.join(currentchunk))
currentchunk = []
chunklen = 0
# pick up the last one
if chunklen:
recipchunks.append(string.join(currentchunk))
# get all the lines of the message, since we're going to do this over and
# over again
msgtext = str(msg)
msglen = len(msgtext)
# cycle through all chunks
failedrecips = []
for chunk in recipchunks:
# TBD: SECURITY ALERT. This invokes the shell!
fp = os.popen(cmd + chunk, 'w')
fp.write(msgtext)
status = fp.close()
if status:
errcode = (status & 0xff00) >> 8
syslog('post', 'post to %s from %s, size=%d, failure=%d',
mlist.internal_name(), msg.get_sender(),
msglen, errcode)
# TBD: can we do better than this? What if only one recipient out
# of the entire chunk failed?
failedrecips.append(chunk)
# Log the successful post
syslog('post', 'post to %s from %s, size=%d, success',
mlist.internal_name(), msg.get_sender(), msglen)
if failedrecips:
msgdata['recips'] = failedrecips
raise Errors.SomeRecipientsFailed
|