【问题标题】:How to start TLS on an active connection in python?如何在 python 中的活动连接上启动 TLS?
【发布时间】:2012-09-17 14:52:02
【问题描述】:

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

这个程序的输出是:

220 mx.google.com ESMTP y10sm3296641yhd.6

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

250 尺寸 35882577

250-8BITMIME

250-STARTTLS

250 个增强状态代码

220 2.0.0 准备启动 TLS

from socket import *
import ssl
msg = "\r\n smtp.."
endmsg = "\r\n.\r\n"

# 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\r\n'
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\r\n"
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\r\n"
clientSocket.send(command)

recv1 = clientSocket.recv(1024)
print recv1

【问题讨论】:

  • 为什么不直接使用docs.python.org/library/smtplib.html
  • @MK。我想手动做这个练习。
  • 我是这么认为的。如果不使用用 C 编写的 ssl 模块,则在某处有一个纯 python ssl 模块。可能从 ssl.wrap_socket(self.sock, keyfile, certfile) 开始

标签: python sockets smtp ssl


【解决方案1】:

您可以对连接的套接字进行 ssl 封装。这会给你一个想法:

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\r\n')
cc.send('starttls\r\n')
# 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\r\n')
# scc.read(..)

scc.send(base64.b64encode('username')+'\r\n')
scc.send(base64.b64encode('password')+'\r\n')

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

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

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

【讨论】:

  • 我想补充一点,如果你在cc.send('starttls\r\n')之后不做cc.read(...),那么SSL包装器会被服务器的“准备启动TLS”消息弄糊涂,并给出一个“未知协议” " 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
相关资源
最近更新 更多