使用集成Windows身份验证(NTLM)使用Python通过Exchange进行SMTP

Lou*_*uis 12 python ntlm smtp pywin32

我想使用登录的Windows用户的凭据来验证使用NTLM到Exchange服务器的SMTP连接.

我知道python-ntlm模块和两个 为SMTP启用NTLM身份验证的补丁,但我想使用当前用户的安全令牌而不必提供用户名和密码.

使用Python和urllib2的Windows身份验证非常相似的问题.

Lou*_*uis 14

虽然下面的解决方案仅使用Python Win32扩展(Python Win32扩展中包含的sspi示例代码非常有用),但问题中提到的python-ntlm IMAP和SMTP补丁也是有用的指南.

from smtplib import SMTPException, SMTPAuthenticationError
import string
import base64
import sspi

# NTLM Guide -- http://curl.haxx.se/rfc/ntlm.html

SMTP_EHLO_OKAY = 250
SMTP_AUTH_CHALLENGE = 334
SMTP_AUTH_OKAY = 235

def asbase64(msg):
    return string.replace(base64.encodestring(msg), '\n', '')

def connect_to_exchange_as_current_user(smtp):
    """Example:
    >>> import smtplib
    >>> smtp = smtplib.SMTP("my.smtp.server")
    >>> connect_to_exchange_as_current_user(smtp)
    """

    # Send the SMTP EHLO command
    code, response = smtp.ehlo()
    if code != SMTP_EHLO_OKAY:
        raise SMTPException("Server did not respond as expected to EHLO command")

    sspiclient = sspi.ClientAuth('NTLM')

    # Generate the NTLM Type 1 message
    sec_buffer=None
    err, sec_buffer = sspiclient.authorize(sec_buffer)
    ntlm_message = asbase64(sec_buffer[0].Buffer)

    # Send the NTLM Type 1 message -- Authentication Request
    code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)

    # Verify the NTLM Type 2 response -- Challenge Message
    if code != SMTP_AUTH_CHALLENGE:
        raise SMTPException("Server did not respond as expected to NTLM negotiate message")

    # Generate the NTLM Type 3 message
    err, sec_buffer = sspiclient.authorize(base64.decodestring(response))
    ntlm_message = asbase64(sec_buffer[0].Buffer)

    # Send the NTLM Type 3 message -- Response Message
    code, response = smtp.docmd("", ntlm_message)
    if code != SMTP_AUTH_OKAY:
        raise SMTPAuthenticationError(code, response)
Run Code Online (Sandbox Code Playgroud)


小智 5

很好的答案,但作为python 3.0+的更新

def asbase64(msg):
    # encoding the message then convert to string
    return((base64.b64encode(msg)).decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)