Sending and receiving emails automatically in Python

There are different situations, when you may want to process email messages automatically. I will give some examples related to Vulnerability Management:

  • Send a message to your colleagues that you are going to start a network  vulnerability  scan or WAS scan. It is much better than investigating performance problems in a hurry.
  • Send the results of vulnerability scanning to colleagues or a responsible employee. Many patch management and configuration issues can be delegated to the end user directly without bothering IT department.
  • Process the response (if any) on your message. If it is not, you can send another message or escalate the problem.
  • Send a report with the current security status in the organization to your colleagues and boss.
  • Some systems you can integrate by email only. They will send messages to some email address and you will process them automatically.
  • Maybe you do not like existing email clients and you want to write your own? 😉

Gmail Python IMAP SMTP

In any case, the ability to send e-mails can be very useful. How to do this in python? Let’s assume that your IT team has granted you access to smtp and imap servers.

Sending messages

SMTP is a good and clear protocol for sending messages.

Without SSL

Before making any scripting it may be useful to test sending manually using Telnet. You need to connect to the server and perform some commands.

Note that after AUTH LOGIN the server will suddenly start to speak with you in base64, asking username (“VXNlcm5hbWU6”) and password (“UGFzc3dvcmQ6”), and you will need to answer in base64 also. So, prepare login and passport in base64 form using:

$ echo -n my_email_account | base64
bXlfZW1haWxfYWNjb3VudA==
$ echo -n my_secure_password | base64
bXlfc2VjdXJlX3Bhc3N3b3Jk

If your server works without SSL, you can try to send a message this way:

$ telnet smtp.corporation.com 25
EHLO
AUTH LOGIN
<Server shows VXNlcm5hbWU6 - Username>
bXlfZW1haWxfYWNjb3VudA==  
<Server shows UGFzc3dvcmQ6 - Password>
bXlfc2VjdXJlX3Bhc3N3b3Jk
<Server shows "Authentication successful">
MAIL FROM: my_email_account@corporation.com
RCPT TO: user1@corporation.com
DATA
[Place your message][ENTER]
.[ENTER]

With SSL

Ok, but what if smtp server uses ssl? Let’s try to send a message using Google mail account. First of all go to https://mail.google.com/mail/u/0/#settings/fwdandpop and choose Enable IMAP:

imap gmail

Enable “less secure apps” at https://myaccount.google.com/lesssecureapps:

gmail less secure applications

Addresses of Gmail IMAP and SMTP servers:

gmail email settings

Making username and password in base64:

$ echo -n my_account@gmail.com | base64
bXlfYWNjb3VudEBnbWFpbC5jb20=
$ echo -n my_password | base64
bXlfcGFzc3dvcmQ=

For manual connecting to the Gmail smtp server use openssl tool:

openssl s_client -starttls smtp -connect smtp.gmail.com:587 -crlf -ign_eof
EHLO localhost
AUTH LOGIN
bXlfYWNjb3VudEBnbWFpbC5jb20=
bXlfcGFzc3dvcmQ=
MAIL FROM: <my_account@gmail.com>
RCPT TO: <my_account@gmail.com>
DATA
[Place your message, e.g. "123123"][ENTER]
.[ENTER]
quit

Message received:

gmail telnet sent

Sending with smtplib

Trying to do the the same with smtplib (if your server doesn’t use SSL connection, comment part in is in bold):

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.encoders import encode_base64
import os

login = 'my_account@gmail.com'
password = 'my_password'
sender = 'my_account@gmail.com'
receivers = ['my_account@gmail.com']

msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ", ".join(receivers)
msg['Subject'] = "Test Message"

# Simple text message or HTML
TEXT = "Hello everyone,\n"
TEXT = TEXT + "\n"
TEXT = TEXT + "Important message.\n"
TEXT = TEXT + "\n"
TEXT = TEXT + "Thanks,\n"
TEXT = TEXT + "SMTP Robot"

msg.attach(MIMEText(TEXT))

filenames = ["test.txt", "test.jpg"]
for file in filenames:
    part = MIMEBase('application', 'octet-stream')
    part.set_payload(open(file, 'rb').read())
    encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="%s"'
                    % os.path.basename(file))
    msg.attach(part)

smtpObj = smtplib.SMTP('smtp.gmail.com:587')
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login(login, password)
smtpObj.sendmail(sender, receivers, msg.as_string())

Note attached files test.jpg and test.txt.

Message was received successfully:

Receiving messages with easyimap

IMAP protocol is much trickier. But you can easily get access to the messages with easyimap library. Iterating by messages:

import easyimap

login = 'my_account@gmail.com'
password = 'my_password'

imapper = easyimap.connect('imap.gmail.com', login, password)
for mail_id in imapper.listids(limit=100):
    mail = imapper.mail(mail_id)
    print(mail.from_addr)
    print(mail.to)
    print(mail.cc)
    print(mail.title)
    print(mail.body)
    print(mail.attachments)

Output:

...
my_account@gmail.com
my_account@gmail.com
None
Test Message
Hello everyone,

Important message.

Thanks,
SMTP Robot
[('test.txt', '1\n2\n3\n4\n5\n6\n7\n8\n9\n10', 'application/octet-stream'), ('test.jpg', '\xff\xd8\xff\xe0\x00\x10...ff\xd9', 'application/octet-stream')]
...

You can save simply save attached data in directory “attachments” this way:

for attachment in mail.attachments:
    f = open("attachments/" + attachment[0], "wb")
    f.write(attachment[1])
    f.close()

I hope, that It will be enough for you to start working with email messages in python.

One thought on “Sending and receiving emails automatically in Python

Leave a Reply

Your email address will not be published. Required fields are marked *