如何在 python 中的活动连接上启动 TLS?

2022-01-17 00:00:00 python sockets smtp ssl

问题描述

以下是我当前在端口 587 上连接到 gmail 的 smtp 服务器的代码.发出 STARTTLS 命令后,我将如何完成 TLS 会话的协商并开始发出诸如 AUTH LOGIN 和 MAIL FROM 之类的命令?我省略了 Base64 编码的 gmail 用户名,并将其替换为靠近代码底部的 xxxxxxxx.

The following is my current code for connecting to gmail's smtp server on port 587. After issuing the STARTTLS command how would I finish negotiating the TLS session and begin issuing commands such as AUTH LOGIN and MAIL FROM? I have ommitted my Base64 encoded gmail username and replaced it with xxxxxxxx near the bottom of my code.

这个程序的输出是:

220 mx.google.com ESMTP y10sm3296641yhd.6

220 mx.google.com ESMTP y10sm3296641yhd.6

250-mx.google.com 为您服务,[75.66.47.144]

250-mx.google.com at your service, [75.66.47.144]

250 尺寸 35882577

250-SIZE 35882577

250-8BITMIME

250-8BITMIME

250-STARTTLS

250-STARTTLS

250 个增强状态代码

250 ENHANCEDSTATUSCODES

220 2.0.0 准备启动 TLS

220 2.0.0 Ready to start TLS

from socket import *
import ssl
msg = "
 smtp.."
endmsg = "
.
"

# Mailserver hostname and port to be used.
mailserver = ("smtp.gmail.com", 587)


# Create a socket and create an active TCP connection with the mailserver
clientSocket = socket(AF_INET, SOCK_STREAM);
clientSocket.connect(mailserver)

# Read server response
recv = clientSocket.recv(1024)
print recv
if recv[:3] != '220':
    print '220 reply not received from server.'

# Send EHLO command and print server response.
ehloCommand = 'EHLO smtp.google.com
'
clientSocket.send(ehloCommand)

recv1 = clientSocket.recv(1024)
print recv1
if recv1[:3] != '250':
    print '250 reply not received from server.'

# Send STARTTLS command to server and print server response
command = "STARTTLS
"
clientSocket.send(command)

recv1 = clientSocket.recv(1024)
print recv1
if recv[:3] != '220':
    print '220 reply not received from server.'

# SEND AUTH LOGIN command and Base64 encoded username
command = "AUTH LOGIN xxxxxxxxxxxxx
"
clientSocket.send(command)

recv1 = clientSocket.recv(1024)
print recv1


解决方案

你可以ssl封装一个连接的socket.这会给你一个想法:

You can ssl wrap a connected socket. This will give you the idea:

import ssl
import base64
from socket import *


cc = socket(AF_INET, SOCK_STREAM)
cc.connect(("smtp.gmail.com", 587))
# cc.read(..)

cc.send('helo tester.com
')
cc.send('starttls
')
# cc.read(..) If the server responds ok to starttls
#             tls negotiation needs to happen and all
#             communication is then over the SSL socket 

scc = ssl.wrap_socket(cc, ssl_version=ssl.PROTOCOL_SSLv23)
scc.send('auth login
')
# scc.read(..)

scc.send(base64.b64encode('username')+'
')
scc.send(base64.b64encode('password')+'
')

# css.send(
#  mail from:
#  rcpt to:
#  data
#  etc

查看此页面的 AUTH LOGIN 部​​分以获取有关用户名/密码编码的信息:http://www.samlogic.net/articles/smtp-commands-reference-auth.htm

look at the AUTH LOGIN section of this page for info about the username/password encoding: http://www.samlogic.net/articles/smtp-commands-reference-auth.htm

AUTH LOGIN 命令发送到服务器后,服务器通过发送 BASE64 编码文本来询问用户名和密码(问题)给客户.VXNlcm5hbWU6"是 BASE64 编码文本对于单词Username"和UGFzc3dvcmQ6"是BASE64编码文本对于上面示例中的密码"一词.客户端发送用户名和密码也使用 BASE64 编码.adlxdkej",在上面的例子,是一个 BASE64 编码的用户名,lkujsefxlj"是一个BASE64 编码密码.

After that the AUTH LOGIN command has been sent to the server, the server asks for username and password by sending BASE64 encoded text (questions) to the client. "VXNlcm5hbWU6" is the BASE64 encoded text for the word "Username" and "UGFzc3dvcmQ6" is the BASE64 encoded text for the word "Password" in the example above. The client sends username and password also using BASE64 encoding. "adlxdkej", in the example above, is a BASE64 encoded username and "lkujsefxlj" is a BASE64 encoded password.

相关文章