pythonsmtpemail-client

How can I make my current code send multiple emails using SMTP in Python


I am coding an assignment and got the code to successfully send an email to my email address. How can I correctly use a loop to ask the user if they want to send another email or quit. You can see how I attempted this but it doesn't seem to work. Additionally, How do I make it ask them to log into their outlook account and/or ask them the email address of the recipient?

Many thanks for taking time to read

This is the code:

from socket import *
import ssl
import base64

# Some global variables
SMTP_MAIL_SERVER = 'smtp-mail.outlook.com'
SMTP_TLS_PORT = 587
END_MESSAGE = '\r\n.\r\n'

client_socket = None
ssl_context = None


def send_line(line):
    global client_socket
    print('CLIENT: ' + line.strip())
    client_socket.send(line.encode())
    response = client_socket.recv(1024).decode()
    return response


def get_code(response):
    return int(response[:3])


def connect():
    global client_socket
    global ssl_context
    print('CLIENT: Connecting to ' + SMTP_MAIL_SERVER)
    client_socket = socket(AF_INET, SOCK_STREAM)
    client_socket.connect((SMTP_MAIL_SERVER, SMTP_TLS_PORT))
    response = client_socket.recv(1024).decode()
    return response


def send_ehlo():
    helo = 'ehlo smtp-mail.outlook.com\r\n'
    return send_line(helo)


def send_helo():
    helo = 'helo smtp-mail.outlook.com\r\n'
    return send_line(helo)


def start_tls():
    global client_socket
    global ssl_context
    response = send_line('STARTTLS \r\n')
    ssl_context = ssl._create_stdlib_context()
    client_socket = ssl_context.wrap_socket(client_socket, server_hostname=SMTP_MAIL_SERVER)
    return response


def send_auth_request():
    return send_line('auth login \r\n')


def send_username(username):
    as_bytes = username.encode('ascii')
    as_b64 = base64.b64encode(as_bytes)
    as_utf8 = as_b64.decode('utf-8')
    return send_line(as_utf8 + '\r\n')


def send_password(password):
    as_bytes = password.encode('ascii')
    as_b64 = base64.b64encode(as_bytes)
    as_utf8 = as_b64.decode('utf-8')
    return send_line(as_utf8 + '\r\n')


'''--------------------------------------------------------------------------------
TODO - Implement the functions below this point in order to send a test
       email successfully using SMTP commands  
--------------------------------------------------------------------------------'''

def send_mail_from(sender):
    mail_from = 'MAIL FROM: <' + sender + '>\r\n'
    return send_line(mail_from)

def send_rcpt_to(recipient):
    rcpt_to = 'RCPT TO: <' + recipient + '>\r\n'
    return send_line(rcpt_to)

def send_begin_data():
    return send_line('DATA \r\n')

def send_message(subject, message):
    subject_line = 'Subject: ' + subject + '\r\n'
    body = '\nMessage:' + message + '\r\n'

    return send_line(subject_line + body + END_MESSAGE)

def send_quit():
    return send_line('QUIT \r\n')


'''--------------------------------------------------------------------------------
TODO - Implement the functions above this point in order to send a test
       email successfully using SMTP commands  
--------------------------------------------------------------------------------'''

send_email_question = 1
while send_email_question == 1:
    def send_one_email():


            # Open a TCP connection - the reply should start '220'
            reply = connect()
            print('SERVER: ' + reply)
            # Send a EHLO command - the reply should be a list of supported
            # 'enhanced' SMTP functions each starting '250'
            reply = send_ehlo()
            print('SERVER: ' + reply)
            # Ask the server to switch to TLS - reply should start '220'
            reply = start_tls()
            print('SERVER: ' + reply)
            # Send a HELO command encrypted - reply should start '220'
            reply = send_helo()
            print('SERVER: ' + reply)
            # Send an AUTH LOGIN command
            reply = send_auth_request()
            print('SERVER: ' + reply)
            # Send your (base64 encoded username) -
            reply = send_username('#sending email username')
            print('SERVER: ' + reply)
            # Send your (base64 encoded username) -
            reply = send_password('#sending email password')
            print('SERVER: ' + reply)
            # Send MAILFROM command - TODO - YOU IMPLEMENT THE FUNCTION BELOW
            reply = send_mail_from('#sending email') #sending email
            print('SERVER: ' + reply)
            # Send RCPT TO command - TODO - YOU IMPLEMENT THE FUNCTION BELOW
            reply=send_rcpt_to('#target email') #target email
            print('SERVER: ' + reply)
            # Send DATA command - TODO - YOU IMPLEMENT THE FUNCTION BELOW
            reply = send_begin_data()
            print('SERVER: ' + reply)
            # Send the message (including subject) - TODO - YOU IMPLEMENT THE FUNCTION BELOW
            reply = send_message(subject='Nothing much', message='Hello World')
            print('SERVER: ' + reply)
            # Quit the SMTP session - TODO - YOU IMPLEMENT THE FUNCTION BELOW
            user_end_question = int(input("Please enter 1 if you would like to send another email 0 to end connection: "))
            if user_end_question == 0:
                reply = send_quit()
                print('SERVER: ' + reply)



if __name__ == '__main__':
    send_one_email()

Solution

  • When doing :

    send_email_question = 1
    while send_email_question == 1:
        def send_one_email():
            # ... [snip lots of send/reply]
            user_end_question = int(input("Please enter 1 if you would like to send another email 0 to end connection: "))
            if user_end_question == 0:
                reply = send_quit()
                print('SERVER: ' + reply)
    
    if __name__ == '__main__':
        send_one_email()
    

    you are entering the loop, which creates a function (one def instruction). Then in the if __name__ you call one time the function which was created.

    Instead, you should do :

    def send_one_email():
        # ... [snip lots of send/reply]
    
    if __name__ == '__main__':
        send_email_question = 1
        while send_email_question == 1:
            send_one_email()
            user_end_question = int(input("Please enter 1 if you would like to send another email 0 to end connection: "))
            if user_end_question == 0:
                reply = send_quit()
                print('SERVER: ' + reply)
    

    which is creating the function (only once), then in a loop sending an email and asking whether to quit. This way, the send_one_email just sends one email, and do nothing else. And your "main" part decides how many times to call it.

    99% of the time, you don't want to create functions (def) inside loops.