当前位置: 代码迷 >> 综合 >> 《计算机网络自顶向下》Socket Lab3 SMTP Lab
  详细解决方案

《计算机网络自顶向下》Socket Lab3 SMTP Lab

热度:45   发布时间:2023-11-17 17:36:52.0

文章目录

    • 相关博客查阅链接
    • 前引
    • Lab3 SMTP Lab
      • Lab3 文档查阅流程分析
      • Lab3 注意事项
      • SMTP 服务认证过程分析
      • 邮件客户端框架代码
      • 最终核心实现代码
      • Lab3 检验Lab实验成果
        • 163邮箱发件箱(成功发件)
        • qq邮箱收件箱(成功收件)
        • 邮件客户端运行结果


相关博客查阅链接


由衷的感谢以下三个链接博客中的帮助
这个Lab有很多的信息没有给出来 我都是到处在网上乱找 并且再加上尝试终于完成了这个Lab 不容易啊 现在已经是凌晨两点了 今天早上八点钟我就要坐车回到学校了 但还是有很多话想说 把博客写完后再开开心心的睡觉去 这篇博客我会写的很详细 希望能够给大家带来帮助

smtp服务认证过程
Computer-Networking-A-Top-Down-Approach-NOTES
计算机网络套接字编程作业三: 邮件客户


前引


在这篇博客我打算开始编辑的时候 其实这个Lab我都还没有开始做 大概是10点钟左右 那个时候我已经把要回学校的东西全部收拾完了 但是我又想着明天我坐车(尽管会开车 但是一年没开了qwq)去 在路上就一直睡觉 干脆今天晚一点睡觉 于是这个Lab就开始了他的故事

哈哈 说的这么神奇 其实完成这个Lab 卡我卡的最久的就是 第一个 我的邮件服务器第一个是选择的是搜狐服务器 在核对账号的时候 发现搜狐的邮件服务器应该不是直接发送账号过去 而可能是需要在前面加一些其他的东西 那里折腾了半个多小时 之后卡的最久的地方是 base64编码 那里就一直出错 可能是编码的格式不对 反正那里卡了大概一个半小时左右 最后我完成这个Lab大概是花了4个小时左右

我认为这个Lab还是很有价值的 哈哈哈 尽管过程很让人心酸 甚至我一度中途不打算完成了 就是因为账户认证那个地方 但是之后看了我贴的第三个链接的博客的账户密码编码方式 我才改过来 最后这个地方才得以解决

那就先说到这里 后面会详细的写交互流程与注意事项的 ^^


Lab3 SMTP Lab


Lab3 文档查阅流程分析


下载链接如下 中文翻译找到Python3 socket即可
Pearson Computer Networking: a Top-Down Approach, 8th Edition

下面是中文的文档翻译 但说实话 这个说了等于没说 后面会写STMP邮件发送交互的流程分析的
在这里插入图片描述


Lab3 注意事项


1、尽量选择网易163邮箱 邮箱可能选择的动态验证码不同 可能协议也不同
2、密码问题 由于现在的POP3/SMTP协议 一般都已经升级用了授权码 用这个可以保护自己的密码不被泄露 仅泄露授权码- - 然后我们需要自己去网易邮箱那里打开POP3/SMTP服务 我们登陆的密码就是打开服务后的授权码
3、发送信息的格式 我们需要稍微注意一下 需要格式 并以endmsg结尾
4、账户密码需用base64编码 如下格式 发送时再用encode编码
5、在编写代码错误过多时 容易卡住 建议每次尝试时 后面都加一句socket.close() 关闭你的套接字 防止大量创建后出错

base64编码格式示例

mailserver_163_SMTP_Password = base64.b64encode(b'ZLVZ**********').decode() + '\r\n'

SMTP 服务认证过程分析


这里的话还是要大概说一下思路 我们充当的角色就是一个客户端 通过SMTP给一个邮件服务器发信息 由于例如稍微大一点的邮件服务器之间都能互相通信 所以我们就选择的是 一个是网易的 一个是qq邮箱

很详细的全流程大家就看下面的这个链接即可 说的很详细 我还是在下方贴个链接并且把过程贴一下吧 并把状态码贴出来 这里讲了基本上这个实验就做的差不多了
smtp服务认证过程

1、客户端TCP连接服务器25端口
2、三次握手以后,连接建立成功,服务器主动推送服务就绪信息(220 163.com
3、客户与服务器打招呼 给服务器介绍自己 Helo Love6250 OK
4、发出身份认证请求 AUTH LOGIN334 dXNlcm5hbWU6)dX…指的是表示等待输入用户名

5、客户输入用户名(base64编码) (334 UGFzc3dvcmQ6)UG…指的是表示等待输入密码(授权码)
6、客户输入授权码(base64编码)(235 Authentication successful)认证成功 如果账户或者密码中有错的话 会返回535

