summaryrefslogtreecommitdiff
path: root/Mailman/GatewayManager.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/GatewayManager.py')
-rw-r--r--Mailman/GatewayManager.py267
1 files changed, 149 insertions, 118 deletions
diff --git a/Mailman/GatewayManager.py b/Mailman/GatewayManager.py
index 911b89df1..bdebc8f21 100644
--- a/Mailman/GatewayManager.py
+++ b/Mailman/GatewayManager.py
@@ -16,131 +16,162 @@
'''Mixin class for gatewaying mail to news, and news to mail.'''
+# All these things should already be imported, so might as well do them here
+# at the top level
+import os
+import string
+import time
+import mm_cfg
# XXX: This should be integrated with the Errors module
ImproperNNTPConfigError = "ImproperNNTPConfigError"
-
+# XXX: Bogus, but might as we do it `legally'
+QuickEscape = 'QuickEscape'
class GatewayManager:
- def InitVars(self):
- # Configurable
- self.nntp_host = ''
- self.linked_newsgroup = ''
- self.gateway_to_news = 0
- self.gateway_to_mail = 0
-
- def GetConfigInfo(self):
- import mm_cfg
- return [
- 'Mail to news and news to mail gateway services.',
- ('nntp_host', mm_cfg.String, 50, 0,
- 'The internet address of the machine your news server is running on.',
+ def InitVars(self):
+ # Configurable
+ self.nntp_host = ''
+ self.linked_newsgroup = ''
+ self.gateway_to_news = 0
+ self.gateway_to_mail = 0
- 'The news server is not part of Mailman proper. You have to already'
- ' have access to a nntp server, and that nntp server has to recognize'
- ' the machine this mailing list runs on as a machine capable of'
- ' reading and posting news.'),
- ('linked_newsgroup', mm_cfg.String, 50, 0,
- 'The name of the usenet group to gateway to and/or from.'),
- ('gateway_to_news', mm_cfg.Toggle, ('No', 'Yes'), 0,
- 'Should posts to the mailing list be resent to the newsgroup?'),
- ('gateway_to_mail', mm_cfg.Toggle, ('No', 'Yes'), 0,
- 'Should newsgroup posts not sent from the list be resent to the'
- ' list?')
- ]
+ def GetConfigInfo(self):
+ return [
+ 'Mail-to-News and News-to-Mail gateway services.',
+ ('nntp_host', mm_cfg.String, 50, 0,
+ 'The Internet address of the machine your News server '
+ 'is running on.',
+ 'The News server is not part of Mailman proper. You have to '
+ 'already have access to a NNTP server, and that NNTP server '
+ 'has to recognize the machine this mailing list runs on as '
+ 'a machine capable of reading and posting news.'),
+ ('linked_newsgroup', mm_cfg.String, 50, 0,
+ 'The name of the Usenet group to gateway to and/or from.'),
+ ('gateway_to_news', mm_cfg.Toggle, ('No', 'Yes'), 0,
+ 'Should posts to the mailing list be resent to the '
+ 'newsgroup?'),
+ ('gateway_to_mail', mm_cfg.Toggle, ('No', 'Yes'), 0,
+ 'Should newsgroup posts not sent from the list be resent '
+ 'to the list?')
+ ]
- # Watermarks are kept externally to avoid locking problems.
- def PollNewsGroup(self, watermark):
- if (not self.gateway_to_mail or not self.nntp_host or
- not self.linked_newsgroup):
- return 0
- import nntplib, os, string, mm_cfg
- con = nntplib.NNTP(self.nntp_host)
- r,c,f,l,n = con.group(self.linked_newsgroup)
- # NEWNEWS is not portable and has synchronization issues...
- # Use a watermark system instead.
- if watermark == 0:
- return eval(l)
- for num in range(max(watermark+1, eval(f)), eval(l)+1):
- try:
- headers = con.head(`num`)[3]
- found_to = 0
- for header in headers:
- i = string.find(header, ':')
- if i > 0 and string.lower(header[:i]) == 'to':
- found_to = 1
- if header[:i] <> 'X-BeenThere':
- continue
- if header[i:] == ': %s' % self.GetListEmail():
- raise "QuickEscape"
- body = con.body(`num`)[3]
- file = os.popen("%s %s nonews" %
- (os.path.join(mm_cfg.SCRIPTS_DIR,
- "post"), self._internal_name), "w")
- file.write(string.join(headers,'\n'))
- # If there wasn't already a TO: header, add one.
- if not found_to:
- file.write("\nTo: %s" % self.GetListEmail())
- file.write('\n\n')
- file.write(string.join(body,'\n'))
- file.write('\n')
- file.close()
- except nntplib.error_temp:
- pass # Probably canceled, etc...
- except "QuickEscape":
- pass # We gated this TO news, don't repost it!
- return eval(l)
-
- def SendMailToNewsGroup(self, mail_msg):
- import Message
- import os
- #if self.gateway_to_news == 0:
- # return
- if self.linked_newsgroup == '' or self.nntp_host == '':
- raise ImproperNNTPConfigError
- try:
- if self.tmp_prevent_gate:
- return
+ # Watermarks are kept externally to avoid locking problems.
+ def PollNewsGroup(self, watermark):
+ if (not self.gateway_to_mail or not self.nntp_host or
+ not self.linked_newsgroup):
+ return 0
+ import nntplib
+ con = nntplib.NNTP(self.nntp_host)
+ r,c,f,l,n = con.group(self.linked_newsgroup)
+ # the (estimated)count, first, and last are numbers returned as
+ # string. We use them as numbers throughout
+ c = int(c)
+ f = int(f)
+ l = int(l)
+ # NEWNEWS is not portable and has synchronization issues...
+ # Use a watermark system instead.
+ if watermark == 0:
+ return l
+ for num in range(max(watermark+1, f, l+1)):
+ try:
+ headers = con.head(`num`)[3]
+ found_to = 0
+ for header in headers:
+ i = string.find(header, ':')
+ if i > 0 and string.lower(header[:i]) == 'to':
+ found_to = 1
+ if header[:i] <> 'X-BeenThere':
+ continue
+ if header[i:] == ': %s' % self.GetListEmail():
+ raise QuickEscape
+ body = con.body(`num`)[3]
+ # Create the pipe to the Mail posting script. Note that it is
+ # not installed executable, so we'll tack on the path to
+ # Python we discovered when we configured Mailman
+ cmd = '%s %s %s nonews' % (
+ mm_cfg.PYTHON,
+ os.path.join(mm_cfg.SCRIPTS_DIR, 'post'),
+ self._internal_name)
+ file = os.popen(cmd, 'w')
+ file.write(string.join(headers,'\n'))
+ # If there wasn't already a TO: header, add one.
+ if not found_to:
+ file.write("\nTo: %s" % self.GetListEmail())
+ file.write('\n\n')
+ file.write(string.join(body,'\n'))
+ file.write('\n')
+ file.close()
+ except nntplib.error_temp:
+ pass # Probably canceled, etc...
+ except "QuickEscape":
+ pass # We gated this TO news, don't repost it!
+ return l
+
+ def SendMailToNewsGroup(self, mail_msg):
+ import Message
+ #if self.gateway_to_news == 0:
+ # return
+ if self.linked_newsgroup == '' or self.nntp_host == '':
+ raise ImproperNNTPConfigError
+ try:
+ if self.tmp_prevent_gate:
+ return
except AttributeError:
- pass # Wasn't remailed by the news gater then. Let it through.
- # Fork in case the nntp connection hangs.
- x = os.fork()
- if not x:
- # Now make the news message...
- msg = Message.NewsMessage(mail_msg)
-
- import nntplib,string
-
- # Ok, munge headers, etc.
- subj = msg.getheader('subject')
- if not subj:
- msg.SetHeader('Subject', '%s(no subject)' % prefix)
- if self.reply_goes_to_list:
- del msg['reply-to']
- msg.headers.append('Reply-To: %s\n' % self.GetListEmail())
- msg.headers.append('Sender: %s\n' % self.GetAdminEmail())
- msg.headers.append('Errors-To: %s\n' % self.GetAdminEmail())
- msg.headers.append('X-BeenThere: %s\n' % self.GetListEmail())
- msg.headers.append('Newsgroups: %s\n' % self.linked_newsgroup)
- # Note: Need to be sure 2 messages aren't ever sent to the same
- # list in the same process, since message ID's need to be unique.
- # could make the ID be mm.listname.postnum instead if that happens
- if msg.getheader('Message-ID') == None:
- import time
- msg.headers.append('Message-ID: <mm.%s.%s@%s>\n' %
- (time.time(), os.getpid(), self.host_name))
- if msg.getheader('Lines') == None:
- msg.headers.append('Lines: %s\n' %
+ pass # Wasn't remailed by the news gater then. Let it through.
+ # Fork in case the nntp connection hangs.
+ x = os.fork()
+ if not x:
+ import nntplib
+ # Now make the news message...
+ msg = Message.NewsMessage(mail_msg)
+ # Ok, munge headers, etc.
+ subj = msg.getheader('subject')
+ if not subj:
+ msg.SetHeader('Subject', '%s(no subject)' % prefix)
+ if self.reply_goes_to_list:
+ del msg['reply-to']
+ msg.headers.append('Reply-To: %s\n' % self.GetListEmail())
+ # if we already have a sender header, don't add another one; use
+ # the header that's already there.
+ if not msg.getheader('sender'):
+ msg.headers.append('Sender: %s\n' % self.GetAdminEmail())
+ msg.headers.append('Errors-To: %s\n' % self.GetAdminEmail())
+ msg.headers.append('X-BeenThere: %s\n' % self.GetListEmail())
+ ngheader = msg.getheader('newsgroups')
+ if ngheader is not None:
+ # see if the Newsgroups: header already contains our
+ # linked_newsgroup. If so, don't add it again. If not,
+ # append our linked_newsgroup to the end of the header list
+ ngroups = map(string.strip, string.split(ngheader, ','))
+ if self.linked_newsgroup not in ngroups:
+ ngroups.append(self.linked_newsgroup)
+ ngheader = string.join(ngroups, ',')
+ # subtitute our new header for the old one. XXX Message
+ # class should have a __setitem__()
+ del msg['newsgroups']
+ msg.headers.append('Newsgroups: %s\n' % ngroups)
+ else:
+ # Newsgroups: isn't in the message
+ msg.headers.append('Newsgroups: %s\n' % self.linked_newsgroup)
+ # Note: Need to be sure 2 messages aren't ever sent to the same
+ # list in the same process, since message ID's need to be unique.
+ # Could make the ID be mm.listname.postnum instead if that happens
+ if msg.getheader('Message-ID') is None:
+ msg.headers.append('Message-ID: <mm.%s.%s@%s>\n' %
+ (time.time(), os.getpid(), self.host_name))
+ if msg.getheader('Lines') is None:
+ msg.headers.append('Lines: %s\n' %
len(string.split(msg.body,"\n")))
- del msg['received']
+ del msg['received']
- # NNTP is strict about spaces after the colon in headers.
- for n in range(len(msg.headers)):
- line = msg.headers[n]
- i = string.find(line,":")
- if i <> -1 and line[i+1] <> ' ':
- msg.headers[n] = line[:i+1] + ' ' + line[i+1:]
- con = nntplib.NNTP(self.nntp_host)
- con.post(msg)
- con.quit()
- os._exit(0)
+ # NNTP is strict about spaces after the colon in headers.
+ for n in range(len(msg.headers)):
+ line = msg.headers[n]
+ i = string.find(line,":")
+ if i <> -1 and line[i+1] <> ' ':
+ msg.headers[n] = line[:i+1] + ' ' + line[i+1:]
+ con = nntplib.NNTP(self.nntp_host)
+ con.post(msg)
+ con.quit()
+ os._exit(0)