summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mailman/Defaults.py.in8
-rw-r--r--Mailman/Digester.py22
-rw-r--r--Mailman/mm_cfg.py.dist.in15
-rw-r--r--Mailman/smtplib.py104
-rw-r--r--modules/mm_cfg.py.in15
-rw-r--r--modules/mm_defaults.py8
-rw-r--r--modules/mm_defaults.py.in8
-rw-r--r--modules/mm_digest.py22
-rw-r--r--modules/smtplib.py104
9 files changed, 277 insertions, 29 deletions
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index 31f470f7e..f5c82d242 100644
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -9,7 +9,7 @@ this file, to override the distributed defaults with site-specific ones.
import os
VERSION = '1.0b1.2'
-__version__ = "$Revision: 423 $"
+__version__ = "$Revision: 445 $"
# Many site-specific settings #
@@ -21,8 +21,10 @@ DEFAULT_URL = 'http://www.OVERRIDE.WITH.YOUR.HOST/mailman/'
PUBLIC_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PUBLIC.ARCHIVE.URL/'
PRIVATE_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PRIVATE.ARCHIVE.URL/'
# Once we know our home directory we can figure out the rest.
-HOME_DIR = '/home/mailman' # Override if you change
-MAILMAN_DIR = '/home/mailman/mailman' # Override if you change
+# BUT, if you override these in mm_cfg.py, you have to override the dependants
+# as well.
+HOME_DIR = '/home/mailman'
+MAILMAN_DIR = '/home/mailman/mailman'
LIST_DATA_DIR = os.path.join(MAILMAN_DIR, 'lists')
HTML_DIR = os.path.join(HOME_DIR, 'public_html')
CGI_DIR = os.path.join(HOME_DIR, 'cgi-bin')
diff --git a/Mailman/Digester.py b/Mailman/Digester.py
index 5ff7fe4b8..8413ae2a3 100644
--- a/Mailman/Digester.py
+++ b/Mailman/Digester.py
@@ -1,6 +1,6 @@
"""Mixin class with list-digest handling methods and settings."""
-__version__ = "$Revision: 396 $"
+__version__ = "$Revision: 445 $"
import mm_utils, mm_err, mm_message, mm_cfg
import time, os, string
@@ -185,10 +185,26 @@ From: %s
Subject: Contents of %s digest, Volume %d #%d
Date: %s
+When replying, please edit your Subject line so it is more specific than
+"Re: Contents of %s digest..."
+
+Send %s maillist submissions to
+ %s
+To subscribe or unsubscribe via the web, visit
+ %s
+or send email to %s
+
Topics for this digest:
%s
-''' % (self._mime_separator, msg.GetSender(), self.real_name, self.volume,
- self.next_digest_number, time.ctime(time.time()), topics_text)
+''' % (self._mime_separator,
+ msg.GetSender(),
+ self.real_name, self.volume, self.next_digest_number,
+ time.ctime(time.time()),
+ self.real_name, self.GetListEmail(),
+ self.real_name,
+ self.GetScriptURL('listinfo'),
+ self.GetRequestEmail(),
+ topics_text)
if self.digest_header:
digest_header = digest_header + (self.digest_header
diff --git a/Mailman/mm_cfg.py.dist.in b/Mailman/mm_cfg.py.dist.in
index 24847cd8c..99865588a 100644
--- a/Mailman/mm_cfg.py.dist.in
+++ b/Mailman/mm_cfg.py.dist.in
@@ -1,13 +1,14 @@
-"""This is the module which take your site-specific settings.
+"""This is the module which takes your site-specific settings.
-From a raw distribution it should be moved to be named mm_cfg.py. If you
-already have an mm_cfg.py, be careful to add in only the new settings you
-want. The complete set of distributed defaults are in ./mm_defaults. In
-mm_cfg, override only those you want to change, after the
+From a raw distribution it should be copied to mm_cfg.py. If you
+already have an mm_cfg.py, be careful to add in only the new settings
+you want. The complete set of distributed defaults, with annotation,
+are in ./mm_defaults. In mm_cfg, override only those you want to
+change, after the
from mm_defaults import *
-line, below.
+line (see below).
Note that these are just default settings - many can be overridden via the
admin and user interfaces on a per-list or per-user basis.
@@ -17,7 +18,7 @@ setting by using the value as a format string against the
list-instance-object's dictionary - see the distributed value of
DEFAULT_MSG_FOOTER for an example."""
-__version__ = "$Revision: 428 $"
+__version__ = "$Revision: 445 $"
#######################################################
# Here's where we get the distributed defaults. #
diff --git a/Mailman/smtplib.py b/Mailman/smtplib.py
new file mode 100644
index 000000000..db6e3e254
--- /dev/null
+++ b/Mailman/smtplib.py
@@ -0,0 +1,104 @@
+# A quick hack. Talk to the SMTP port.
+# Right now this isn't very functional.
+# A lot of functionality was borrowed directly from ftplib...
+# John Viega (viega@list.org)
+
+# >>> from smtplib import *
+# >>> s = SmtpConnection('list.org')
+# >>> s.helo('adder.cs.virginia.edu')
+# >>> s.send(to='viega@list.org', frm='jtv2j@cs.virginia.edu', text='hello, world!')
+# >>> s.quit()
+
+from socket import *
+import string
+
+SMTP_PORT = 25
+
+CRLF = '\r\n'
+
+# Exception raised when an error or invalid response is received
+error_reply = 'smtplib.error_reply' # unexpected [123]xx reply
+error_temp = 'smtplib.error_temp' # 4xx errors
+error_perm = 'smtplib.error_perm' # 5xx errors
+error_proto = 'smtplib.error_proto' # response does not begin with [1-5]
+
+class SmtpConnection:
+ def __init__(self, host=''):
+ self.host = host
+ self._file = None
+ self.connect()
+
+ def connect(self):
+ self._sock = socket(AF_INET, SOCK_STREAM)
+ self._sock.connect(self.host, SMTP_PORT)
+ self._file = self._sock.makefile('r')
+ self.getresp()
+
+ def helo(self, host):
+ self._sock.send('HELO %s\r\n' % host)
+ self.getresp()
+
+ def quit(self):
+ self._sock.send('QUIT\r\n')
+ self.getresp()
+
+ # text should be \n at eol, we'll add the \r.
+ def send(self, to, frm, text, headers=None):
+ if headers:
+ hlines = string.split(headers, '\n')
+ lines = string.split(text, '\n')
+ self._sock.send('MAIL FROM: %s\r\n' % frm)
+ self.getresp()
+ self._sock.send('RCPT TO: %s\r\n' % to)
+ self.getresp()
+ self._sock.send('DATA\r\n')
+ self.getresp()
+ if headers:
+ for line in hlines:
+ self._sock.send(line + '\r\n')
+ self._sock.send('\r\n')
+ for line in lines:
+ if line == '.': line = '..'
+ self._sock.send(line + '\r\n')
+ self._sock.send('.\r\n')
+ self.getresp()
+
+# Private crap from here down.
+ def getline(self):
+ line = self._file.readline()
+ if not line: raise EOFError
+ if line[-2:] == CRLF: line = line[:-2]
+ elif line[-1:] in CRLF: line = line[:-1]
+ return line
+
+ # Internal: get a response from the server, which may possibly
+ # consist of multiple lines. Return a single string with no
+ # trailing CRLF. If the response consists of multiple lines,
+ # these are separated by '\n' characters in the string
+ def getmultiline(self):
+ line = self.getline()
+ if line[3:4] == '-':
+ code = line[:3]
+ while 1:
+ nextline = self.getline()
+ line = line + ('\n' + nextline)
+ if nextline[:3] == code and \
+ nextline[3:4] <> '-':
+ break
+ return line
+
+ def getresp(self):
+ resp = self.getmultiline()
+ self.lastresp = resp[:3]
+ c = resp[:1]
+ if c == '4':
+ raise error_temp, resp
+ if c == '5':
+ raise error_perm, resp
+ if c not in '123':
+ raise error_proto, resp
+ return resp
+
+
+
+
diff --git a/modules/mm_cfg.py.in b/modules/mm_cfg.py.in
index 24847cd8c..99865588a 100644
--- a/modules/mm_cfg.py.in
+++ b/modules/mm_cfg.py.in
@@ -1,13 +1,14 @@
-"""This is the module which take your site-specific settings.
+"""This is the module which takes your site-specific settings.
-From a raw distribution it should be moved to be named mm_cfg.py. If you
-already have an mm_cfg.py, be careful to add in only the new settings you
-want. The complete set of distributed defaults are in ./mm_defaults. In
-mm_cfg, override only those you want to change, after the
+From a raw distribution it should be copied to mm_cfg.py. If you
+already have an mm_cfg.py, be careful to add in only the new settings
+you want. The complete set of distributed defaults, with annotation,
+are in ./mm_defaults. In mm_cfg, override only those you want to
+change, after the
from mm_defaults import *
-line, below.
+line (see below).
Note that these are just default settings - many can be overridden via the
admin and user interfaces on a per-list or per-user basis.
@@ -17,7 +18,7 @@ setting by using the value as a format string against the
list-instance-object's dictionary - see the distributed value of
DEFAULT_MSG_FOOTER for an example."""
-__version__ = "$Revision: 428 $"
+__version__ = "$Revision: 445 $"
#######################################################
# Here's where we get the distributed defaults. #
diff --git a/modules/mm_defaults.py b/modules/mm_defaults.py
index 31f470f7e..f5c82d242 100644
--- a/modules/mm_defaults.py
+++ b/modules/mm_defaults.py
@@ -9,7 +9,7 @@ this file, to override the distributed defaults with site-specific ones.
import os
VERSION = '1.0b1.2'
-__version__ = "$Revision: 423 $"
+__version__ = "$Revision: 445 $"
# Many site-specific settings #
@@ -21,8 +21,10 @@ DEFAULT_URL = 'http://www.OVERRIDE.WITH.YOUR.HOST/mailman/'
PUBLIC_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PUBLIC.ARCHIVE.URL/'
PRIVATE_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PRIVATE.ARCHIVE.URL/'
# Once we know our home directory we can figure out the rest.
-HOME_DIR = '/home/mailman' # Override if you change
-MAILMAN_DIR = '/home/mailman/mailman' # Override if you change
+# BUT, if you override these in mm_cfg.py, you have to override the dependants
+# as well.
+HOME_DIR = '/home/mailman'
+MAILMAN_DIR = '/home/mailman/mailman'
LIST_DATA_DIR = os.path.join(MAILMAN_DIR, 'lists')
HTML_DIR = os.path.join(HOME_DIR, 'public_html')
CGI_DIR = os.path.join(HOME_DIR, 'cgi-bin')
diff --git a/modules/mm_defaults.py.in b/modules/mm_defaults.py.in
index 31f470f7e..f5c82d242 100644
--- a/modules/mm_defaults.py.in
+++ b/modules/mm_defaults.py.in
@@ -9,7 +9,7 @@ this file, to override the distributed defaults with site-specific ones.
import os
VERSION = '1.0b1.2'
-__version__ = "$Revision: 423 $"
+__version__ = "$Revision: 445 $"
# Many site-specific settings #
@@ -21,8 +21,10 @@ DEFAULT_URL = 'http://www.OVERRIDE.WITH.YOUR.HOST/mailman/'
PUBLIC_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PUBLIC.ARCHIVE.URL/'
PRIVATE_ARCHIVE_URL = 'http://www.OVERRIDE.WITH.YOUR.PRIVATE.ARCHIVE.URL/'
# Once we know our home directory we can figure out the rest.
-HOME_DIR = '/home/mailman' # Override if you change
-MAILMAN_DIR = '/home/mailman/mailman' # Override if you change
+# BUT, if you override these in mm_cfg.py, you have to override the dependants
+# as well.
+HOME_DIR = '/home/mailman'
+MAILMAN_DIR = '/home/mailman/mailman'
LIST_DATA_DIR = os.path.join(MAILMAN_DIR, 'lists')
HTML_DIR = os.path.join(HOME_DIR, 'public_html')
CGI_DIR = os.path.join(HOME_DIR, 'cgi-bin')
diff --git a/modules/mm_digest.py b/modules/mm_digest.py
index 5ff7fe4b8..8413ae2a3 100644
--- a/modules/mm_digest.py
+++ b/modules/mm_digest.py
@@ -1,6 +1,6 @@
"""Mixin class with list-digest handling methods and settings."""
-__version__ = "$Revision: 396 $"
+__version__ = "$Revision: 445 $"
import mm_utils, mm_err, mm_message, mm_cfg
import time, os, string
@@ -185,10 +185,26 @@ From: %s
Subject: Contents of %s digest, Volume %d #%d
Date: %s
+When replying, please edit your Subject line so it is more specific than
+"Re: Contents of %s digest..."
+
+Send %s maillist submissions to
+ %s
+To subscribe or unsubscribe via the web, visit
+ %s
+or send email to %s
+
Topics for this digest:
%s
-''' % (self._mime_separator, msg.GetSender(), self.real_name, self.volume,
- self.next_digest_number, time.ctime(time.time()), topics_text)
+''' % (self._mime_separator,
+ msg.GetSender(),
+ self.real_name, self.volume, self.next_digest_number,
+ time.ctime(time.time()),
+ self.real_name, self.GetListEmail(),
+ self.real_name,
+ self.GetScriptURL('listinfo'),
+ self.GetRequestEmail(),
+ topics_text)
if self.digest_header:
digest_header = digest_header + (self.digest_header
diff --git a/modules/smtplib.py b/modules/smtplib.py
new file mode 100644
index 000000000..db6e3e254
--- /dev/null
+++ b/modules/smtplib.py
@@ -0,0 +1,104 @@
+# A quick hack. Talk to the SMTP port.
+# Right now this isn't very functional.
+# A lot of functionality was borrowed directly from ftplib...
+# John Viega (viega@list.org)
+
+# >>> from smtplib import *
+# >>> s = SmtpConnection('list.org')
+# >>> s.helo('adder.cs.virginia.edu')
+# >>> s.send(to='viega@list.org', frm='jtv2j@cs.virginia.edu', text='hello, world!')
+# >>> s.quit()
+
+from socket import *
+import string
+
+SMTP_PORT = 25
+
+CRLF = '\r\n'
+
+# Exception raised when an error or invalid response is received
+error_reply = 'smtplib.error_reply' # unexpected [123]xx reply
+error_temp = 'smtplib.error_temp' # 4xx errors
+error_perm = 'smtplib.error_perm' # 5xx errors
+error_proto = 'smtplib.error_proto' # response does not begin with [1-5]
+
+class SmtpConnection:
+ def __init__(self, host=''):
+ self.host = host
+ self._file = None
+ self.connect()
+
+ def connect(self):
+ self._sock = socket(AF_INET, SOCK_STREAM)
+ self._sock.connect(self.host, SMTP_PORT)
+ self._file = self._sock.makefile('r')
+ self.getresp()
+
+ def helo(self, host):
+ self._sock.send('HELO %s\r\n' % host)
+ self.getresp()
+
+ def quit(self):
+ self._sock.send('QUIT\r\n')
+ self.getresp()
+
+ # text should be \n at eol, we'll add the \r.
+ def send(self, to, frm, text, headers=None):
+ if headers:
+ hlines = string.split(headers, '\n')
+ lines = string.split(text, '\n')
+ self._sock.send('MAIL FROM: %s\r\n' % frm)
+ self.getresp()
+ self._sock.send('RCPT TO: %s\r\n' % to)
+ self.getresp()
+ self._sock.send('DATA\r\n')
+ self.getresp()
+ if headers:
+ for line in hlines:
+ self._sock.send(line + '\r\n')
+ self._sock.send('\r\n')
+ for line in lines:
+ if line == '.': line = '..'
+ self._sock.send(line + '\r\n')
+ self._sock.send('.\r\n')
+ self.getresp()
+
+# Private crap from here down.
+ def getline(self):
+ line = self._file.readline()
+ if not line: raise EOFError
+ if line[-2:] == CRLF: line = line[:-2]
+ elif line[-1:] in CRLF: line = line[:-1]
+ return line
+
+ # Internal: get a response from the server, which may possibly
+ # consist of multiple lines. Return a single string with no
+ # trailing CRLF. If the response consists of multiple lines,
+ # these are separated by '\n' characters in the string
+ def getmultiline(self):
+ line = self.getline()
+ if line[3:4] == '-':
+ code = line[:3]
+ while 1:
+ nextline = self.getline()
+ line = line + ('\n' + nextline)
+ if nextline[:3] == code and \
+ nextline[3:4] <> '-':
+ break
+ return line
+
+ def getresp(self):
+ resp = self.getmultiline()
+ self.lastresp = resp[:3]
+ c = resp[:1]
+ if c == '4':
+ raise error_temp, resp
+ if c == '5':
+ raise error_perm, resp
+ if c not in '123':
+ raise error_proto, resp
+ return resp
+
+
+
+