Changeset 15:8ae771653ffe in mailjam
- Timestamp:
- May 21, 2012, 7:22:27 PM (12 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 2 added
- 8 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
MANIFEST
r3 r15 2 2 README 3 3 setup.py 4 bin/postman-mta 5 bin/postman-server 6 conf/postman-mta.conf 7 conf/postman.conf 4 8 postman/__init__.py 5 9 postman/config.py 6 10 postman/daemon.py 7 postman/daemon_contrib.py8 11 postman/models.py 9 12 postman/mta.py -
conf/postman-mta.conf
r14 r15 1 1 # 2 # postman .conf - Postman MTA client configuration file2 # postman-mta.conf - Postman MTA client configuration file 3 3 # 4 4 5 [ postman_server]5 [server] 6 6 address = localhost 7 7 port = 9876 8 uri = http://%(address)s:%(port)s 8 9 ssl = false 9 10 11 [archive] 12 persistent = true 13 path = /usr/local/postman/archive-mta -
postman/config.py
r14 r15 86 86 class MTAClientConfig(DaemonConfig): 87 87 @property 88 def default_filename( ):88 def default_filename(self): 89 89 return 'postman-mta.conf' 90 90 91 91 @property 92 92 def sections(self): 93 return [' postman_server',]93 return ['server', 'archive'] 94 94 95 95 -
postman/daemon.py
r13 r15 189 189 'server.log')) 190 190 logging.basicConfig(filename=self.logfile, level=logging.DEBUG) 191 192 191 self.server = None 193 192 self.ready_to_serve = False -
postman/mta.py
r11 r15 11 11 """ 12 12 13 import sys, email, smtplib13 import os, sys, email, smtplib, xmlrpclib 14 14 from datetime import datetime 15 from models import MailingList 16 import config 15 from postman.models import MailingList 16 from postman.config import MTAClientConfig 17 from postman.tools import validate_email_address 17 18 18 class Sendmail():19 class MTAClient(): 19 20 20 def __init__(self, mailing_list=None, configfile=None): 21 if not isinstance(mailing_list, MailingList): 22 raise ValueError(mailing_list, ' is not a valid mailing list') 23 self.mailing_list = mailing_list 24 self.suscriptors = self.mailing_list.members_addresses 25 self.reply_to = self.mailing_list.address 21 def __init__(self, address=None, configfile=None): 22 if not validate_email_address(address): 23 raise ValueError(address, ' is not a valid email address') 24 25 mta_config = MTAClientConfig() 26 mta_config.load() 27 self.config = mta_config.config 28 self.rpc = xmlrpclib.ServerProxy(self.config['server']['uri']) 29 self.address = self._validate_address(address) 30 self.suscriptors = self.rpc.members.list(address) 31 self.reply_to = self.address 26 32 self.raw_email = None 27 33 self.queue = [] 28 self.archive_config = config.get_config_parameters('archive', 29 configfile) 34 35 def _validate_archive_path(self): 36 """ 37 Validate that the archive path exists. If not, try to create it 38 """ 39 if not os.path.exists(self.config['archive']['path']): 40 # FIXME: This will raise an IOError if the user has no 41 # privileges to create the directory, perhaps we should catch 42 # that and show an error instead 43 os.makedirs(self.config['archive']['path']) 44 return True 30 45 31 def get_raw_email(self): 32 try: 33 self.raw_email = sys.stdin.read() 34 except: 35 raise IOError('Can not get a valid email from stdin') 46 def _validate_address(self, address=None): 47 """ 48 The address provided by the user will be valid only if it is a 49 valid email address and if it is the email address of an already 50 existing mailing list 51 """ 52 if not validate_email_address(address): 53 raise ValueError(address, ' is not a valid email address') 54 if not address in self.rpc.lists.addresses(): 55 raise ValueError(address, 56 ' is not the address of any existing mailing list') 57 # If it is valid, return it 58 return address 59 60 def get_raw_email(self, raw_email=None): 61 """ 62 get the raw data containing email information. If raw_email is None, 63 try to get the data from stdin 64 """ 65 if not raw_email: 66 try: 67 self.raw_email = sys.stdin.read() 68 except: 69 raise IOError('Can not get a valid email from stdin') 70 else: 71 self.raw_email = raw_email 72 # FIXME: We should perform some checks on the raw data, ensuring 73 # it is a valid email text 36 74 return self.raw_email 37 75 … … 40 78 # FIXME: perhaps a while loop here, with some maximum recursion 41 79 # check, would be nice here 42 self.get_raw_email 43 filename = os.path.join(self.archive_config['path'], 80 self.get_raw_email() 81 # Check the path to the archive exists 82 self._validate_archive_path() 83 filename = os.path.join(self.config['archive']['path'], 44 84 datetime.today().strftime('%Y%d%m%H%M%S%f')) 45 85 tmpfile = file(filename, 'w') … … 49 89 50 90 def send_email(self): 91 """ 92 Send emails from the queue, if there is any 93 """ 51 94 if self.queue: 52 95 next_email = self.queue.pop() … … 54 97 email_data = email.message_from_file(email_file) 55 98 email_file.close() 56 57 99 email_data['Reply-to'] = self.reply_to 58 59 smtp_conn = smtplib.SMTP() 60 smtp_conn.connect() 61 smtp_conn.sendmail(email_data['From'], self.suscriptors, 62 email_data.as_string()) 63 smtp_conn.close() 100 print 'SENDING EMAIL:' 101 print email_data 102 #smtp_conn = smtplib.SMTP() 103 #smtp_conn.connect() 104 #smtp_conn.sendmail(email_data['From'], self.suscriptors, 105 # email_data.as_string()) 106 #smtp_conn.close() 107 # FIXME: enable tmp data removal here: 108 # if not self.config['archive']['persistent']: 109 # REMOVE THE FILE FROM DISK 64 110 65 111 def run(self): 66 self.get_raw_email()67 112 self.save_raw_email() 68 113 self.send_email() -
postman/tests/__init__.py
r11 r15 12 12 13 13 from models import * 14 from mta import *14 # from mta import * 15 15 from daemon import * -
postman/tests/mta.py
r10 r15 1 1 # -*- coding: utf-8 -*- 2 2 3 import os, sys 3 import os, sys, multiprocessing, time 4 4 from unittest import TestCase 5 from postman.mta import Sendmail 5 from postman.mta import MTAClient 6 from postman.daemon import PostmanDaemon 6 7 from postman.models import Member, MailingList 7 8 8 class TestSendmail(TestCase): 9 10 class TestMTAClient(TestCase): 11 """ 12 FIXME: These are dummy tests, they cover almost nothing from the 13 real postman mta client (yet) 14 """ 9 15 def setUp(self): 16 self.mta_configfile = os.path.join(os.path.dirname(__file__), 17 'postman-mta.conf') 10 18 self.configfile = os.path.join(os.path.dirname(__file__), 11 19 'postman.conf') … … 13 21 members={}, configfile=self.configfile) 14 22 self.member = Member('test@example.com') 15 self.mta = Sendmail(self.mailing_list)16 23 self.raw_email_file = os.path.join(os.path.dirname(__file__), 17 24 'sample_raw_email.txt') … … 19 26 self.raw_email = tmp_to_read.read() 20 27 tmp_to_read.close() 21 28 22 29 def test___init__(self): 30 # in order to start mta client instances, we need to have a postman 31 # daemon running on the background 32 # This should be added to the setUp() method, but then it would be 33 # more difficult to terminate the process after all the methods 34 # were called 35 daemon = PostmanDaemon(self.configfile) 36 daemon.port = 9100 37 p = multiprocessing.Process(target=daemon.run) 38 p.start() 39 # Add a delay here to allow the server to be fully started before 40 # starting to send requests from the client 41 time.sleep(1) 42 23 43 with self.assertRaises(ValueError): 24 mta = Sendmail('test_list@example.com')25 mta = Sendmail(self.member)26 mta = Sendmail(None)27 mta = Sendmail(self.mailing_list)28 self.assertTrue(isinstance(mta, Sendmail))29 self.assertEqual(mta. mailing_list, self.mailing_list)44 mta = MTAClient(self.mailing_list, self.mta_configfile) 45 mta = MTAClient(self.member, self.mta_configfile) 46 mta = MTAClient(None, self.mta_configfile) 47 mta = MTAClient(self.mailing_list.address, self.mta_configfile) 48 self.assertTrue(isinstance(mta, MTAClient)) 49 self.assertEqual(mta.address, self.mailing_list.address) 30 50 self.assertEqual(mta.suscriptors, self.mailing_list.members_addresses) 31 51 self.assertEqual(mta.reply_to, self.mailing_list.address) 32 52 53 p.terminate() 54 33 55 def test_get_raw_email(self): 56 # in order to start mta client instances, we need to have a postman 57 # daemon running on the background 58 # This should be added to the setUp() method, but then it would be 59 # more difficult to terminate the process after all the methods 60 # were called 61 daemon = PostmanDaemon(self.configfile) 62 daemon.port = 9100 63 p = multiprocessing.Process(target=daemon.run) 64 p.start() 65 # Add a delay here to allow the server to be fully started before 66 # starting to send requests from the client 67 time.sleep(1) 68 69 mta = MTAClient(self.mailing_list.address, self.mta_configfile) 70 34 71 sys_stdin = sys.stdin 35 72 sys.stdin = open(self.raw_email_file, 'r') 36 self.assertEqual( self.mta.get_raw_email(),73 self.assertEqual(mta.get_raw_email(), 37 74 self.raw_email) 38 75 sys.stdin.close() 39 76 with self.assertRaises(IOError): 40 self.mta.get_raw_email() 77 mta.get_raw_email() 78 79 tmp_file= open(self.raw_email_file('r')) 80 raw_data = tmp_file.read() 81 tmp_file.close() 82 self.assertEqual(mta.get_raw_email(raw_data), 83 self.raw_email) 84 85 p.terminate() 41 86 42 87 #def save_raw_email(self): -
setup.py
r3 r15 1 import os 1 2 from distutils.core import setup 3 4 def proper_etc_path(): 5 # Yes, I'm ommiting windoze... 6 BSDs = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFlyBSD'] 7 linux = ['Linux'] 8 osx = ['Darwin'] 9 os_name = os.uname()[0] 10 if os_name in BSDs: 11 return '/usr/local/etc/' 12 if os_name in linux or os_name in osx: 13 return '/etc/' 2 14 3 15 setup( … … 11 23 description='Mailing lists management software', 12 24 long_description=open('README').read(), 25 scripts=['bin/postman-server', 'bin/postman-mta'], 26 #data_files=[(proper_etc_path()+'postman', ['conf/postman.conf', 27 # 'conf/postman-mta.conf']), 28 # ] 13 29 )
Note:
See TracChangeset
for help on using the changeset viewer.