Skip to content

nos111/SMTP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 

Repository files navigation

SMTP

Simple Mail Transfer Protocol

 

Overview:

This is a python SMTP server, built using sockets and without the python smtp library, confirming to the rfc 5321

SMTP servers are used to send emails.

Note: I’m not trying to reinvent the wheel, I’m just learning how to build one :)

How it works:

  1. The server is started and the IP that it should listen on should be provided as a command line argument. The port is already decided which is 25.
  2. A client (ex. telnet) will establish a connection to the server
  3. The server will reply with it’s version and code “220”
  4. The client to send “HELO domain” to start a new session where mail transactions can take place.
  5. The server will reply with: “250 clientPort OK”
  6. The client need to send “MAIL FROM:<email>” to start an email transaction
  7. The server will reply with: “250 2.1.0 Ok”
  8. The client need to send rcpt command to indicate the recipient “RCPT TO:<email>”
  9. The server will reply with “250 2.1.5 Ok“
  10. The client should send the data command now to supply the email data.
  11. The server will reply with “354 End data with <CR><LF>.<CR><LF>
  12. The server will keep on receiving data until a dot followed by an enter is received.
  13. The server will start the forwarding procedure:
    1. Start a new thread for forwarding the email.
    2. Perform a DNS lookup to retrieve the mail exchange addresses from the recipient address domain.
    3. Find the mail exchange addresses with the lowest latency.
    4. Connect to the prefered address
    5. Send the commands we received in the correct order.

Notes:

  • The server will not wait until the session end to start forwarding to the receiving end.
  • Since this server is not tied to a domain, it’s only job is to forward emails.
  • No postmaster email is needed because the server that we will forward to will send from a postmaster email any errors that occur.

Compile:

sudo python smtp.py localhost

How to test:

The following steps will send an email from “[email protected]” to “[email protected]” with the subject “testing my smtp server” and a message body of “Dear Nour, This is me testing my server”.

  1. Open a terminal
  2. Go to the directory where the SMTP.py file is located
  3. sudo python SMTP.py localhost
  4. Open another terminal
  5. telnet localhost 25
  6. Send the following lines:
    1. helo me.com
    2. MAIL FROM:<[email protected]>
    3. RCPT TO:<[email protected]>
    4. Data
    5. SUBJECT:  testing my smtp server
    6. FROM: [email protected]
    7. Dear Nour, This is me testing my server
  7. The server will reply with queued.
  8. The email should be available with in a few seconds in the spam.

However if you do the test with a vu email, the email will arrive to the inbox

I have tested the server with thunderbird mail client on ubuntu and the messages were sent properly to the inbox of the receiver.

Commands:

As specified by the rfc5321 section 4.5.1 I have implemented the following commands:
HELO \ EHLO:

Syntax: HELO Hostname

HELO: Marks the beginning of a session.

EHLO: Should only be accepted if the server is an extended mail transfer server(Which is not in our case)

  • Upon receiving the correct syntax the server will respond with “250 OK”
  • If an error in the syntax is received the server will reply with: “501 Syntax: HELO hostname”
  • Sending the “HELO” command at any point in a mail session will reset the mail session, the state and clear all the buffers. As specified by the RFC
  • No mail transaction can be allowed before receiving the HELO command

 

MAIL:

Syntax: MAIL FROM:<[email protected]>

MAIL: Marks the beginning of a mail transaction.

  • Upon receiving the correct syntax the server will respond with “250 OK”
  • If an error in the syntax is received the server will reply with: “501 5.5.4 Syntax: MAIL FROM:<address>”
  • The server will check the correction of the email address format since it’s important for the receiving end.
  • Nested mail commands are not allowed and the server will respond with “503 5.5.1 Error: nested MAIL command
  • If a mail command is used before “HELO” a sequence error reply is returned: “503 5.5.1 Error: send HELO/EHLO first”

 

RCPT:

Syntax: RCPT TO:<[email protected]>

RCPT: gives the recipients) of an email. This command can be send multiple times to indicate multiple recipients. Mailing lists can be implemented but it’s discouraged by the RFC.

  • Upon receiving the correct syntax the server will respond with “250 OK”
  • If an error in the syntax is received the server will reply with: “501 5.5.4 Syntax: RCPT TO:<address>”
  • The server will check the correction of the email address format since it’s crucial for the relaying process to have a domain to relay to.
  • If a “RCPT”  command is used before “MAIL” a sequence error reply is returned: “503 5.5.1 Error: need mail command”


DATA

Syntax: DATA

RCPT: Marks the beginning of the

  • Upon receiving the correct syntax the server will respond with “354 End data with <CR><LF>.<CR><LF>
  • The server will keep on receiving data until a “.\n” is received which will mark the end of the data and the sending operation will start in a new thread.
  • Data command can only be used after: “HELO”, “MAIL”, “RCPT”
  • Each mail transaction will have one data command.

 

RSET:

Syntax: RSET

RSET: Resets the mail session

  • Sending the “RSET” command at any point in a mail session will reset the mail session, the state and clear all the buffers. As specified by the RFC


NOOP

Syntax: NOOP

NOOP: This command does not affect any parameters or previously entered commands.  It specifies no action other than that the receiver send a "250 OK" reply

 

QUIT

Syntax: QUIT

QUIT: This command specifies that the receiver MUST send a "221 OK" reply, and then close the transmission channel.

 

VRFY

Syntax: VRFY emailAddress

VRFY: This command asks the receiver to confirm that the argument identifies a user or mailbox.  If it is a user name, information is returned as specified in Section 3.5.

Due to security concerns this command will never verify an email. However the syntax is checked.

Sessions:

Whenever a connection is received a new thread is started to handle the client. Each thread will maintain its own state variable and whenever “HELO” command is received a txt file is started, using the port number as a name for the file, to keep the sequence of commands used for relaying the email whenever the email transaction is completed.

State:

The state is thread seperate.

state = {

'HELO': False,

'MAIL': False,

'RCPT': False,

'loop': True,

'data': False,

'recipient': "",

'file':0,

'domain': "",

'completedTransaction': False

}

  • HELO is marked as true whenever the “HELO” command is recieved. Without HELO no mail transaction will be allowed.
  • MAIL is marked as true whenever a mail transaction has begun. Without the mail marked as true no recipient command will be allowed.
  • RCPT is marked as true if a mail transaction has already begun. Once marked as true the data command will be allowed.
  • Loop is used to keep the “handleClient” function alive. Whenever a “QUIT” command is received this variable will be marked as false.
  • Recipient is used to keep the email of the recipient in the state for easy access by the resolve domain function.
  • File is used to keep the name of the file being used to record the sequence of commands.
  • Domain is used to save the domain provided with the HELO command.
  • completedTransaction is used to keep track of a client has already completed a mail transaction in this session. If that’s the case than a new file will be started for the new transaction while the earlier transactions are being handled in a seperate thread for forwarding emails.

Multiple connections:

Multiple connections are supported by this server. There is no limit to how many users can connect to the server. I have tested this server with 3 connections on a local network and no problems were discovered by us.

Timeouts:

Unlike an SMTP client which has different timeouts for every state of the session, SMTP servers will timeout the connection after 5 minutes of inactivity.




About

SMTP server using sockets

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages