Python 3 - Тайм-аут сокета SMTP после отправки имени пользователя в Gmail - PullRequest
0 голосов
/ 11 октября 2018

Не уверен, если это было задано ранее, но я не могу найти какие-либо решения, которые кажутся работающими.

Я запускаю это на компьютере с Windows 10 с Python 3.6.6.

Для школьного задания мне было поручено написать скрипт 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 голосов
/ 11 октября 2018
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 пытается прочитать с сервера, даже если вы ничего не ожидаете обратно.И код также будет жаловаться, что некоторые коды состояния, возвращаемые с сервера, отличаются от ожидаемых.Но как только это будет исправлено, письмо будет успешно отправлено.

...