2010-05-26 7 views
10

Я хочу использовать учетные данные вошедшего в систему пользователя Windows для аутентификации SMTP-подключения к серверу Exchange с использованием NTLM.SMTP через Exchange с использованием встроенной проверки подлинности Windows (NTLM) с использованием Python

Я осведомлен о python-ntlm модуля и twopatches, которые позволяют проверку подлинности NTLM для SMTP, однако я хочу использовать маркер безопасности текущего пользователя и не должны ввести имя пользователя и пароль.

Очень похожая проблема с Windows Authentication with Python and urllib2.

ответ

10

Несмотря на то, что в нижеприведенном решении используются расширения Python Win32 (пример кода sspi, входящего в состав расширений Python Win32, был очень полезен), исправления SMTP python-ntlm IMAP &, упомянутые в вопросе, также служили полезными руководствами.

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) 
+0

этот код серьезно спас мой бекон! –

+0

@NoahYetter Вы знаете, как и где можно получить 'sspi'? – gt6989b

+0

@ gt6989b прилагается к pywin32 –

3

Великий ответ, но как обновление для питона 3.0+

def asbase64(msg): 
    # encoding the message then convert to string 
    return((base64.b64encode(msg)).decode("utf-8")) 
2

Python 2.7.x будет неудачным отправкой сообщений NTLM типа 3 в связи с пустым ЦМДОМ указанным:

code, response = smtp.docmd("", ntlm_message)

Это приводит к отправке правильного ответа на сервер, однако он предварительно задерживает пространство из-за характера вызова docmd() putcmd().

smtplib.py:

def putcmd(self, cmd, args=""): 
    """Send a command to the server.""" 
    if args == "": 
     str = '%s%s' % (cmd, CRLF) 
    else: 
     str = '%s %s%s' % (cmd, args, CRLF) 
    self.send(str) 

# ... 

def docmd(self, cmd, args=""): 
    """Send a command, and return its response code.""" 
    self.putcmd(cmd, args) 
    return self.getreply() 

, который в итоге принимает путь условия другое, тем самым посылая str(' ' + ntlm_message + CRLF) что приводит к (501, 'Syntax error in parameters or arguments').

Исходя из этого, это просто отправить сообщение NTLM в виде cmd.

code, response = smtp.docmd(ntlm_message)

Исправление к выше ответ был представлен, хотя, кто знает, когда будет рассмотрено/принято.

 Смежные вопросы

  • Нет связанных вопросов^_^