aboutsummaryrefslogtreecommitdiffstats
path: root/news2mail.py
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2002-06-04 17:02:00 +0200
committerMatěj Cepl <mcepl@cepl.eu>2015-01-03 10:31:58 +0100
commit59eda1d0150e4b517a071c1e04ded96ff8f0f314 (patch)
tree47db347f3ff74e3a7fb23cef1cba2ed4a452aeaa /news2mail.py
parenta9d49c6a0fd9dbad859659d7f49901bc9101d790 (diff)
downloadpygn-59eda1d0150e4b517a071c1e04ded96ff8f0f314.tar.gz
pyg 0.9.6 from archive.debian.org0.9.6
Diffstat (limited to 'news2mail.py')
-rw-r--r--news2mail.py412
1 files changed, 271 insertions, 141 deletions
diff --git a/news2mail.py b/news2mail.py
index 78d0ae4..73808b3 100644
--- a/news2mail.py
+++ b/news2mail.py
@@ -3,12 +3,13 @@
Author: Cosimo Alfarano
Date: June 11 2000
-news2mail.py - (C) 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
+news2mail.py - Copyright 2000 by Cosimo Alfarano <Alfarano@Students.CS.UniBo.It>
You can use this software under the terms of the GPL. If we meet some day,
and you think this stuff is worth it, you can buy me a beer in return.
Thanks to md for this useful formula. Beer is beer.
+
Gets news article and sends it via SMTP.
class news2mail is hopefully conform to rfc822.
@@ -19,151 +20,280 @@ normal (what pygs does) operations flow is:
3) merges NNTP and SMTP heads into a unique heads
4) adds, renames and removes some heads
5) sorts remaining headers starting at top with Received: From: To: Subject:
- Date:, normal headers ending with X-* and Resent-* headers.
+ Date:, normal headers ending with X-* and Resent-* headers.
"""
-from collections import OrderedDict
-import email
-from mail2news import VERSION, DESC
-import smtplib
-from socket import gethostbyaddr, gethostname
+
import sys
+import smtplib
+import string
+from re import compile
+#import getopt
import time
+#import rfc822
+from socket import gethostbyaddr, gethostname
+import tempfile
+import pyginfo
+
+class news2mail:
+ """news to mail gateway class"""
+
+ TMPFILE = tempfile.mktemp()
+ wlfile = None
+ logfile = None
+
+ sender = ''
+ rcpt = ''
+ envelope = ''
+
+ smtpserver = 'localhost'
+
+ hostname = gethostbyaddr(gethostname())[0]
+
+ heads_dict, smtpheads, nntpheads = {}, {}, {}
+ article, headers, body = [], [], []
+
+ debug = 1
+
+ def readfile(self):
+
+ for line in sys.stdin.readlines():
+ self.article.append(line)
+
+ if (len(self.article) == 1 and self.article[0][0] == '/'):
+ file = self.article[0][:-1]
+ del self.article[0]
+ for line in open(file,'r').readlines():
+ self.article.append(line)
+
+
+ def parsearticle(self):
+ """get news article from file or stdin and separate heads from body
+
+ REMEBER: headers value has '\n' as last char.
+ Use string[:-1] to ignore newline.
+ """
+
+ try:
+ body = 0 # are we in body or in headers?
+
+# voidline = compile('^$') # I need '\n', ^$ matches anything
+# spaceending = compile('\s*\n$')
+
+ for line in self.article:
+ if not body and len(line) == 1:
+ body = 1 # starts article body section
+
+ if not body:
+ try:
+ head, value = string.split(line, ' ', 1)
+ self.nntpheads[head] = value
+ except (string.index_error), message:
+ print 'string error: %s' % message
+ print '(probably missing couple "Header: value" in %s)' % line
+ sys.exit(1)
+
+ elif len(line) > 0 and body:
+ self.body.append(line)
+
+ return self.nntpheads, self.body
+
+# except (re.error, string.index_error), message:
+ except (string.index_error), message:
+ print message
+ sys.exit(1)
+
+
+ def puthead(self, dict, list, key):
+ """private, x-form dict entries in list entries"""
+
+ if dict.has_key(key):
+ list.append(key + ' ' + dict.get(key))
+ else:
+ return 0
+ return 1
+
+ def sortheads(self):
+ """make list sorting heads, Received: From: To: Subject: first, others, X-*, Resent-* last"""
+
+ set = ('Received:','From:','To:','Subject:','Date:') # put at top
+
+ for k in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] != 'X-' and k[:7] != 'Resent-' and k not in set:
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:2] == 'X-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ for k in self.heads_dict.keys():
+ if k[:7] == 'Resent-':
+ self.puthead(self.heads_dict,self.headers,k)
+
+ return self.headers
+
+
+ def mergeheads(self):
+ """make a unique headers dictionary from NNTP and SMTP
+ single headers dictionaries."""
+
+ self.heads_dict = {}
+
+
+ try:
+ for header in self.nntpheads.keys(): # fill it w/ nntp old heads
+ self.heads_dict[header] = self.nntpheads[header]
+
+ for header in self.smtpheads.keys(): # and replace them w/ smtp new heads
+ self.heads_dict[header] = self.smtpheads[header]
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def addheads(self):
+ """add new header like X-Gateway: Received:
+ """
+
+ info = pyginfo.pygsinfo()
+
+ try:
+ self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \
+ info.__doc__ + '\n'
+
+ ##self.heads_dict['X-Gateway:'] = '%s %s\n' % (info.PROGNAME, info.__doc__)
+
+ # to make Received: header
+ t = time.ctime(time.time())
+
+ if time.daylight:
+ tzone = time.tzname[1]
+ else:
+ tzone = time.tzname[0]
+
+ # An exemple from debian-italian:
+ # Received: from murphy.debian.org (murphy.debian.org [216.234.231.6])
+ # by smv04.iname.net (8.9.3/8.9.1SMV2) with SMTP id JAA26407
+ # for <kame.primo@innocent.com> sent by
+ # <debian-italian-request@lists.debian.org
+
+ tmp = 'from GATEWAY by ' + self.hostname + \
+ ' with ' + info.PROGNAME + \
+ '\n\tfor <' + self.rcpt + '> ; ' + \
+ t + ' (' + tzone +')\n'
+
+ self.heads_dict['Received:'] = tmp
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def renameheads(self):
+ """rename headers such as Newsgroups: to X-Newsgroups:
+
+ headers renamed are useless or not rfc 822 copliant
+ """
+ try:
+ if self.heads_dict.has_key('Newsgroups:'):
+ self.heads_dict['X-Newsgroups:'] = self.heads_dict['Newsgroups:']
+ del self.heads_dict['Newsgroups:']
+
+ if self.heads_dict.has_key('NNTP-Posting-Host:'):
+ self.heads_dict['X-NNTP-Posting-Host:'] = self.heads_dict['NNTP-Posting-Host:']
+ del self.heads_dict['NNTP-Posting-Host:']
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+
+ def removeheads(self):
+ """remove headers like Xref: Path: Lines:
+ """
+
+ try:
+ # removing some others useless headers ....
+
+ if self.heads_dict.has_key('Approved:'):
+ del self.heads_dict['Approved:']
+
+ if self.heads_dict.has_key('From'): # neither 'From ' nor 'From:'
+ del self.heads_dict['From']
+
+ if self.heads_dict.has_key('Xref:'):
+ del self.heads_dict['Xref:']
+
+ if self.heads_dict.has_key('Path:'):
+ del self.heads_dict['Path:']
+
+ if self.heads_dict.has_key('Lines:'):
+ del self.heads_dict['Lines:']
+
+ # it is usually set by INN, if ng is moderated...
+ if self.heads_dict.has_key('Sender:'):
+ del self.heads_dict['Sender:']
+
+
+ if self.heads_dict.has_key('Message-id:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-id']
+ del(self.heads_dict['Message-id'])
+
+ if self.heads_dict.has_key('Message-ID:'):
+ self.heads_dict['Message-Id:'] = self.heads_dict['Message-ID']
+ del(self.heads_dict['Message-ID'])
+
+ # If message-id is not present, I generate it
+ if not self.heads_dict.has_key('Message-Id:'):
+ # It should put a real user@domain
+ msgid = 'pyg@puppapera.org'
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def sendarticle(self):
+ """Talk to SMTP server and try to send email."""
+ try:
+ msglist = []
+
+ s = smtplib.SMTP(self.smtpserver)
+
+ # put real locahost domain name.
+ s.helo(self.hostname)
+ if s.helo_resp is None and s.ehlo_resp is None:
+ print 'No helo resp'
+ sys.exit(1)
+
+ resp = s.mail(self.envelope)
+ if resp[0] != 250:
+ print 'SMTP error during MAIL cmd: %s %s' % (resp[0], resp[1])
+ print 'envelope %s gave problem?' % self.envelope
+ sys.exit(1)
+ resp = s.rcpt(self.rcpt)
+ if resp[0] != 250:
+ print 'SMTP error during MAIL cmd: %s %s' % (resp[0], resp[1])
+ sys.exit(1)
+
+
+ msglist.append(string.join(self.headers,''))
+
+ msglist.append(string.join(self.body,''))
+ msg = string.join(msglist,'')
+
+ s.data(msg)
+ s.quit()
+
+ return 1
+
+ except (smtplib.SMTPException), messaggio:
+ print messaggio
+ sys.exit(1)
-# logging.basicConfig(level=logging.DEBUG)
-class news2mail(object):
- """news to mail gateway class"""
-
- def __init__(self, verbose=False):
- self.wlfile = None
- self.logfile = None
- self.verbose = verbose
-
- self.sender = ''
- self.rcpt = ''
- self.envelope = ''
-
- self.smtpserver = 'localhost'
-
- self.hostname = gethostbyaddr(gethostname())[0]
- self.heads_dict = {}
- self.article, self.headers, self.body = [], [], []
- self.message = self.__addheads(email.message_from_file(sys.stdin))
- def __addheads(self, msg):
- """add new header like X-Gateway: Received:
- """
-
- msg['X-Gateway'] = 'pyg {0} {1}'.format(VERSION, DESC)
-
- # to make Received: header
- t = time.ctime(time.time())
-
- if time.daylight:
- tzone = time.tzname[1]
- else:
- tzone = time.tzname[0]
-
- # An example from debian-italian:
- # Received: from murphy.debian.org (murphy.debian.org [216.234.231.6])
- # by smv04.iname.net (8.9.3/8.9.1SMV2) with SMTP id JAA26407
- # for <kame.primo@innocent.com> sent by
- # <debian-italian-request@lists.debian.org
-
- tmp = 'from GATEWAY by ' + self.hostname + \
- ' with pyg' + \
- '\n\tfor <' + self.rcpt + '> ; ' + \
- t + ' (' + tzone + ')\n'
-
- msg['Received'] = tmp
-
- return msg
-
- def __renameheads(self):
- """remove headers like Xref: Path: Lines:
- rename headers such as Newsgroups: to X-Newsgroups:
-
- headers renamed are useless or not rfc 822 copliant
- """
- try:
- if 'Newsgroups' in self.message:
- self.message['X-Newsgroups'] = \
- self.message['Newsgroups']
- del self.message['Newsgroups']
-
- if 'NNTP-Posting-Host' in self.message:
- self.message['X-NNTP-Posting-Host'] = \
- self.message['NNTP-Posting-Host']
- del self.message['NNTP-Posting-Host']
- except KeyError as ex:
- print(ex)
-
- try:
- # removing some others useless headers ....
- # that includes BOTH 'From ' and 'From'
- # 'Sender is usually set by INN, if ng is moderated...
- for key in ('Approved', 'From', 'Xref', 'Path', 'Lines', 'Sender'):
- if key in self.message:
- del self.message[key]
-
- if 'Message-id' in self.message:
- msgid = self.message['Message-id']
- del self.message['Message-id']
- self.message['Message-Id'] = msgid
- else:
- # It should put a real user@domain
- self.heads_dict['Message-Id'] = 'pyg@puppapera.org'
-
- if 'References' in self.message and \
- 'In-Reply-To' not in self.message:
- refs = self.message['References'].split()
- self.message['In-Reply-To'] = refs[-1]
-
- except KeyError, message:
- print message
-
- def __sortheads(self):
- """make list sorting heads, Received: From: To: Subject: first,
- others, X-*, Resent-* last"""
-
- # put at top
- header_set = ('Received', 'From', 'To', 'Subject', 'Date')
-
- heads_dict = OrderedDict(self.message)
- for hdr in self.message.keys():
- del self.message[hdr]
-
- for k in header_set:
- if k in heads_dict:
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if not k.startswith('X-') and not k.startswith('Resent-') \
- and k not in header_set:
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if k.startswith('X-'):
- self.message[k] = heads_dict[k]
-
- for k in heads_dict:
- if k.startswith('Resent-'):
- self.message[k] = heads_dict[k]
-
- def process_message(self):
- """phase 3:
- format rfc 822 headers from input article
- """
- self.__renameheads() # remove other heads
- self.__sortheads()
-
- def sendarticle(self):
- """Talk to SMTP server and try to send email."""
- s = smtplib.SMTP(self.smtpserver)
- s.set_debuglevel(self.verbose)
-
- s.sendmail(self.envelope, self.rcpt, self.message.as_string())
-
- s.quit()