Python Email Automation

Hi everyone, hope you’re all having a good day. :slight_smile:

You’ve probably created many programs which output interesting files and text. Lets use Python to mass mail these outputs to as many people as we want, as many times as we want, without having to manually fill out 100s of emails.

We can accomplish this using smtplib from the standard python library. Which uses Simple Mail Transfer Protocol aka SMTP.

Code availabe at https://github.com/chr0x6d/python_mail

What you'll need

  • Python 3.7+
  • An email account which supports SMTP (Gmail and Outlook work fine)
  • List of email recipients

Notes

  • I am far from an expert programmer, all criticism is welcome!
  • This program is not secure in its current state, passwords are stored in plain-text. This is for simplicity, adapt the program to your own needs.

Setup

Create a new python file called client.py and lets start with adding in all the imports we’ll need. We’ll discuss these later.

import smtplib
from email.mime.multipart import MIMEMultipart # Creating email messages
from email.mime.text import MIMEText           # Creating email body text
from email.utils import formataddr             # Formatting email headers
from email.mime.base import MIMEBase           # Handling email attachments
from email import encoders                     # Encoding email attachments

import config

Create a new file called config.py, this is to simplify using the program, instead of wading through lots of code to change simple things like the recipient list we only have to edit config.py.

I will be using Gmail but feel free to use any email provider. Ensure config.py is in the same directory as client.py and add the following with your own details:

smtp_addr = 'smtp.gmail.com'      # Gmails SMTP server
smtp_port = 587                   # SMTP supported port for Gmail

attachments = [                   # Locations of Attachments, relative or full path, leave as empty [] for no attachments
    'important.pdf', 
    'cat.png',
    '/opt/opt_cat.jpeg',
]

which_sender_to_use = 0           # Leave at 0 to use the first sender in dictionary
senders = {
    '[email protected]':'PASSWORD',  # Your actual email and password from provider
    '[email protected]':'PASSWORD', # This is not particularly secure, consider using a throw-away account or encryption
}

receivers = {                     # The List of recipients, mail will go to each.
    '[email protected]':'User', # <receiver_email>:<receiver_actual_name(Optional - leave as "" for no-name)>
    '[email protected]':'John Smith',
    '[email protected]':'Captain Jack Sparrow',
}

We use port 587 for Gmail SMTP which allows us to start a plain text conversation then enable TLS afterwards.
That’s it for the setup, now we can jump into starting our SMTP client.

Using SMTP

Now that we have a base to work with, lets go back to client.py.

smtp_client = smtplib.SMTP(config.smtp_addr, config.smtp_port)
# smtp_client.set_debuglevel(True) # Uncomment for verbose logging in console

smtp_client.ehlo() # Extended Hello to SMTP server, client identifies itself to initiate conversation
smtp_client.starttls() # The connection now uses TLS encryption
smtp_client.ehlo() # We introduce ourselves to the server again under TLS

# Grab our username and password from config.py
username = list(config.senders.keys())[config.which_sender_to_use]
password = config.senders[username]

smtp_client.login(username, password) # Attempt to login to our email account

If all went well we will now be logged in to our email account under TLS encryption. If you get an Authentication error and are using Gmail, ensure you have enabled Less Secure Apps. Google classes all login attempts from not within a browser as insecure and blocks them by default.

Creating email messages

We are now able to send emails using SMTP. This is not much use without being able to form sensible email messages complete with subjects, attachments and text. Lets write a message creating function in client.py.

def makeEmailMessage(receiver_name, receiver, subject, attachments=None, extra=''):
    # Make body using f-string, extra is an optional parameter to include text in body.
    body = f"""Hi {receiver_name},

{extra}"""
    msg = MIMEMultipart() # Use MIME standard for email formatting
    msg['From'] = username # Email address used for login
    msg['To'] = formataddr((receiver_name, receiver)) # Actual name of receiver will show instead of email address
    msg['Subject'] = subject
    body = MIMEText(body)
    msg.attach(body) # This does not "attach" the body text as a file, it is added to the text content of email 

    # Handle case of 0 attachments
    if attachments is None:
        attachments = []

    # Every file in attachments will be added to msg using standard email encoding
    # The files local name will be used to name it
    for file in attachments:
        attach_file = open(file, 'rb') # open in binary mode
        email_file = MIMEBase('application', 'octate-stream')
        email_file.set_payload((attach_file).read())
        encoders.encode_base64(email_file)

        email_file.add_header('Content-Disposition', 'attachment', filename=file)
        msg.attach(email_file) # The processed file is now added to the email

    return msg

Mass Mailing

Now we can start spamming emails and annoying everyone in our receivers dictionary from config.py. I’m going to use a for loop in this example. If I was sending a static email with the same content in each email I would not use a loop, instead using a receivers list and sending all the mail at once like in this stack overflow answer.

So, continuing on in client.py:

def genNuclearLaunchCodes(n): # Example of function which isn't purely static
    return ("6E 75 6B 65 21" * n)

iteration = 1
for receiver in config.receivers:
    msg = makeEmailMessage(config.receivers[receiver], receiver, 'SUBJECT HERE', config.attachments, genNuclearLaunchCodes(iteration))
    smtp_client.send_message(msg, username, receiver) # The email will be sent through the SMTP account we've logged into
    print(f'{iteration}: email sent to {receiver} from {username}')
    iteration += 1

Add the correct data into config.py then we can run client.py and our mail will be sent.

That’s the simple python mailer finished, thanks for reading.

11 Likes

Great first post and welcome to the community! Look forward to more.

2 Likes

Thank you @Ph03n1x_Crus4d3r :slight_smile: I read your post on Applications of XSS earlier and it was a great intro to the topic.

1 Like

Very good first approach! Welcome! :slight_smile: