KekSec

MULTITHREADED EMAIL SPAMMER - BULK EMAIL EASY

May 18th, 2020
689
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.39 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. """
  4. Mass-emailer, reading an email text file and a list of email addresses.
  5. (c) 2009-2015 University of Manchester
  6.  
  7.    This program is free software: you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation, either version 3 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  
  20. Author: Stian Soiland-Reyes <stian@soiland-reyes.com>
  21. http://orcid.org/0000-0001-9842-9718
  22.  
  23. https://github.com/stain/mailer
  24.  
  25.  
  26. On first run, ~/.mailer is created, and must be configured with the
  27. smtp details.
  28.  
  29. Tested with smtp.gmail.com.
  30. """
  31.  
  32.  
  33. from ConfigParser import ConfigParser
  34. import email
  35. import email.utils
  36. import getpass
  37. import os
  38. import re
  39. import smtplib
  40. import sys
  41. import time
  42. import threading
  43. DUMMY_USER="nobody@gmail.com"
  44.  
  45. def _configpath():
  46.     configpath = os.path.expanduser("~/.mailer")
  47.     if not os.path.exists(configpath):
  48.         open(configpath, "w").close()
  49.         os.chmod(configpath, 0600)
  50.     return configpath
  51.  
  52. _config = None
  53. def config():
  54.     global _config
  55.     if _config is not None:
  56.         return _config
  57.     _config = ConfigParser()
  58.     _config.read(_configpath())
  59.     if not _config.has_section("smtp"):
  60.         template_config()
  61.         save_config()
  62.     return _config
  63.  
  64. def save_config():
  65.     fp = open(_configpath(), "w")
  66.     try:
  67.         config().write(fp)
  68.     finally:
  69.         fp.close()
  70.  
  71. def template_config():
  72.     if not config().has_section("smtp"):
  73.         config().add_section("smtp")
  74.     config().set("smtp", "host", "smtp.gmail.com")
  75.     config().set("smtp", "port", 587)
  76.     config().set("smtp", "tls", True)
  77.     config().set("smtp", "username", DUMMY_USER)
  78.     config().set("smtp", "password", "WrongPassword")
  79.     if not config().has_section("email"):
  80.         config().add_section("email")
  81.     config().set("email", "sender", DUMMY_USER)
  82.     config().set("email", "from", "Dummy User")
  83.  
  84. _smtp = None
  85. def smtp(_smtp):
  86.     if _smtp is not None:
  87.         return _smtp
  88.     if config().get("smtp", "username") == DUMMY_USER:
  89.         print >>sys.stderr, "You need to configure 'smtp' settings in", _configpath()
  90.         sys.exit(2)
  91.     if config().get("email", "sender") == DUMMY_USER:
  92.         print >>sys.stderr, "You need to configure 'email' settings in", _configpath()
  93.         sys.exit(3)
  94.     _smtp = smtplib.SMTP()
  95.     _smtp.connect(config().get("smtp", "host"), config().getint("smtp", "port"))
  96.     if (config().getboolean("smtp", "tls")):
  97.         _smtp.starttls()
  98.     if (config().has_option("smtp", "username")):
  99.         _smtp.login(config().get("smtp", "username"), config().get("smtp", "password"))
  100.     return _smtp
  101.  
  102. def send_email(_smtp, email_filename, to, counter, cc=None):
  103.     text = open(email_filename).read()
  104.     if "John Doe" in text:
  105.         print >>sys.stderr, "You need to edit", email_filename
  106.         sys.exit(4)
  107.  
  108.     ## template to insert a tracking counter that is
  109.     ## unique per email, e.g. into the Subject field
  110.     ## or signature. Note that the counter starttls
  111.     ## from 00 for each execution.
  112.     text = text.replace("--counter--", "%02x" % counter)
  113.     if cc:
  114.         ## template to insert the name of the first CC-ed person
  115.         ## into message, e.g. the recommending "friend"
  116.         first_cc = cc[0].split("<")[0].strip()
  117.         text = text.replace("--friend--", first_cc)
  118.     else:
  119.         ## some kind of fallback
  120.         text = text.replace("--friend--", "someone")
  121.  
  122.     msg = email.message_from_string(text)
  123.  
  124.     # Set standard headers if not already read from
  125.     # file
  126.     msg["MIME-Version"]= "1.0"
  127.     if not msg["Content-Type"]:
  128.         msg["Content-Type"] = "text/plain; charset=UTF-8"
  129.  
  130.     sender_email = config().get("email", "sender")
  131.     sender_from = config().get("email", "from")
  132.     msg["Sender"] = sender_email
  133.     if not msg["From"]:
  134.         msg["From"] = "%s <%s>" % (sender_from, sender_email)
  135.     msg["Date"] = email.utils.formatdate(localtime=True)
  136.     msg["Message-Id"] = email.utils.make_msgid("mailer.py")
  137.     msg["To"] = to
  138.     if (cc):
  139.         msg["Cc"] = ", ".join(cc)
  140.     #to_email = re.split("[<>]", to)[1]
  141.     #print to_email
  142.     ## sendmail seems to parse "Blah Blah <>" format?
  143.  
  144.     recipients = [to]
  145.     if cc:
  146.         recipients += cc
  147.     _smtp.sendmail(sender_email, recipients, msg.as_string())
  148.        
  149. global running
  150. running = 0
  151. def checklist(chunk):
  152.     global running
  153.     running += 1
  154.     threadID = running
  155.     try:
  156.         _smtp = smtp(None)
  157.     except:
  158.         time.sleep(30)
  159.         try:
  160.             _smtp = smtp(None)
  161.         except:
  162.             return
  163.     for recipient in chunk:
  164.         recipient = recipient.strip()
  165.         if "johndoe@example.com" in recipient:
  166.             print >>sys.stderr, "You need to edit", email_filename
  167.             sys.exit(5)
  168.         cc = []
  169.         if ("\t") in recipient:
  170.             # A line with CC
  171.             fields = recipient.split("\t")
  172.             recipient = fields[0]
  173.             cc = fields[1:]
  174.         if recipient.count("<") > 1:
  175.             print "FAILED: More than one email address on line - use \\t (tab character)"
  176.             return
  177.         counter = threadID
  178.         counter += 1
  179.         sent = False
  180.         try:
  181.             while not sent:
  182.                 try:
  183.                     send_email(_smtp, sys.argv[1], recipient, counter, cc)
  184.                     print recipient,
  185.                     print "%02x" % counter
  186.                     for also in cc:
  187.                         print "      Cc:", also
  188.                     sent = True
  189.                 except smtplib.SMTPServerDisconnected, ex:
  190.                     print recipient,
  191.                     print repr(ex)
  192.                     print "Reconnecting in 5 seconds"
  193.                     time.sleep(5)
  194.                     _smtp.quit()
  195.                     _smtp = None
  196.                     _smtp = smtp(_smtp)
  197.         except Exception, ex:
  198.             #print recipient,
  199.            print repr(ex)
  200.            pass
  201.     running -= 1
  202.  
  203. if __name__ == "__main__":
  204.     config()
  205.     if len(sys.argv) < 3:
  206.         print "Usage:", sys.argv[0], "email.txt", "addresses.txt"
  207.         print ""
  208.         print "Where email.txt is the RC822 formatted email (with headers)"
  209.         print "and addresses.txt is a list of addresses to email, in the form"
  210.         print ""
  211.         print "First Last <email@example.com>"
  212.         print ""
  213.         sys.exit(1)
  214.  
  215. threads=200
  216. def chunkify(lst,n):
  217.     return [ lst[i::n] for i in xrange(n) ]
  218.  
  219. lines = open(sys.argv[2],"r").readlines()
  220.  
  221. lines = map(lambda s: s.strip(), lines) # remove all newlines
  222.  
  223. chunks = chunkify(lines, threads) # make seperate chunk for each thread
  224. for thread in xrange(0,threads):
  225.     if thread >= 384:
  226.         sleep(0.2)
  227.     try:
  228.         threading.Thread(target = checklist, args = (chunks[thread],)).start()
  229.     except:
  230.         pass
  231. print "Scanning... Press enter 3 times to stop."
  232.  
  233. for i in range(0,3):
  234.     raw_input()
  235.  
  236. os.popen("kill -9 " + str(os.getpid()))
Add Comment
Please, Sign In to add comment