Snapshot release 20030306-1134
Charles Cazabon <[email protected]> 6 Mar 2003 17:35:00 -0000
| Newsgroups | gmane.mail.bikini.devel |
|---|---|
| Message-ID | <[email protected]> |
Snapshot 20030306-1134 released and uploaded. From the CHANGELOG:
2003-03-06
Move configuration defaults from constants.py to config.py.
Add the sendmessage submodule. This provides methods for making SEND work
with qmail-queue as before (the default), new-inject (for cleaning up
headers before sending, /usr/sbin/sendmail, pseudo-sendmail, or the special
"null" method, which forbids the server from sending mail. Change
defaults['sendmethod'] in config.py to configure. If you have another
method to add, please do so and send me a diff.
Diff follows.
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/classes.py bikini-20030306-1134/bikini/classes.py
--- bikini-20030306-0908/bikini/classes.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/classes.py Thu Mar 6 11:34:36 2003
@@ -4,6 +4,7 @@
import os
import signal
+import config
from errors import *
from constants import *
from utilities import *
@@ -105,7 +106,7 @@
self.respond ('success', 'ok')
###################################
- def timeout (self, timeout=defaults['timeout']):
+ def timeout (self, timeout=config.defaults['timeout']):
'''Start a timer.
'''
log (TRACE, 'timeout %i\n' % timeout)
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/config.py bikini-20030306-1134/bikini/config.py
--- bikini-20030306-0908/bikini/config.py Wed Dec 31 18:00:00 1969
+++ bikini-20030306-1134/bikini/config.py Thu Mar 6 11:34:36 2003
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+import os
+import string
+import sendmessage
+
+from constants import loglevels
+
+defaults = {
+ 'loglevel' : loglevels[os.environ.get ('LOGLEVEL', 'DEBUG')],
+ 'timeout' : int (os.environ.get ('TIMEOUT', 180)), # three minutes
+ 'newdirmode' : string.atoi (os.environ.get ('TIMEOUT', '0700'), 0),
+ 'maxauthtries' : int (os.environ.get ('TIMEOUT', 5)),
+ 'serverpath' : '/usr/lib/python2.2/site-packages/bikini/server.py',
+ 'sendmethod' : sendmessage.qmailqueue,
+
+ 'anonymous-mailstore' : '/tmp/bikini-mail/',
+ 'anonymous-user' : 'nobody',
+}
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/constants.py bikini-20030306-1134/bikini/constants.py
--- bikini-20030306-0908/bikini/constants.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/constants.py Thu Mar 6 11:34:36 2003
@@ -1,7 +1,6 @@
#!/usr/bin/python
import os
-import string
# Components of stack trace (indices to tuple)
FILENAME, LINENO, FUNCNAME = 0, 1, 2 #SOURCELINE = 3 ; not used
@@ -35,14 +34,3 @@
'AUTH=LOGIN', # 'auth login' support
'MESSAGE-SIZE %d' % os.environ.get ('DATABYTES', 0), # max message size for put
)
-
-defaults = {
- 'loglevel' : loglevels[os.environ.get ('LOGLEVEL', 'DEBUG')],
- 'timeout' : int (os.environ.get ('TIMEOUT', 180)), # three minutes
- 'newdirmode' : string.atoi (os.environ.get ('TIMEOUT', '0700'), 0),
- 'maxauthtries' : int (os.environ.get ('TIMEOUT', 5)),
- 'serverpath' : '/usr/lib/python2.2/site-packages/bikini/server.py',
-
- 'anonymous-mailstore' : '/tmp/bikini-mail/',
- 'anonymous-user' : 'nobody',
-}
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/sasl.py bikini-20030306-1134/bikini/sasl.py
--- bikini-20030306-0908/bikini/sasl.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/sasl.py Thu Mar 6 11:34:36 2003
@@ -3,7 +3,7 @@
import sys
from errors import *
-from constants import defaults
+import config
class Mechanism:
def checkpassword(self):
@@ -55,11 +55,11 @@
class ANONYMOUS(Mechanism):
def __init__(self, unused):
- self.username = defaults['anonymous-user']
+ self.username = config.defaults['anonymous-user']
self.password = None
self.pwchecker = self
self.checkpassword ()
- self.dir = defaults['anonymous-mailstore']
+ self.dir = config.defaults['anonymous-mailstore']
def check (self, *unused):
return 0
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/sendmessage.py bikini-20030306-1134/bikini/sendmessage.py
--- bikini-20030306-0908/bikini/sendmessage.py Wed Dec 31 18:00:00 1969
+++ bikini-20030306-1134/bikini/sendmessage.py Thu Mar 6 11:34:36 2003
@@ -0,0 +1,161 @@
+#!/usr/bin/python2.2
+
+import os
+import time
+
+from errors import *
+from constants import *
+from utilities import *
+
+READ, WRITE = 0, 1
+
+#
+# Functions to send messages with
+#
+
+#######################################
+def null (path, envelope):
+ '''Fail to queue a message. Use this to prohibit the bikini server from
+ sending mail.
+ '''
+ log (TRACE, 'path %s envelope %s\n' % (path, envelope))
+ raise PermanentCommandError, 'SEND prohibited'
+
+#######################################
+def qmailqueue (path, envelope):
+ '''Queue message using qmail-queue. Sends message exactly as is.
+ '''
+ log (TRACE, 'path %s envelope %s\n' % (path, envelope))
+ cmd = '/var/qmail/bin/qmail-queue'
+ try:
+ messagepipe = os.pipe ()
+ envelopepipe = os.pipe ()
+ child_pid = os.fork ()
+ if child_pid == 0:
+ # child
+ os.close (messagepipe[WRITE])
+ os.close (envelopepipe[WRITE])
+ os.close (0)
+ os.close (1)
+ os.close (2)
+ os.dup2 (messagepipe[READ], 0)
+ os.dup2 (envelopepipe[READ], 1)
+ os.execl (cmd, cmd)
+ raise TemporaryCommandError, 'exec failed'
+ # Parent
+ log (DEBUG, 'forked pid %i\n' % child_pid)
+ os.close (messagepipe[READ])
+ os.close (envelopepipe[READ])
+ # Write message
+ os.write (messagepipe[WRITE], open (path, 'rb').read ())
+ os.close (messagepipe[WRITE])
+ # Write envelope
+ parts = envelope.split ('\0')
+ os.write (envelopepipe[WRITE], 'F%s\0' % parts[0])
+ for recip in parts[1:-1]:
+ os.write (envelopepipe[WRITE], 'T%s\0' % recip)
+ os.write (envelopepipe[WRITE], '\0')
+ os.close (envelopepipe[WRITE])
+ tries = 0
+ while tries < 10:
+ pid, rc = os.waitpid (child_pid, os.WNOHANG)
+ log (TRACE, 'os.waitpid returned %i, %s\n' % (pid, rc))
+ if pid == child_pid and os.WIFEXITED (rc):
+ if os.WEXITSTATUS (rc) == 0:
+ log (TRACE, 'message queued\n')
+ return 'this is a receipt, should be a queue id or similar' # ???
+ log (TRACE, 'message not queued (exited %i)\n' % os.WEXITSTATUS (rc))
+ raise TemporaryCommandError, '%s exited %i' % (cmd, os.WEXITSTATUS (rc))
+ time.sleep (1)
+ log (ERROR, 'child never exited?\n')
+ raise TemporaryCommandError, '%s never exited' % cmd
+
+ except UnhandledException, txt:
+ raise TemporaryCommandError, 'failure queuing message: %s' % txt
+
+#######################################
+class sendmessageBase:
+ '''Queue message using a command which takes the envelope as arguments and
+ reads stdin for the message content, returning only an exit code.
+ '''
+ ###################################
+ def __init__ (self, path, envelope):
+ log (TRACE, 'path %s envelope %s\n' % (path, envelope))
+ parts = envelope.split ('\0')
+ self.sender = parts[0]
+ self.recips = parts [1:-1]
+ self.setup ()
+ try:
+ messagepipe = os.pipe ()
+ child_pid = os.fork ()
+ if child_pid == 0:
+ # child
+ os.close (messagepipe[WRITE])
+ os.close (0)
+ os.dup2 (messagepipe[READ], 0)
+ os.execv (self.cmd, self.args)
+ raise TemporaryCommandError, 'exec failed'
+ # Parent
+ log (DEBUG, 'forked pid %i\n' % child_pid)
+ os.close (messagepipe[READ])
+ # Write message
+ os.write (messagepipe[WRITE], open (path, 'rb').read ())
+ os.close (messagepipe[WRITE])
+ tries = 0
+ while tries < 10:
+ pid, rc = os.waitpid (child_pid, os.WNOHANG)
+ log (TRACE, 'os.waitpid returned %i, %s\n' % (pid, rc))
+ if pid == child_pid and os.WIFEXITED (rc):
+ if os.WEXITSTATUS (rc) == 0:
+ log (TRACE, 'message queued\n')
+ self.rc = 'this is a receipt, should be a queue id or similar' # ???
+ return
+ log (TRACE, 'message not queued (exited %i)\n' % os.WEXITSTATUS (rc))
+ raise TemporaryCommandError, '%s exited %i' % (self.cmd, os.WEXITSTATUS (rc))
+ time.sleep (1)
+ log (ERROR, 'child never exited?\n')
+ raise TemporaryCommandError, '%s never exited' % self.cmd
+
+ except UnhandledException, txt:
+ raise TemporaryCommandError, 'failure queuing message: %s' % txt
+
+ ###################################
+ def __str__ (self):
+ return self.rc
+
+#######################################
+class newinject (sendmessageBase):
+ '''Queue message using new-inject. new-inject cleans up the header before
+ queuing the mail. new-inject is part of the mess822 package.
+ '''
+ ###################################
+ def setup (self):
+ log (TRACE)
+ self.cmd = '/usr/bin/new-inject'
+ self.args = [self.cmd, '-a', '-f', self.sender, '--']
+ self.args.extend (self.recips)
+
+#######################################
+class sendmail (sendmessageBase):
+ '''Queue message using a "real" sendmail interface.
+ '''
+ ###################################
+ def setup (self):
+ log (TRACE)
+ self.cmd = '/usr/sbin/sendmail'
+ self.args = [self.cmd, '-U', '-i', '-O', 'DeliveryMode=q', '-O', 'ErrorMode=q', '-f', self.sender, '--']
+ self.args.extend (self.recips)
+
+#######################################
+class simple_sendmail (sendmessageBase):
+ '''Queue message using a sendmail-type interface that doesn't understand
+ some options. Use this if the default sendmail interface doesn't work
+ for you and there isn't a better, more MTA-specific interface for your
+ MTA.
+ '''
+ ###################################
+ def setup (self):
+ log (TRACE)
+ self.cmd = '/usr/sbin/sendmail'
+ self.args = [self.cmd, '-i', '-f', self.sender, '--']
+ self.args.extend (self.recips)
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/server.py bikini-20030306-1134/bikini/server.py
--- bikini-20030306-0908/bikini/server.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/server.py Thu Mar 6 11:34:36 2003
@@ -49,6 +49,7 @@
from classes import *
from utilities import *
from constants import *
+import config
#
# Globals
@@ -421,7 +422,7 @@
or len (parts) < 3): # Not enough parts
raise bSyntaxError, 'bad envelope format'
- receipt = deliver_message (f, envelope)
+ receipt = config.defaults['sendmethod'] (f, envelope)
except KeyError, err:
raise PermanentCommandError, 'no such message %s' % path
@@ -446,7 +447,7 @@
except PermanentCommandError:
raise PermanentCommandError, 'directory %s already exists' % path
try:
- os.mkdir (path, defaults['newdirmode'])
+ os.mkdir (path, config.defaults['newdirmode'])
self.dirs.append (path + '/')
self.dirs.sort ()
except OSError, err:
@@ -486,10 +487,10 @@
except PermanentCommandError:
raise PermanentCommandError, 'directory %s already exists' % path
try:
- os.mkdir (path, defaults['newdirmode'])
- os.mkdir (os.path.join (path, 'cur'), defaults['newdirmode'])
- os.mkdir (os.path.join (path, 'new'), defaults['newdirmode'])
- os.mkdir (os.path.join (path, 'tmp'), defaults['newdirmode'])
+ os.mkdir (path, config.defaults['newdirmode'])
+ os.mkdir (os.path.join (path, 'cur'), config.defaults['newdirmode'])
+ os.mkdir (os.path.join (path, 'new'), config.defaults['newdirmode'])
+ os.mkdir (os.path.join (path, 'tmp'), config.defaults['newdirmode'])
self.dirs.append (path)
self.dirs.sort ()
except OSError, err:
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/serverauth.py bikini-20030306-1134/bikini/serverauth.py
--- bikini-20030306-0908/bikini/serverauth.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/serverauth.py Thu Mar 6 11:34:36 2003
@@ -50,6 +50,7 @@
from constants import *
import sasl
import pwcheck
+import config
#
# Globals
@@ -87,7 +88,7 @@
need_auth = 1
while need_auth:
try:
- if need_auth > defaults['maxauthtries']:
+ if need_auth > config.defaults['maxauthtries']:
raise SessionTimeout, 'max tries exceeded'
self.timeout ()
cmd, args = self.getcmd ()
@@ -134,7 +135,7 @@
os.setgid (auth.gid)
os.setuid (auth.uid)
os.chdir (auth.dir)
- os.execl (defaults['serverpath'], defaults['serverpath'], './Mail', self.inbox)
+ os.execl (config.defaults['serverpath'], config.defaults['serverpath'], './Mail', self.inbox)
raise TemporaryCommandError, 'execl failed'
#######################################
diff -urN --exclude=bikini.html --exclude=bikini.txt --exclude=CHANGELOG bikini-20030306-0908/bikini/utilities.py bikini-20030306-1134/bikini/utilities.py
--- bikini-20030306-0908/bikini/utilities.py Thu Mar 6 09:08:42 2003
+++ bikini-20030306-1134/bikini/utilities.py Thu Mar 6 11:34:36 2003
@@ -10,6 +10,7 @@
from errors import *
from constants import *
+import config
# For trace output
newline = 1
@@ -35,59 +36,6 @@
and os.path.isdir (os.path.join (path, 'new')))
#######################################
-def deliver_message (path, envelope):
- '''Ask the local MTA to deliver the message.
- '''
- log (TRACE, 'path %s envelope %s\n' % (path, envelope))
- mail_command = '/var/qmail/bin/qmail-queue'
- READ, WRITE = 0, 1
- try:
- messagepipe = os.pipe ()
- envelopepipe = os.pipe ()
- child_pid = os.fork ()
- if child_pid == 0:
- # child
- os.close (messagepipe[WRITE])
- os.close (envelopepipe[WRITE])
- os.close (0)
- os.close (1)
- os.close (2)
- os.dup2 (messagepipe[READ], 0)
- os.dup2 (envelopepipe[READ], 1)
- os.execl (mail_command, mail_command)
- raise TemporaryCommandError, 'exec failed'
- # Parent
- log (DEBUG, 'forked pid %i\n' % child_pid)
- os.close (messagepipe[READ])
- os.close (envelopepipe[READ])
- # Write message
- os.write (messagepipe[WRITE], open (path, 'rb').read ())
- os.close (messagepipe[WRITE])
- # Write envelope
- parts = envelope.split ('\0')
- os.write (envelopepipe[WRITE], 'F%s\0' % parts[0])
- for recip in parts[1:-1]:
- os.write (envelopepipe[WRITE], 'T%s\0' % recip)
- os.write (envelopepipe[WRITE], '\0')
- os.close (envelopepipe[WRITE])
- tries = 0
- while tries < 10:
- pid, rc = os.waitpid (child_pid, os.WNOHANG)
- log (TRACE, 'os.waitpid returned %i, %s\n' % (pid, rc))
- if pid == child_pid and os.WIFEXITED (rc):
- if os.WEXITSTATUS (rc) == 0:
- log (TRACE, 'message queued\n')
- return 'this is a receipt, should be a queue id or similar' # ???
- log (TRACE, 'message not queued (exited %i)\n' % os.WEXITSTATUS (rc))
- raise TemporaryCommandError, '%s exited %i' % (mail_command, os.WEXITSTATUS (rc))
- time.sleep (1)
- log (ERROR, 'child never exited?\n')
- raise TemporaryCommandError, '%s never exited' % mail_command
-
- except UnhandledException, txt:
- raise TemporaryCommandError, 'failure queuing message: %s' % txt
-
-#######################################
def utcdate (timestamp):
'''
'''
@@ -205,7 +153,7 @@
msg = arg
elif type (arg) == IntType:
level = arg
- if level < defaults['loglevel']:
+ if level < config.defaults['loglevel']:
return
if level == TRACE:
if not newline: