From a5de2571e34ebddf3b5940086d7227ef2201e65a Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Wed, 28 Mar 2007 08:28:12 +0000 Subject: [PATCH] Better parsing of ESMTP extensions. --- ChangeLog | 4 ++ src/net/smtp/SMTPTransport.cpp | 74 ++++++++++++++++---------------- vmime/net/smtp/SMTPTransport.hpp | 2 +- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4cd1f713..c603d3c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ VERSION 0.8.2cvs ================ +2007-03-28 Vincent Richard + + * SMTPTransport.cpp: better parsing of ESMTP extensions. + 2007-03-02 Vincent Richard * Maildir: added support for "Courier" Maildir. diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp index 55b72278..1233b0b7 100644 --- a/src/net/smtp/SMTPTransport.cpp +++ b/src/net/smtp/SMTPTransport.cpp @@ -191,7 +191,9 @@ void SMTPTransport::helo() // // eg: C: EHLO thismachine.ourdomain.com // S: 250-smtp.theserver.com - // S: 250 AUTH CRAM-MD5 DIGEST-MD5 + // S: 250-AUTH CRAM-MD5 DIGEST-MD5 + // S: 250-PIPELINING + // S: 250 SIZE 2555555555 sendRequest("EHLO " + platform::getHandler()->getHostName()); @@ -213,12 +215,39 @@ void SMTPTransport::helo() } m_extendedSMTP = false; - m_extendedSMTPResponse.clear(); + m_extensions.clear(); } else { m_extendedSMTP = true; - m_extendedSMTPResponse = resp->getText(); + m_extensions.clear(); + + // Get supported extensions from SMTP response + for (int i = 1, n = resp->getLineCount() ; i < n ; ++i) + { + const string line = resp->getLineAt(i).getText(); + std::istringstream iss(line); + + string ext; + iss >> ext; + + // Special case: some servers send "AUTH=LOGIN" + if (ext.length() == 10 && utility::stringUtils::toUpper(ext) == "AUTH=LOGIN") + { + m_extensions["AUTH"].push_back("LOGIN"); + } + // Default case: EXT PARAM1 PARAM2... + else + { + std::vector params; + string param; + + while (iss >> param) + params.push_back(utility::stringUtils::toUpper(param)); + + m_extensions[ext] = params; + } + } } } @@ -277,41 +306,10 @@ void SMTPTransport::authenticateSASL() if (!getAuthenticator().dynamicCast ()) throw exceptions::authentication_error("No SASL authenticator available."); - // Obtain SASL mechanisms supported by server from EHLO response - std::vector saslMechs; - std::istringstream iss(m_extendedSMTPResponse); - - while (!iss.eof()) - { - string line; - std::getline(iss, line); - - std::istringstream liss(line); - string word; - - bool inAuth = false; - - while (liss >> word) - { - if (word.length() == 4 && - (word[0] == 'A' || word[0] == 'a') && - (word[1] == 'U' || word[1] == 'u') && - (word[2] == 'T' || word[2] == 't') && - (word[3] == 'H' || word[3] == 'h')) - { - inAuth = true; - } - else if (inAuth) - { - saslMechs.push_back(word); - } - // Some servers send "AUTH=LOGIN" - else if (word.length() == 10 && utility::stringUtils::toUpper(word) == "AUTH=LOGIN") - { - saslMechs.push_back("LOGIN"); - } - } - } + // Obtain SASL mechanisms supported by server from ESMTP extensions + const std::vector saslMechs = + (m_extensions.find("AUTH") != m_extensions.end()) + ? m_extensions["AUTH"] : std::vector (); if (saslMechs.empty()) throw exceptions::authentication_error("No SASL mechanism available."); diff --git a/vmime/net/smtp/SMTPTransport.hpp b/vmime/net/smtp/SMTPTransport.hpp index ea1d64e8..b8e4ff9a 100644 --- a/vmime/net/smtp/SMTPTransport.hpp +++ b/vmime/net/smtp/SMTPTransport.hpp @@ -89,7 +89,7 @@ private: bool m_authentified; bool m_extendedSMTP; - string m_extendedSMTPResponse; + std::map > m_extensions; ref m_timeoutHandler;