KekSec icon

MULTITHREADED EMAIL SPAMMER - BULK EMAIL EASY

KekSec | PRO | 05/18/20 05:17:36 AM UTC | 0 ⭐ | 1113 👁️ | Never ⏰ | []
Python |

7.39 KB

|

None

|

0 👍

/

0 👎

#!/usr/bin/env python
 
"""
Mass-emailer, reading an email text file and a list of email addresses.
(c) 2009-2015 University of Manchester
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
Author: Stian Soiland-Reyes <[email protected]>
http://orcid.org/0000-0001-9842-9718
 
https://github.com/stain/mailer
 
 
On first run, ~/.mailer is created, and must be configured with the
smtp details.
 
Tested with smtp.gmail.com.
"""
 
 
from ConfigParser import ConfigParser
import email
import email.utils
import getpass
import os
import re
import smtplib
import sys
import time
import threading
DUMMY_USER="[email protected]"
 
def _configpath():
    configpath = os.path.expanduser("~/.mailer")
    if not os.path.exists(configpath):
        open(configpath, "w").close()
        os.chmod(configpath, 0600)
    return configpath
 
_config = None
def config():
    global _config
    if _config is not None:
        return _config
    _config = ConfigParser()
    _config.read(_configpath())
    if not _config.has_section("smtp"):
        template_config()
        save_config()
    return _config
 
def save_config():
    fp = open(_configpath(), "w")
    try:
        config().write(fp)
    finally:
        fp.close()
 
def template_config():
    if not config().has_section("smtp"):
        config().add_section("smtp")
    config().set("smtp", "host", "smtp.gmail.com")
    config().set("smtp", "port", 587)
    config().set("smtp", "tls", True)
    config().set("smtp", "username", DUMMY_USER)
    config().set("smtp", "password", "WrongPassword")
    if not config().has_section("email"):
        config().add_section("email")
    config().set("email", "sender", DUMMY_USER)
    config().set("email", "from", "Dummy User")
 
_smtp = None
def smtp(_smtp):
    if _smtp is not None:
        return _smtp
    if config().get("smtp", "username") == DUMMY_USER:
        print >>sys.stderr, "You need to configure 'smtp' settings in", _configpath()
        sys.exit(2)
    if config().get("email", "sender") == DUMMY_USER:
        print >>sys.stderr, "You need to configure 'email' settings in", _configpath()
        sys.exit(3)
    _smtp = smtplib.SMTP()
    _smtp.connect(config().get("smtp", "host"), config().getint("smtp", "port"))
    if (config().getboolean("smtp", "tls")):
        _smtp.starttls()
    if (config().has_option("smtp", "username")):
        _smtp.login(config().get("smtp", "username"), config().get("smtp", "password"))
    return _smtp
 
def send_email(_smtp, email_filename, to, counter, cc=None):
    text = open(email_filename).read()
    if "John Doe" in text:
        print >>sys.stderr, "You need to edit", email_filename
        sys.exit(4)
 
    ## template to insert a tracking counter that is
    ## unique per email, e.g. into the Subject field
    ## or signature. Note that the counter starttls
    ## from 00 for each execution.
    text = text.replace("--counter--", "%02x" % counter)
    if cc:
        ## template to insert the name of the first CC-ed person
        ## into message, e.g. the recommending "friend"
        first_cc = cc[0].split("<")[0].strip()
        text = text.replace("--friend--", first_cc)
    else:
        ## some kind of fallback
        text = text.replace("--friend--", "someone")
 
    msg = email.message_from_string(text)
 
    # Set standard headers if not already read from
    # file
    msg["MIME-Version"]= "1.0"
    if not msg["Content-Type"]:
        msg["Content-Type"] = "text/plain; charset=UTF-8"
 
    sender_email = config().get("email", "sender")
    sender_from = config().get("email", "from")
    msg["Sender"] = sender_email
    if not msg["From"]:
        msg["From"] = "%s <%s>" % (sender_from, sender_email)
    msg["Date"] = email.utils.formatdate(localtime=True)
    msg["Message-Id"] = email.utils.make_msgid("mailer.py")
    msg["To"] = to
    if (cc):
        msg["Cc"] = ", ".join(cc)
    #to_email = re.split("[<>]", to)[1]
    #print to_email
    ## sendmail seems to parse "Blah Blah <>" format?
 
    recipients = [to]
    if cc:
        recipients += cc
    _smtp.sendmail(sender_email, recipients, msg.as_string())
        
global running
running = 0
def checklist(chunk):
    global running
    running += 1
    threadID = running
    try:
        _smtp = smtp(None)
    except:
        time.sleep(30)
        try:
            _smtp = smtp(None)
        except:
            return
    for recipient in chunk:
        recipient = recipient.strip()
        if "[email protected]" in recipient:
            print >>sys.stderr, "You need to edit", email_filename
            sys.exit(5)
        cc = []
        if ("\t") in recipient:
            # A line with CC
            fields = recipient.split("\t")
            recipient = fields[0]
            cc = fields[1:]
        if recipient.count("<") > 1:
            print "FAILED: More than one email address on line - use \\t (tab character)"
            return
        counter = threadID
        counter += 1
        sent = False
        try:
            while not sent:
                try:
                    send_email(_smtp, sys.argv[1], recipient, counter, cc)
                    print recipient,
                    print "%02x" % counter
                    for also in cc:
                        print "      Cc:", also
                    sent = True
                except smtplib.SMTPServerDisconnected, ex:
                    print recipient,
                    print repr(ex)
                    print "Reconnecting in 5 seconds"
                    time.sleep(5)
                    _smtp.quit()
                    _smtp = None
                    _smtp = smtp(_smtp)
        except Exception, ex:
            #print recipient,
           print repr(ex)
           pass
    running -= 1
 
if __name__ == "__main__":
    config()
    if len(sys.argv) < 3:
        print "Usage:", sys.argv[0], "email.txt", "addresses.txt"
        print ""
        print "Where email.txt is the RC822 formatted email (with headers)"
        print "and addresses.txt is a list of addresses to email, in the form"
        print ""
        print "First Last <[email protected]>"
        print ""
        sys.exit(1)
 
threads=200
def chunkify(lst,n):
    return [ lst[i::n] for i in xrange(n) ]
 
lines = open(sys.argv[2],"r").readlines()
 
lines = map(lambda s: s.strip(), lines) # remove all newlines
 
chunks = chunkify(lines, threads) # make seperate chunk for each thread
for thread in xrange(0,threads):
    if thread >= 384:
        sleep(0.2)
    try:
        threading.Thread(target = checklist, args = (chunks[thread],)).start()
    except:
        pass
print "Scanning... Press enter 3 times to stop."
 
for i in range(0,3):
    raw_input()
 
os.popen("kill -9 " + str(os.getpid()))

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