Added support for enhanced status codes (RFC-3463).

This commit is contained in:
Vincent Richard 2013-08-14 21:49:24 +02:00
parent 2591c82079
commit 8cd361ff8c
3 changed files with 154 additions and 4 deletions

View File

@ -35,6 +35,8 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
#include <cctype>
namespace vmime {
namespace net {
@ -71,6 +73,12 @@ int SMTPResponse::getCode() const
}
const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const
{
return m_lines[m_lines.size() - 1].getEnhancedCode();
}
const string SMTPResponse::getText() const
{
string text = m_lines[0].getText();
@ -175,7 +183,7 @@ const SMTPResponse::responseLine SMTPResponse::getNextResponse()
else
text = "";
return responseLine(code, text);
return responseLine(code, text, extractEnhancedCode(text));
}
@ -195,6 +203,33 @@ int SMTPResponse::extractResponseCode(const string& response)
}
// static
const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText)
{
enhancedStatusCode enhCode;
std::istringstream iss(responseText);
if (std::isdigit(iss.peek()))
{
iss >> enhCode.klass;
if (iss.get() == '.' && std::isdigit(iss.peek()))
{
iss >> enhCode.subject;
if (iss.get() == '.' && std::isdigit(iss.peek()))
{
iss >> enhCode.detail;
return enhCode;
}
}
}
return enhancedStatusCode(); // no enhanced code found
}
const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const
{
return m_lines[pos];
@ -225,8 +260,8 @@ const SMTPResponse::state SMTPResponse::getCurrentState() const
// SMTPResponse::responseLine
SMTPResponse::responseLine::responseLine(const int code, const string& text)
: m_code(code), m_text(text)
SMTPResponse::responseLine::responseLine(const int code, const string& text, const enhancedStatusCode& enhCode)
: m_code(code), m_text(text), m_enhCode(enhCode)
{
}
@ -243,6 +278,18 @@ int SMTPResponse::responseLine::getCode() const
}
void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode)
{
m_enhCode = enhCode;
}
const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const
{
return m_enhCode;
}
void SMTPResponse::responseLine::setText(const string& text)
{
m_text = text;
@ -255,6 +302,22 @@ const string SMTPResponse::responseLine::getText() const
}
// SMTPResponse::enhancedStatusCode
SMTPResponse::enhancedStatusCode::enhancedStatusCode()
: klass(0), subject(0), detail(0)
{
}
SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode)
: klass(enhCode.klass), subject(enhCode.subject), detail(enhCode.detail)
{
}
} // smtp
} // net
} // vmime

View File

@ -35,6 +35,9 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
VMIME_TEST(testMultiLineResponseDifferentCode)
VMIME_TEST(testIncompleteMultiLineResponse)
VMIME_TEST(testNoResponseText)
VMIME_TEST(testEnhancedStatusCode)
VMIME_TEST(testNoEnhancedStatusCode)
VMIME_TEST(testInvalidEnhancedStatusCode)
VMIME_TEST_LIST_END
@ -171,6 +174,68 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
VASSERT_EQ("Text", "", resp->getText());
}
void testEnhancedStatusCode()
{
vmime::ref <testSocket> socket = vmime::create <testSocket>();
vmime::ref <vmime::net::timeoutHandler> toh =
vmime::create <testTimeoutHandler>();
socket->localSend("250 2.1.5 OK fu13sm4720601wic.7 - gsmtp\r\n");
vmime::net::smtp::SMTPResponse::state responseState;
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
VASSERT_EQ("Code", 250, resp->getCode());
VASSERT_EQ("Lines", 1, resp->getLineCount());
VASSERT_EQ("Text", "2.1.5 OK fu13sm4720601wic.7 - gsmtp", resp->getText());
VASSERT_EQ("Enh.class", 2, resp->getEnhancedCode().klass);
VASSERT_EQ("Enh.subject", 1, resp->getEnhancedCode().subject);
VASSERT_EQ("Enh.detail", 5, resp->getEnhancedCode().detail);
}
void testNoEnhancedStatusCode()
{
vmime::ref <testSocket> socket = vmime::create <testSocket>();
vmime::ref <vmime::net::timeoutHandler> toh =
vmime::create <testTimeoutHandler>();
socket->localSend("354 Go ahead fu13sm4720601wic.7 - gsmtp\r\n");
vmime::net::smtp::SMTPResponse::state responseState;
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
VASSERT_EQ("Code", 354, resp->getCode());
VASSERT_EQ("Lines", 1, resp->getLineCount());
VASSERT_EQ("Text", "Go ahead fu13sm4720601wic.7 - gsmtp", resp->getText());
VASSERT_EQ("Enh.class", 0, resp->getEnhancedCode().klass);
VASSERT_EQ("Enh.subject", 0, resp->getEnhancedCode().subject);
VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail);
}
void testInvalidEnhancedStatusCode()
{
vmime::ref <testSocket> socket = vmime::create <testSocket>();
vmime::ref <vmime::net::timeoutHandler> toh =
vmime::create <testTimeoutHandler>();
socket->localSend("250 4.2 xxx\r\n");
vmime::net::smtp::SMTPResponse::state responseState;
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
VASSERT_EQ("Code", 250, resp->getCode());
VASSERT_EQ("Lines", 1, resp->getLineCount());
VASSERT_EQ("Text", "4.2 xxx", resp->getText());
VASSERT_EQ("Enh.class", 0, resp->getEnhancedCode().klass);
VASSERT_EQ("Enh.subject", 0, resp->getEnhancedCode().subject);
VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail);
}
VMIME_TEST_SUITE_END

View File

@ -60,16 +60,30 @@ public:
string responseBuffer;
};
/** Enhanced status code (as per RFC-3463). */
struct enhancedStatusCode
{
enhancedStatusCode();
enhancedStatusCode(const enhancedStatusCode& enhCode);
unsigned short klass; /**< Success/failure. */
unsigned short subject; /**< Source of anomaly. */
unsigned short detail; /**< Precise error condition. */
};
/** An element of a SMTP response. */
class responseLine
{
public:
responseLine(const int code, const string& text);
responseLine(const int code, const string& text, const enhancedStatusCode& enhCode);
void setCode(const int code);
int getCode() const;
void setEnhancedCode(const enhancedStatusCode& enhCode);
const enhancedStatusCode getEnhancedCode() const;
void setText(const string& text);
const string getText() const;
@ -77,6 +91,7 @@ public:
int m_code;
string m_text;
enhancedStatusCode m_enhCode;
};
/** Receive and parse a new SMTP response from the
@ -97,6 +112,12 @@ public:
*/
int getCode() const;
/** Return the SMTP enhanced status code, if available.
*
* @return enhanced status code
*/
const enhancedStatusCode getEnhancedCode() const;
/** Return the SMTP response text.
* The text of each line is concatenated.
*
@ -140,6 +161,7 @@ private:
const responseLine getNextResponse();
static int extractResponseCode(const string& response);
static const enhancedStatusCode extractEnhancedCode(const string& responseText);
std::vector <responseLine> m_lines;