【问题标题】:Python 3 - Socket SMTP timeout after sending username to GmailPython 3 - 将用户名发送到 Gmail 后的 Socket SMTP 超时
【发布时间】:2019-03-16 22:28:42
【问题描述】:

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

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

【问题讨论】:

  • 你为什么不用smtplib
  • 我会,但我的教授明确告诉我不要。

标签: python sockets smtp gmail


【解决方案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 函数会尝试从服务器读取数据,即使您不希望有任何回报。并且代码还会抱怨从服务器返回的某些状态码与您期望的不同。但是一旦解决了这个问题,邮件就会成功发送。

【讨论】:

  • 感谢您的周到回复!
猜你喜欢
  • 2012-11-14
  • 2021-08-04
  • 2013-03-11
  • 2011-01-27
  • 2013-11-24
  • 2016-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多