Sending Email With Python!

Osei J
4 min readJan 15, 2019

So I was at work today when I realized my resume formatting needed to be fixed. I had some downtime (like I always do) and thought I’d send myself a copy and take care of that (yes, I was planning to work on my resume, while at work). Anyway, I quickly realized that company policy blocks access to gmail, and even further, prevents us from using our corporate email accounts to send out to gmail as well.

After trying to find a workaround, I eventually decided to rebuild my resume using one of the MS Word templates. After about 15 minutes I was finished, but realized I wouldn’t be able to send it from my work PC. Not wanting to wait until I got home, I decided I would look for a tutorial on sending email with Python. Might as well learn something new when you can right?!

I came across a pretty solid tutorial, and did some testing to see if the network admins at the job would block a terminal connection to the SMTP servers for Gmail. NOPE. I thought, “well then, ONWARD!

I followed along the tutorial until I decided I wanted some additional functionality as well as some testing within my script. So I veered off on my own to do some tweaking. I’m a big fan of collecting user input, so I knew immediately I didn’t want to have to open the script to store things like email addresses, and DEFINITELY not passwords. I read up on the getpass library and decided I needed to implement that into my code because why risk showing your password to anyone? Even at the terminal. What getpass does is hide your password, so you can’t even see what you’re typing. It reminds me of how typing an admin password on linux works. Just remember what your typing and you’ll be fine.

Ok next I had to read up on the email library and MIME and honestly, I need to do some more reading on it because I still feel like my understanding still isn’t sharp enough. At a high level, the email library handles email messages. More importantly, you need it to send an email attachment, because it reads files in as binary and encodes them to ASCII, and creates the headers for email as well. Come to think of it, I’ll probably go through the documentation again tonight because at work was too much going on around me for me to really dive into the read.

Anyway, I set up a couple try/except blocks for collecting the file as well as for connecting to gmail and sending the email. I also added some messages within the script as well — when a user decides not to attach a file, when a file is attached successfully, when things don’t go as planned, and finally, when an email is successfully sent. I did this because when I was testing the code initially it got annoying having to wait to see if things would actually work. With messages like these throughout, it lets a user know how things are going!

After some more tweaks here and there, I was able to send my resume to my gmail account successfully!

I threw the script in a github repo so others who are blocked from gmail at work can send email as they please (disclaimer: I’m just joking! Don’t get yourself fired!).

Check the full script out here:

# Script that sends plain text emails w/ or without attachments from a gmail account.import email, smtplib, ssl, getpassfrom email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
port = 465 # for SSL
subject = input("Email subject: ")
sender_email = input("Enter your email address: ")
reciever_email = input("Enter reciever email address: ")
body = input("Enter email body: ")
password = getpass.getpass(prompt="Password: ", stream=None) #IDLE has issue, still shows input. Use terminal!
# Create multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = reciever_email
message["Subject"] = subject
# Add body to email
message.attach(MIMEText(body, "plain"))
prompt = "\n\n********INSTRUCTIONS FOR SENDING********"
prompt += "\nEnter exact filename w/ file extension (ie: example.jpg)."
prompt += "\nMake sure it's located in the same directory as the script!"
prompt += "\nLeave blank to send without attachment."
prompt += "\n\nEnter File: "
filename = input(prompt)try:
if filename:
# Open file in binary mode
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII to send via email
encoders.encode_base64(part)
# Add header as key/value pair
part.add_header(
"Content-Disposition",
f"attachment; filename={filename}",
)
# add attachment to message and convert to string
message.attach(part)
text = message.as_string()
print("file attached!")
else:
text = body
print("No filename provided....sending email")
except:
print("something went wrong")
pass
try:
# Create a secure connection
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, reciever_email, text)
print("Email sent!")
except:
print("Something went wrong.")

That’s all I got for now!

*P.S I’ll likely find something new I want to add to the script and just keep building on it. Maybe make it a GUI? Who knows!

--

--

Osei J

IT Pro, Occasional Music Maker & Blogger. Interested in pretty much all things cloud, cybersecurity and tech related.