Python 3-将用户名发送到Gmail后,套接字SMTP超时

时间:2018-10-11 18:34:43

标签: python sockets smtp gmail

不确定是否曾经有人问过这个问题,但是我找不到任何可行的解决方案。

我正在使用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的服务器后,该应用程序会挂起。它上面的所有代码似乎都可以执行并返回适当的服务器响应,而没有任何问题。但是,一旦到达发送编码用户名的命令,程序就会挂起,直到我关闭终端为止。

1 个答案:

答案 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上。该代码还将抱怨服务器返回的某些状态代码与您期望的不同。但是一旦解决,邮件将成功发送。