aboutsummaryrefslogtreecommitdiffstats
path: root/mail2news.py.withtab
diff options
context:
space:
mode:
Diffstat (limited to 'mail2news.py.withtab')
-rw-r--r--mail2news.py.withtab319
1 files changed, 319 insertions, 0 deletions
diff --git a/mail2news.py.withtab b/mail2news.py.withtab
new file mode 100644
index 0000000..8b80e0c
--- /dev/null
+++ b/mail2news.py.withtab
@@ -0,0 +1,319 @@
+"""Mail to news gateway script. Copyright 2000 Cosimo Alfarano
+
+Author: Cosimo Alfarano
+Date: September 16 2000
+
+mail2news.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 email and sends it via SMTP.
+
+class mail2news is hopefully conform to rfc850.
+
+"""
+
+import sys
+from os import unlink, getpid
+from socket import gethostbyaddr, gethostname
+import string
+from re import findall
+import time
+import nntplib
+import pyginfo
+import tempfile
+
+class mail2news:
+ """news to mail gateway class"""
+
+
+ reader = None # mode reader
+# newsgroups = None # Newsgroups: local.test,local.moderated...
+# approved = None # Approved: kame@aragorn.lorien.org
+ newsserver = 'localhost' # no comment :)
+ port = 119
+ user = None
+ password = None
+
+ hostname = gethostbyaddr(gethostname())[0]
+
+ heads_dict, smtpheads, nntpheads = {}, {}, {}
+ email, headers, body = [], [], []
+
+
+ def readfile(self):
+
+ for line in sys.stdin.readlines():
+ self.email.append(line)
+
+ if(len(self.email) == 1 and self.email[0][0] == '/'):
+ file = self.email[0][:-1]
+ del self.email[0]
+ for line in open(file,'r').readlines():
+ self.email.append(line)
+
+ return 1
+
+
+ def parseemail(self):
+ """get news email 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?
+
+ for line in self.email:
+ if not body and len(line) == 1:
+ body = 1 # starts email body section
+
+ if not body:
+ try:
+ # if it is a multi-line header like Received:
+ if not line[0] in [' ','\t']:
+ try:
+ head, value = string.split(line, ' ', 1)
+ except string.index_error:
+ value = ''
+ self.smtpheads[head] = value
+ else:
+ self.smtpheads[head] = '%s%s' % \
+ (self.smtpheads[head], line)
+ except (string.index_error), message:
+ print 'line: %s' % line
+ print '(probably missing couple "Header: value" in %s)' % line
+ sys.exit(1)
+
+ elif len(line) > 0 and body:
+ self.body.append(line)
+
+ except (string.index_error), message:
+ print message
+ sys.exit(1)
+
+ return self.smtpheads, self.body
+
+ def puthead(self, dict, list, key):
+ """private, transform dict entries in list entries
+ Appends key of dict to list, deleting it from dict.
+ """
+
+ if dict.has_key(key):
+ list.append(key + ' ' + dict.get(key))
+ del dict[key]
+ else:
+ return 0
+ return 1
+
+ def sortheads(self):
+ """make list sorted by heads: From: To: Subject: first, others, X-*, X-Resent-* last"""
+
+ set = ('Newsgroups:','From:','To:','X-To:','Cc:','Subject:','Date:','Approved:','References:','Message-Id:') # 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[:9] != 'X-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[:9] == 'X-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.smtpheads.keys(): # fill it w/ smtp old heads
+ self.heads_dict[header] = self.smtpheads[header]
+
+ for header in self.nntpheads.keys(): # and replace them w/ nntp new heads
+ self.heads_dict[header] = self.nntpheads[header]
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def addheads(self):
+ """add new header like X-Gateway:
+ """
+
+ info = pyginfo.pygsinfo()
+
+ try:
+ self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \
+ info.PROGDESC + ' - Mail to News\n'
+
+# it is nntpheads stuff
+# if(self.newsgroups):
+# self.heads_dict['Newsgroups:'] = self.newsgroups
+
+# if(self.approved):
+# self.heads_dict['Approved:'] = self.approved
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def renameheads(self):
+ """rename headers such as Resent-*: to X-Resent-*:
+
+ headers renamed are useless or not rfc 977/850 copliant
+ handles References/In-Reply-To headers
+ """
+ try:
+
+### test
+# if(post):
+# if(self.heads_dict.has_key(post)):
+# self.heads_dict['X-Original-' + post] = self.heads_dict[post]
+#
+# self.heads_dict[post] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+#
+# else:
+# if(pre[0:2] == 'X-' and self.heads_dict.has_key(pre)):
+# self.heads_dict['X-Original-' + pre] = self.heads_dict[pre]
+# elif(not pre[0:2] == 'X-' and self.heads_dict.has_key('X-' + pre)):
+# self.heads_dict['X-' + pre] = self.heads_dict[pre]
+# del(self.heads_dict[pre])
+### end test
+
+ for key in self.heads_dict.keys():
+ if(key[:7] in ['Resent-']):
+ if(self.heads_dict.has_key('X-' + key)):
+ self.heads_dict[ 'X-Original-' + key ] = self.heads_dict['X-' + key]
+ self.heads_dict[ 'X-' + key ] = self.heads_dict[key]
+ del self.heads_dict[key]
+
+
+ # In rfc822 References: is considered, but many MUA doen't put it.
+ if(not self.heads_dict.has_key('References:') and self.heads_dict.has_key('In-Reply-To:')):
+ print self.heads_dict['In-Reply-To:']
+
+ # some MUA uses msgid without '<' '>'
+# ref = findall('([^\s<>\']+@[^\s<>;:\']+)', \
+ # but I prefer use RFC standards
+ ref = findall('(<[^<>]+@[^<>]+>)', \
+ self.heads_dict['In-Reply-To:'])
+
+ # if found, keep first element that seems a Msg-ID.
+ if(ref and len(ref)):
+ self.heads_dict['References:'] = '%s\n' % ref[0]
+
+# if(self.heads_dict.has_key('To:')):
+# self.heads_dict['X-To:'] = self.heads_dict['To:']
+# del self.heads_dict['To:']
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+
+ def removeheads(self, heads = None):
+ """remove headers like Xref: Path: Lines:
+ """
+
+ try:
+ # removing some others useless headers .... (From is not From:)
+
+ rmheads = ['Received:','From','NNTP-Posting-Host:','X-Trace']
+ if(heads):
+ rmheads.append(heads)
+
+ for head in rmheads:
+ if self.heads_dict.has_key(head):
+ del self.heads_dict[head]
+
+# if self.heads_dict.has_key('From'): # neither 'From ' nor 'From:'
+# del self.heads_dict['From']
+
+# if self.heads_dict.has_key('NNTP-Posting-Host:'): # neither 'From ' nor 'From:'
+# del self.heads_dict['']
+
+
+# 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:'):
+ msgid = '<pyg.%d@tuchailepuppapera.org>\n' % (getpid())
+ self.heads_dict['Message-Id:'] = msgid
+
+ except KeyError, message:
+ print message
+
+ return self.heads_dict
+
+ def sendemail(self):
+ """Talk to NNTP server and try to send email."""
+ try:
+ msglist = []
+
+ n = nntplib.NNTP(self.newsserver, self.port, self.user, self.password)
+
+ if(self.reader):
+ n.putline('mode reader')
+ resp = n.getline()
+ print resp
+
+ resp = n.shortcmd('POST')
+
+ # sett RFC977 2.4.2
+ if resp[0] <> '3':
+ raise n.error_reply, str(resp)
+
+ for line in self.headers:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ for line in self.body:
+ if not line:
+ break
+ if line[-1] == '\n':
+ line = line[:-1]
+ if line[:1] == '.':
+ line = '.' + line
+ n.putline(line)
+
+ n.putline('.')
+ n.quit()
+ return None
+ except (nntplib.error_reply, nntplib.error_temp, nntplib.error_perm, nntplib.error_proto, nntplib.error_data), message:
+ return 'NNTP: ' + str(message)