diff options
Diffstat (limited to 'mail2news.py')
-rw-r--r-- | mail2news.py | 177 |
1 files changed, 76 insertions, 101 deletions
diff --git a/mail2news.py b/mail2news.py index 0b97b92..f802277 100644 --- a/mail2news.py +++ b/mail2news.py @@ -14,12 +14,16 @@ Gets news email and sends it via SMTP. class mail2news is hopefully conform to rfc850. """ -import sys +import email +import logging +#logging.basicConfig(level=logging.DEBUG) +import nntplib from os import getpid -from socket import gethostbyaddr, gethostname from re import findall -from news2mail import news2mail -import nntplib +from collections import OrderedDict +from socket import gethostbyaddr, gethostname +import sys + import pyginfo @@ -38,106 +42,47 @@ class mail2news: heads_dict, smtpheads, nntpheads = {}, {}, {} email, headers, body = [], [], [] + message = None def readfile(self, opt): - for line in sys.stdin.readlines(): - self.email.append(line) + self.message = email.message_from_file(sys.stdin) - 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) + if (len(self.message) == 0) \ + and self.message.get_payload().startswith('/'): + msg_file_name = self.message.get_payload().strip() + del self.message + with open(msg_file_name, 'r') as msg_file: + self.message = email.message_from_file(msg_file) # introduce nntpheads if opt.newsgroup != '': # TODO put it directly to self.message when we have it - self.nntpheads['Newsgroups:'] = opt.newsgroup + '\n' + self.nntpheads['Newsgroups'] = opt.newsgroup if opt.approver != '': - self.nntpheads['Approved:'] = opt.approver + '\n' + self.nntpheads['Approved'] = opt.approver 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 line[0] not in [' ', '\t']: - try: - head, value = line.split(' ', 1) - except ValueError: - value = '' - self.smtpheads[head] = value - else: - self.smtpheads[head] = '%s%s' % \ - (self.smtpheads[head], line) - except (ValueError), 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 (ValueError), message: - print message - sys.exit(1) - - return self.smtpheads, self.body - @staticmethod - def puthead(*args, **kwargs): - news2mail.puthead(*args, **kwargs) - - def sortheads(self): - """make list sorted by heads: From: To: Subject: first, - others, X-*, X-Resent-* last""" - - # put at top - set = ('Newsgroups:', 'From:', 'To:', 'X-To:', 'Cc:', 'Subject:', - 'Date:', 'Approved:', 'References:', 'Message-Id:') - - 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 puthead(from_dict, out_list, key): + """private, x-form dict entries in out_list entries""" + if key in from_dict: + out_list.append(key + ': ' + from_dict.get(key)) + else: + return 0 + return 1 def mergeheads(self): """make a unique headers dictionary from NNTP and SMTP single headers dictionaries.""" - self.heads_dict = {} + self.heads_dict = OrderedDict() + logging.debug('self.message.keys() = %s', self.message.keys()) try: - for header in self.smtpheads.keys(): # fill it w/ smtp old heads - self.heads_dict[header] = self.smtpheads[header] + for header in self.message.keys(): # fill it w/ smtp old heads + self.heads_dict[header] = self.message[header] # and replace them w/ nntp new heads for header in self.nntpheads.keys(): @@ -155,8 +100,8 @@ class mail2news: info = pyginfo.pygsinfo() try: - self.heads_dict['X-Gateway:'] = info.PROGNAME + ' ' + \ - info.PROGDESC + ' - Mail to News\n' + self.heads_dict['X-Gateway'] = info.PROGNAME + ' ' + \ + info.PROGDESC + ' - Mail to News' except KeyError, message: print message @@ -180,19 +125,19 @@ class mail2news: del self.heads_dict[key] # In rfc822 References: is considered, but many MUA doen't put it. - if ('References:' not in self.heads_dict) and \ - ('In-Reply-To:' in self.heads_dict): - print self.heads_dict['In-Reply-To:'] + if ('References' not in self.heads_dict) and \ + ('In-Reply-To' in self.heads_dict): + 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:']) + 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] + self.heads_dict['References'] = '%s\n' % ref[0] except KeyError, message: print message @@ -206,8 +151,8 @@ class mail2news: try: # removing some others useless headers .... (From is not From:) - rmheads = ['Received:', 'From', 'NNTP-Posting-Host:', - 'X-Trace:', 'X-Compliants-To:', 'NNTP-Posting-Date:'] + rmheads = ['Received', 'From ', 'NNTP-Posting-Host', + 'X-Trace', 'X-Compliants-To', 'NNTP-Posting-Date'] if(heads): rmheads.append(heads) @@ -215,24 +160,54 @@ class mail2news: if head in self.heads_dict: del self.heads_dict[head] - if 'Message-id:' in self.heads_dict: - self.heads_dict['Message-Id:'] = self.heads_dict['Message-id:'] - del(self.heads_dict['Message-id:']) + if 'Message-id' in self.heads_dict: + self.heads_dict['Message-Id'] = self.heads_dict['Message-id'] + del(self.heads_dict['Message-id']) - if 'Message-ID:' in self.heads_dict: - self.heads_dict['Message-Id:'] = self.heads_dict['Message-ID:'] - del(self.heads_dict['Message-ID:']) + if 'Message-ID' in self.heads_dict: + 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 'Message-Id:' not in self.heads_dict: + if 'Message-Id' not in self.heads_dict: msgid = '<pyg.%d@tuchailepuppapera.org>\n' % (getpid()) - self.heads_dict['Message-Id:'] = msgid + self.heads_dict['Message-Id'] = msgid except KeyError, message: print message return self.heads_dict + def sortheads(self): + """make list sorted by heads: From: To: Subject: first, + others, X-*, X-Resent-* last""" + + # put at top + head_set = ('Newsgroups', 'From', 'To', 'X-To', 'Cc', 'Subject', + 'Date', 'Approved', 'References', 'Message-Id') + + logging.debug('self.heads_dict = %s', self.heads_dict) + + for k in head_set: + self.puthead(self.heads_dict, self.headers, k) + + for k in self.heads_dict.keys(): + if not k.startswith('X-') and not k.startswith('X-Resent-') \ + and k not in head_set: + self.puthead(self.heads_dict, self.headers, k) + + for k in self.heads_dict.keys(): + if k.startswith('X-'): + self.puthead(self.heads_dict, self.headers, k) + + for k in self.heads_dict.keys(): + if k.startswith('X-Resent-'): + self.puthead(self.heads_dict, self.headers, k) + + logging.debug('self.headers = %s', self.headers) + + return self.headers + def sendemail(self): """Talk to NNTP server and try to send email.""" try: |