#!/usr/bin/env python
"""
Utility Python3 script to manually inspect the behavior of an SMTP server.

Dependencies:
    pip install colorama termcolor

References:
    https://en.wikipedia.org/wiki/List_of_SMTP_server_return_codes
    https://www.samlogic.net/articles/smtp-commands-reference.htm
    https://mailtrap.io/blog/smtp-commands-and-responses/
    http://www.smtp-server.com/simple_mail_verifying.htm
"""

import time
import re
from socket import *
from termcolor import colored

# Test context
SMTP_HOST = "10.10.10.10"
SMTP_PORT = 25
LEGIT_EMAIL_ADDRESSES = ["user1@domain.com", "user2@domain.com"]
NOT_LEGIT_EMAIL_ADDRESS = "dominique.righetto@gmail.com"
LOCAL_SYSTEM_USERS = ["root", "mail", "sshd", "daemon", "syslog"]
ENUMERATION_COMMANDS = ["VRFY", "EXPN"]


def write(client_socket, cmd, throttling=False):
    # Add throttling for some commands to prevent ban
    if throttling:
        time.sleep(1)
    print(f"[>] {cmd}")
    smtp_cmd = f"{cmd}\n"
    client_socket.send(smtp_cmd.encode())
    read(client_socket)


def read(client_socket):
    resp = client_socket.recv(2048)
    resp = resp.decode()
    marker = "<"
    if len(re.findall(r'^25\d', resp[:3])) > 0:
        msg_color = "green"
    elif len(re.findall(r'^(4|5)\d\d', resp[:3])) > 0:
        msg_color = "yellow"
    elif len(re.findall(r'^2(2|3)\d', resp[:3])) > 0 or len(re.findall(r'^3\d\d', resp[:3])) > 0:
        msg_color = "cyan"
        marker = "*"
    else:
        msg_color = "white"
    print(f"[{marker}] " + colored(f"{resp}", msg_color), end="")


client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect((SMTP_HOST, SMTP_PORT))
read(client_socket)
write(client_socket, "HELO righettod.eu")
# Display supported commands
write(client_socket, "HELP")
# Test which SENDER is accepted
for addr in LEGIT_EMAIL_ADDRESSES:
    write(client_socket, f"MAIL FROM: <{addr}>", throttling=True)
    write(client_socket, "RSET")
write(client_socket, f"MAIL FROM: <{NOT_LEGIT_EMAIL_ADDRESS}>")
write(client_socket, "RSET")
write(client_socket, f"MAIL FROM: <{LEGIT_EMAIL_ADDRESSES[0]}>")
# Test which RECIPIENT is accepted
for addr in LEGIT_EMAIL_ADDRESSES:
    write(client_socket, f"RCPT TO: <{addr}>")
write(client_socket, f"RCPT TO: <{NOT_LEGIT_EMAIL_ADDRESS}>")
# Test the behavior of the "VRFY" and "EXPN" commands
for cmd in ENUMERATION_COMMANDS:
    for usr in LOCAL_SYSTEM_USERS:
        write(client_socket, f"{cmd} {usr}", throttling=True)
    for addr in LEGIT_EMAIL_ADDRESSES:
        write(client_socket, f"{cmd} {addr}", throttling=True)
        write(client_socket, f"{cmd} {addr.split('@')[0]}", throttling=True)
# Test sending an email to the local root user
write(client_socket, "RSET")
write(client_socket, f"MAIL FROM: <{NOT_LEGIT_EMAIL_ADDRESS}>")
write(client_socket, "RCPT TO: root")
write(client_socket, "DATA")
write(client_socket, "Test of sending an email to the root user.\n.")
# Finalize the communication in a clean way
write(client_socket, "QUIT")
client_socket.close()
