1#!/usr/bin/python 2 3import os 4import smtplib 5import thread 6import time 7import sys 8import mailbox 9import string 10from optparse import OptionParser 11 12 13# default host 14HOST = "localhost" 15 16# default port 17PORT = 10024 18 19# default number of concurrent lmtp clients to create 20CLIENTS = 20 21 22# default number of messages to send per lmtp client 23MESSAGES = 100 24 25# default mailbox 26MAILBOX = os.path.join(os.path.dirname(__file__), "testbox") 27 28# username 29USERNAME = "testuser1" 30 31# number of messages to send per session 32RECONNECT = 5 33 34DEBUG = False 35 36tlocks = {} 37tdict = {} 38 39 40class LMTPClient: 41 def __init__(self, hostname, port): 42 self._hostname = hostname 43 self._port = port 44 self.conn = smtplib.SMTP(self._hostname, self._port) 45 self.conn.set_debuglevel(DEBUG) 46 47 def lhlo(self, hostname): 48 return self.conn.docmd('LHLO', hostname) 49 50 def send(self, fromaddr, toaddrs, message): 51 r = self.conn.mail(fromaddr) 52 assert(r[0] == 250) 53 r = self.conn.rcpt(toaddrs) 54 assert(r[0] == 250) 55 r = self.conn.data(message) 56 assert(r[0] == 215) 57 r = self.conn.rset() 58 assert(r[0] == 250) 59 60 def quit(self): 61 return self.conn.quit() 62 63 64def frontloader(*args): 65 tid = args[0] 66 tlocks[tid].acquire() 67 c = LMTPClient(HOST, PORT) 68 r = c.lhlo('host') 69 assert(r[0] == 250) 70 mb = mailbox.mbox(MAILBOX, factory=None, create=False) 71 i = 1 72 while i < MESSAGES: 73 for msg in mb.values(): 74 addr = string.split(msg.get_from())[0] 75 c.send(addr, USERNAME, msg.as_string()) 76 if not i % RECONNECT: 77 c.quit() 78 c = LMTPClient(HOST, PORT) 79 c.lhlo('host') 80 sys.stdout.write('_') 81 else: 82 sys.stdout.write('.') 83 sys.stdout.flush() 84 i = i + 1 85 if i >= MESSAGES: 86 break 87 88 c.quit() 89 tlocks[tid].release() 90 91if __name__ == '__main__': 92 93 parser = OptionParser() 94 parser.add_option("-H", "--host", dest="HOST", 95 help="Hostname to connect to [default: %default]", 96 default=HOST) 97 parser.add_option("-P", "--port", dest="PORT", 98 help="Port to connect to [default: %default]", 99 default=PORT) 100 parser.add_option("-c", "--clients", dest="CLIENTS", 101 help="Number of concurrent clients [default: %default]", 102 default=CLIENTS) 103 parser.add_option("-m", "--mailbox", dest="MAILBOX", 104 help="mailbox to feed to LMTP [default: %default]", 105 default=MAILBOX) 106 parser.add_option("-n", "--messages", dest="MESSAGES", 107 default=MESSAGES, 108 help="number of messsages clients sends [default: %default]") 109 parser.add_option("-u", "--username", dest="USERNAME", 110 default=USERNAME, 111 help="deliver to username [default: %default]") 112 parser.add_option("-r", "--reconnect", dest="RECONNECT", 113 default=RECONNECT, 114 help="Number of messages to send before " \ 115 "reconnecting [default: %default]") 116 117 (options, args) = parser.parse_args() 118 119 HOST = options.HOST 120 PORT = int(options.PORT) 121 CLIENTS = int(options.CLIENTS) 122 MESSAGES = int(options.MESSAGES) 123 MAILBOX = options.MAILBOX 124 USERNAME = options.USERNAME 125 RECONNECT = int(options.RECONNECT) 126 127 # start the client threads 128 for i in range(0, CLIENTS): 129 tlocks[i] = thread.allocate_lock() 130 131 print "Connect to LMTP server: %s:%d" % (HOST, PORT) 132 print "Starting %d clients" % CLIENTS 133 print "Deliver %d messages per client to %s" % (MESSAGES, USERNAME) 134 print "Use messages from %s" % MAILBOX 135 136 for i in range(0, CLIENTS): 137 id = thread.start_new_thread(frontloader, (i,)) 138 tdict[i] = id 139 time.sleep(1) 140 141 time.sleep(5) 142 # wait for the clients to finish 143 while 1: 144 for i in range(0, CLIENTS): 145 done = [] 146 if i in tdict: 147 r = tlocks[i].acquire(0) 148 if r: 149 sys.stdout.write('Q') 150 sys.stdout.flush() 151 tlocks[i].release() 152 done.append(i) 153 for x in done: 154 del(tlocks[x]) 155 del(tdict[x]) 156 if len(tdict.items()) == 0: 157 break 158 time.sleep(1) 159 160 161#EOF 162