7、客户输入 发送邮件的用户邮件地址MAIL FROM: <gogo@163.com>\r\n250 Mail OK
8、客户输入 邮件要到达的目的邮件地址 RCPT TO: <runrun@qq.com>\r\n250 Mail OK

9、客户输入 DATA 表示下面即将要发送信息了 (354 End data with <CR><LF>.<CR><LF>
10、客户发送消息 并以\r\n.\r\n结尾 (250 Mail OK queued as smtp14,......)
11、客户发送QUIT表示发送完毕 结束任务 (221 Bye


邮件客户端框架代码


from socket import *
msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"
# Choose a mail server (e.g. Google mail server) and call it mailservermailserver = #Fill in start #Fill in end# Create socket called clientSocket and establish a TCP connection with mailserver
# Fill in start
# Fill in endrecv = 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.')# Send MAIL FROM command and print server response.
# Fill in start
# Fill in end# Send RCPT TO command and print server response. 
# Fill in start
# Fill in end# Send DATA command and print server response. 
# Fill in start
# Fill in end# Send message data. 
# Fill in start
# Fill in end# Message ends with a single period. 
# Fill in start
# Fill in end# Send QUIT command and get server response. 
# Fill in start
# Fill in end

最终核心实现代码


from socket import *
import sys
import base64msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver_163 = 'smtp.163.com'
mailserver_163_SMTP_Port = 25
mailserver_163_SMTP_LoginID  = base64.b64encode(b'lov******@163.com').decode() + '\r\n'
mailserver_163_SMTP_Password = base64.b64encode(b'ZLVZ**********').decode() + '\r\n'From = 'lov******@163.com'
To = '22*********@qq.com'# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((mailserver_163,mailserver_163_SMTP_Port))
recv = clientSocket.recv(1024).decode()
print(recv,end = '')
if recv[:3] != '220':print('220 reply not received from server.')clientSocket.close()exit(0)# Send HELO command and print server response.
heloCommand = 'HELO Love6\r\n'
clientSocket.send(heloCommand.encode())
recv1 = clientSocket.recv(1024).decode()
print(recv1,end = '')
if recv1[:3] != '250':print('250 reply not received from server.')clientSocket.close()exit(0)logCommand = 'AUTH LOGIN\r\n'
clientSocket.send(logCommand.encode())
recv2 = clientSocket.recv(1024).decode()
print(recv2,end = '')
if recv2[:3] != '334':print('334 login server goes wrong')clientSocket.close()exit(0)clientSocket.send(mailserver_163_SMTP_LoginID.encode())
recv3 = clientSocket.recv(1024).decode()
print(recv3,end = '')
if recv3[:3] == '535':print('Login ID wrong')clientSocket.close()exit(0)clientSocket.send(mailserver_163_SMTP_Password.encode())
recv4 = clientSocket.recv(1024).decode()
print(recv4,end = '')
if recv4[:3] == '535':print('Password wrong')clientSocket.close()exit(0)fromCommand = 'MAIL FROM ' + '<' + From + '>' + '\r\n'
clientSocket.send(fromCommand.encode())
recv = clientSocket.recv(2048).decode()
print(recv,end = '')
if recv[:3] != '250':print('Mail From server goes wrong')clientSocket.close()exit(0)toCommand = 'RCPT TO: ' + '<' + To + '>' + '\r\n'
clientSocket.send(toCommand.encode())
recv6 = clientSocket.recv(1024).decode()
print(recv6,end = '')
if recv6[:3] != '250':print('Mail to server goes wrong')clientSocket.close()exit(0)beginCommand = 'DATA\r\n'
clientSocket.send(beginCommand.encode())
recv7 = clientSocket.recv(1024).decode()
print(recv7,end = '')
if recv7[:3] != '354':print('Data Begin server goes wrong')clientSocket.close()exit(0)send = "From: " + From + '\r\n'
send += "To: " + To + '\r\n'
send += "Subject: " + "First Web Mail Test From Love6" + '\r\n'
send += msg
clientSocket.send(send.encode())
clientSocket.send(endmsg.encode())
recv8 = clientSocket.recv(1024).decode()
print(recv8, end='')
if recv8[:3] != '250':print('Data Transport goes wrong')clientSocket.close()exit(0)endCommand = 'QUIT\r\n'
clientSocket.send(endCommand.encode())
recv9 = clientSocket.recv(1024).decode()
print(recv9, end='')
if recv9[:3] != '221':print('server end goes wrong')clientSocket.close()exit(0)
clientSocket.close()

Lab3 检验Lab实验成果


163邮箱发件箱(成功发件)


在这里插入图片描述


qq邮箱收件箱(成功收件)


在这里插入图片描述


邮件客户端运行结果


在这里插入图片描述

  相关解决方案