#! /usr/bin/python import sre as RX import os as OS import time as T import socket as S from getopt import getopt, GetoptError from sys import stdin, stdout, stderr, argv, exit from cStringIO import StringIO env = OS.environ prog = argv[0] def bad(msg): print >>stderr, '%s (fatal): %s' % (prog, msg) exit(100) def die(msg): print >>stderr, '%s: %s' % (prog, msg) exit(111) def usage(): print >>stderr, \ ('Usage: %s [-d DIST] [-h HOST] [-r REMOTE] [-p PATH] GROUP $') class NNTP (object): def __init__(me, addr): me.sk = S.socket(S.AF_INET, S.SOCK_STREAM) me.sk.connect(remote) me.f = me.sk.makefile() rc, msg = me.reply() if rc != '200': die('unable to contact server: %s %s' % (rc, msg)) def write(me, stuff): me.f.write(stuff) def flush(me): me.f.flush() def cmd(me, stuff): me.f.write(stuff + '\r\n') me.f.flush() def reply(me): rc, msg = (lambda rc, msg = '.': (rc, msg.strip())) \ (*me.f.readline().split(None, 1)) if rc.startswith('5'): die('server hated me: %s %s' % (rc, msg)) return rc, msg.strip() def send(): hdr = StringIO() body = StringIO() hdr.write('Path: newsgate\r\n' 'Distribution: mail\r\n' 'Newsgroups: %s\r\n' % group) if approved: hdr.write('Approved: %s\r\n' % approved) if sender: hdr.write('Return-Path: <%s>\r\n' % sender) if recip: hdr.write('Delivered-To: %s\r\n' % recip) xify = {} for h in ''' lines xref newsgroups path distribution approved received '''.split(): xify[h] = 1 seen = {} for h in headers(stdin): n, c = hdrsplit(h) if n in xify: h = 'X-Newsgate-' + h elif h.startswith('.'): h = '.' + h seen[n] = c if h.endswith('\r\n'): pass elif h.endswith('\n'): h = h[:-1] + '\r\n' else: h += '\r\n' hdr.write(h) if 'message-id' not in seen: seen['message-id'] = ('' % (OS.popen('gorp 128').read().strip(), host)) hdr.write('Message-ID: %s\r\n' % seen['message-id']) if 'date' not in seen: hdr.write('Date: %s\r\n' % (T.strftime('%a, %d %b %Y %H:%M:%S %Z'))) if 'subject' not in seen: hdr.write('Subject: (no subject)\r\n') msgid = seen['message-id'] if not rx_msgid.match(msgid): bad('invalid message-id %s' % msgid) nntp = NNTP(remote) nntp.cmd('IHAVE %s' % msgid) rc, msg = nntp.reply() if rc == '335': n = 0 for i in stdin: if i.startswith('.'): i = '.' + i if i.endswith('\r\n'): pass elif i.endswith('\n'): i = i[:-1] + '\r\n' else: i = i + '\r\n' body.write(i) n += 1 hdr.write('Lines: %d\r\n' % n) hdr.write('\r\n') nntp.write(hdr.getvalue()) nntp.write(body.getvalue()) nntp.write('.\r\n') nntp.flush() rc, msg = nntp.reply() if rc == '435': ## doesn't want my article; pretend all is fine: I don't care pass elif rc == '436': die('failed to send article: %s %s' % (rc, msg)) elif rc == '437': bad('server rejected article: %s %s' % (rc, msg)) elif not rc.startswith('2'): die('unexpected response from server: %s %s' % (rc, msg)) nntp.cmd('QUIT') nntp.reply() def main(): try: opts() send() except SystemExit: raise # except Exception, exc: # die('unhandled exception: %s, %s' % (exc.__class__.__name__, # exc.args)) main()