不确定是否曾经有人问过这个问题,但是我找不到任何可行的解决方案。
我正在使用Python 3.6.6的Windows 10计算机上运行它。
对于学校作业,我的任务是编写一个Python脚本,该脚本通过SMTP和套接字库连接到Gmail,并发送示例消息。以下是我的完整代码,因为我不确定是什么引起了问题:
import socket, ssl, base64
# Initialize variables
msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"
username = '***' # My email address went here
password = '***' # I put my password here
# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver = "smtp.gmail.com"
port = 465
# Send and get response
def send_com(in_string, response_num):
# Only send content if provided, and if in string format, convert to bytes
if in_string != '':
if type(in_string) == str: in_string = in_string.encode()
ssl_clientSocket.send(in_string)
# Get response
recv = ssl_clientSocket.recv(1024).decode()
# If the first three numbers of the response from the server are not '250', we have a problem
if recv[:3] != response_num and response_num != '':
print (recv[:3] + ' reply not received from server.')
else:
print (recv)
# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_clientSocket = ssl.wrap_socket(clientSocket)
ssl_clientSocket.connect((mailserver, port))
send_com('', '220') # SMTP server initialization
send_com('HELO Alice\r\n', '250') # Send HELO command and print server response.
send_com('AUTH LOGIN\r\n', '334') # Authenticate mail server
print ("Username: " + base64.b64encode(username.encode()).decode())
print ("Password: " + base64.b64encode(password.encode()).decode() + "\n")
send_com(base64.b64encode(username.encode()), '334') # Send username
send_com(base64.b64encode(password.encode()), '235') # Sned password
send_com('MAIL From: <' + username + '>\r\n', '250') # Send MAIL FROM command and print server response.
send_com('MAIL From: <' + username + '>\r\n', '250') # Send RCPT TO command and print server response.
send_com('DATA\r\n', '250') # Send DATA command and print server response.
send_com(msg, '') # Send message data.
send_com(endmsg, '') # Message ends with a single period.
send_com('QUIT\r\n', '221') # Send QUIT command and get server response.
#recv5 = ssl_clientSocket.recv(I1024).decode()
我知道在将我的编码用户名发送到Google的服务器后,该应用程序会挂起。它上面的所有代码似乎都可以执行并返回适当的服务器响应,而没有任何问题。但是,一旦到达发送编码用户名的命令,程序就会挂起,直到我关闭终端为止。
答案 0 :(得分:1)
send_com('AUTH LOGIN\r\n', '334') # Authenticate mail server
print ("Username: " + base64.b64encode(username.encode()).decode())
print ("Password: " + base64.b64encode(password.encode()).decode() + "\n")
send_com(base64.b64encode(username.encode()), '334') # Send username
send_com(base64.b64encode(password.encode()), '235') # Sned password
您似乎对LOGIN身份验证方法的工作方式有错误的了解。基本上看起来像这样:
> AUTH LOGIN
< 334 base64("Username:")
> base64(your_username)
< 334 base64("Password:")
> base64(your_password)
因此,您没有将任何"Username: " + base64(your_password)
发送到服务器,而是仅发送了base64编码的密码-当然在结尾处添加了新行。这意味着上面的代码应该更像这样:
send_com('AUTH LOGIN\r\n', '334') # Authenticate mail server
send_com(base64.b64encode(username.encode()) + "\r\n", '334') # Send username
send_com(base64.b64encode(password.encode()) + "\r\n", '235') # Send password
发送用户名和密码的两行都消失了,但剩下的两行是您再次发送用户名和密码的其他行-仅在这种情况下,还会发送新行。
此修复程序将不再被卡在原始位置。
由于您发送到MAIL FROM
而不是MAIL FROM
后跟RCPT TO
的命令,所以稍后会抱怨。由于您的send_com(msg, '')
函数试图从服务器读取数据,因此即使您不希望返回任何内容,它也会卡在send_com
上。该代码还将抱怨服务器返回的某些状态代码与您期望的不同。但是一旦解决,邮件将成功发送。