diff options
Diffstat (limited to 'scripts/profiling/spam.py')
-rwxr-xr-x | scripts/profiling/spam.py | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/scripts/profiling/spam.py b/scripts/profiling/spam.py new file mode 100755 index 00000000..119d8496 --- /dev/null +++ b/scripts/profiling/spam.py @@ -0,0 +1,157 @@ +#!/usr/bin/python + +# Send a lot of messages in parallel. + + +import string +import smtplib +import threading +import logging +import dns.resolver + +from argparse import ArgumentParser + + +SMTP_DEFAULT_PORT = 465 +NUMBER_OF_THREADS = 20 + + +logger = logging.getLogger(__name__) +LOG_FORMAT = '%(asctime)s %(message)s' + + +def _send_email(server, port, subject, to_addr, from_addr, body_text): + """ + Send an email + """ + body = string.join(( + "From: %s" % from_addr, + "To: %s" % to_addr, + "Subject: %s" % subject, + "", + body_text + ), "\r\n") + logger.debug("setting up smtp...") + smtp = smtplib.SMTP_SSL(server, port) + logger.info( + "sending message: (%s, %s, %s, %i)" + % (from_addr, to_addr, server, port)) + smtp.sendmail(from_addr, [to_addr], body) + smtp.quit() + + +def _parse_args(): + parser = ArgumentParser() + parser.add_argument( + 'target_address', + help='The target email address to spam') + parser.add_argument( + 'number_of_messages', type=int, + help='The amount of messages email address to spam') + parser.add_argument( + '--server', '-s', + help='The SMTP server to use') + parser.add_argument( + '--port', '-p', default=SMTP_DEFAULT_PORT, + help='The SMTP port to use') + parser.add_argument( + '--threads', '-t', default=NUMBER_OF_THREADS, + help='The maximum number of parallel threads to launch') + parser.add_argument( + '--debug', '-d', action='store_true', + help='Print debug messages') + return parser.parse_args() + + +class EmailSenderThread(threading.Thread): + + def __init__(self, server, port, subject, to_addr, from_addr, body_text, + finished_fun): + threading.Thread.__init__(self) + logger.debug("initilizing thread...") + self._server = server + self._port = port + self._subject = subject + self._to_addr = to_addr + self._from_addr = from_addr + self._body_text = body_text + self._finished_fun = finished_fun + + def run(self): + logger.debug("running thread...") + try: + _send_email( + self._server, self._port, self._subject, self._to_addr, + self._from_addr, self._body_text) + except Exception as e: + logger.error(e) + finally: + self._finished_fun() + + +def _launch_email_thread(server, port, subject, to_addr, from_addr, body_text, + finished_fun): + logger.debug("will launch email thread...") + thread = EmailSenderThread( + server, port, subject, to_addr, from_addr, body_text, finished_fun) + thread.start() + return thread + + +class FinishedThreads(object): + + def __init__(self): + self._finished = 0 + self._lock = threading.Lock() + + def signal(self): + with self._lock: + self._finished = self._finished + 1 + logger.info('number of messages sent: %d.' % self._finished) + + +def _send_messages(args): + server = args.server + port = args.port + subject = "Message from Soledad script" + to_addr = args.target_address + from_addr = args.target_address + body_text = "Test message" + + # configure log level + if args.debug: + level = logging.DEBUG + else: + level = logging.INFO + logging.basicConfig(format=LOG_FORMAT, level=level) + + # get MX configuration + if not server: + logger.info("Resolving MX server...") + _, domain = to_addr.split("@", 1) + result = dns.resolver.query(domain, "MX") + server = result[0].exchange.to_text() + logger.info("MX server is: %s" % server) + + semaphore = threading.Semaphore(args.threads) + threads = [] + finished_threads = FinishedThreads() + + def _finished_fun(): + semaphore.release() + finished_threads.signal() + + for i in xrange(args.number_of_messages): + semaphore.acquire() + threads.append( + _launch_email_thread( + server, port, subject, to_addr, from_addr, body_text, + _finished_fun)) + + for t in threads: + t.join() + + +if __name__ == "__main__": + args = _parse_args() + _send_messages(args) |