SMTP introduction
I won't talk about too many basic concepts. Just turn to the book or Wikipedia,
In short, SMTP is a simple mail transport protocol. Since it is a transport protocol, it is both sending and receiving mail
It is different from POP3 and IMAP
The difference can be seen simply from here
- working process
SMTP is an application layer protocol based on TCP connection and port 25. It is mainly non real-time, because some customers only ask the agent mailbox regularly (15min) for new mail
There is no need to repeat the text here. Wait, the actual operation code uses pictures to analyze the process
SMTP command and answer codes
Response code, return message of the server
code | explain | Solution |
---|---|---|
220 | This message is usually returned after the connection is established | |
250 | Message returned after completing a requested action / command | |
354 | Transmission instructions for specific contents of mail | |
503 | Command sequence error / authorization required | Generally, check the sequence of several key commands first, and then check the authorization / login error |
502 | Command not implemented |
command | parameter |
---|---|
HELO | Host name / opposite name |
MAIL FROM | Own mailbox |
RCPT TO | Opposite mailbox |
DATA | Start transferring data, the body of the message |
AUTH LOGIN | Generally, LOGIN with LOGIN is used for authorization |
Message format of mail
Definition of message format in RFC document
- All messages are composed of ASCII codes
- The message consists of message lines, which are separated by carriage return (CR) and line feed (LF)
- The length of the message cannot exceed 998 characters
- Length of message line ≤ 78 characters (excluding carriage return line feed character)
- The message can include multiple header fields and header contents
- The message may include a body, which must be separated from its header by a blank line
- Unless carriage return and line feed are required, carriage return and line feed are not used in the message
Specific transmission process
Give the code and wireshark first
from socket import * import base64 # Mail content subject = "I love computer networks!" contenttype = "text/plain" msg = "I love computer networks!" endmsg = "\r\n.\r\n" # Choose a mail server (e.g. Google mail server) and call it mailserver # If you don't know, just search the University / enterprise mailbox server directly, most of which are 25 port sending ports mailserver = "***.mail" # Sender and reciever fromaddress = "****@mail" toaddress = "****@qq.com" # Auth information (Encode with base64) username = base64.b64encode(fromaddress.encode()).decode() password = base64.b64encode("******".encode()).decode() # Create socket called clientSocket and establish a TCP connection with mailserver clientSocket = socket(AF_INET, SOCK_STREAM) clientSocket.connect((mailserver, 25)) recv = clientSocket.recv(1024).decode() print(recv) if recv[:3] != '220': print('220 reply not received from server.') # Send HELO command and print server response. heloCommand = 'HELO Alice\r\n' clientSocket.send(heloCommand.encode()) recv1 = clientSocket.recv(1024).decode() print(recv1) if recv1[:3] != '250': print('250 reply not received from server.') # Auth must be authorized after hello clientSocket.sendall('AUTH LOGIN\r\n'.encode()) recv = clientSocket.recv(1024).decode() print(recv) if (recv[:3] != '334'): print('334 reply not received from server') clientSocket.sendall((username + '\r\n').encode()) recv = clientSocket.recv(1024).decode() print(recv) if (recv[:3] != '334'): print('334 reply not received from server') clientSocket.sendall((password + '\r\n').encode()) recv = clientSocket.recv(1024).decode() print(recv) if (recv[:3] != '235'): print('235 reply not received from server') # Send MAIL FROM command and print server response. # Fill in start #sendall will send all the data until the error or all the data are sent, and send will send less than the required number of bytes clientSocket.sendall(('MAIL FROM: <'+fromaddress+'>\r\n').encode()) recv2 = clientSocket.recv(1024).decode() print(recv2) if (recv2[:3] != '250'): print('250 reply not received from server.') # Fill in end # Send RCPT TO command and print server response. # Fill in start the command here is wrong. It's not MAIL, it's RCPT clientSocket.sendall(('RCPT TO: <'+toaddress+'>\r\n').encode()) recv3 = clientSocket.recv(1024).decode() print(recv3) if (recv3[:3] != '250'): print('250 reply not received from server.') # Fill in end # Send DATA command and print server response. # Fill in start clientSocket.send(('DATA\r\n').encode()) recv = clientSocket.recv(1024).decode() print(recv) if (recv[:3] != '354'): print('354 reply not received from server') # Fill in end # Send message data. # Fill in start message = 'from:' + fromaddress + '\r\n' message += 'to:' + toaddress + '\r\n' message += 'subject:' + subject + '\r\n' message += 'Content-Type:' + contenttype + '\r\n' message += '\r\n' + msg clientSocket.sendall(message.encode()) # Fill in end # Message ends with a single period. # Fill in start clientSocket.sendall(endmsg.encode()) recv = clientSocket.recv(1024).decode() print(recv) if (recv[:3] != '250'): print('250 reply not received from server') # Fill in end # Send QUIT command and get server response. # Fill in start clientSocket.sendall('QUIT\r\n'.encode()) # Fill in end clientSocket.close()
Establish a connection first
First establish a TCP connection with socket
Use the mail server to shake hands with the port number to establish a TCP connection, and the server returns 220
After receiving 220, the client sends a HELO command to initiate a session
The server returns 250, which is OK
After the connection is established, you usually need to log in,
Because it is not a self built mail server, it is owned by an enterprise / someone else and requires authorization to log in
The client sends the command AUTH LOGIN. I'm going to log in
The server answers 334 dXNlcm5hbWU6, which means enter username: the latter is base64 encryption code
The customer sends the encrypted account name and password
Server authorization succeeded
Send mail
- The client uses "Mailfrom" to report the sender's mailbox and domain name to the server
- The server responds to the customer with the response code "250", which represents the completion of the request command
- The client reports the recipient's mailbox and domain name to the server with the "RCPT TO" command
- The server responds to the customer with the response code "250", which represents the completion of the request command
- The customer initializes the message transmission with "DTAT" command
- The server responded "354", indicating that mail input is available
- The client transmits the contents of the message to the server in consecutive lines, and each line is terminated with a two character line end identifier (CR and LF). The message ends with a line with only one "."
- The server responds to the customer with the response code "250", which represents the completion of the request command
Connection termination
- Client sends "QUIT" command
- After receiving the command, the server responds to the response code "221" and ends the session