aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2013-08-14 19:49:24 +0000
committerVincent Richard <[email protected]>2013-08-14 19:49:24 +0000
commit8cd361ff8c5b232c52531d8b3acdf07fcf713eb2 (patch)
tree38a4cd2d3507e2bfb8ee21c6859e907f61bdd230
parentAdded missing exports. (diff)
downloadvmime-8cd361ff8c5b232c52531d8b3acdf07fcf713eb2.tar.gz
vmime-8cd361ff8c5b232c52531d8b3acdf07fcf713eb2.zip
Added support for enhanced status codes (RFC-3463).
-rw-r--r--src/net/smtp/SMTPResponse.cpp69
-rw-r--r--tests/net/smtp/SMTPResponseTest.cpp65
-rw-r--r--vmime/net/smtp/SMTPResponse.hpp24
3 files changed, 154 insertions, 4 deletions
diff --git a/src/net/smtp/SMTPResponse.cpp b/src/net/smtp/SMTPResponse.cpp
index 91923339..86a7a7bd 100644
--- a/src/net/smtp/SMTPResponse.cpp
+++ b/src/net/smtp/SMTPResponse.cpp
@@ -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
diff --git a/tests/net/smtp/SMTPResponseTest.cpp b/tests/net/smtp/SMTPResponseTest.cpp
index 85bf7b3a..5e75b6a7 100644
--- a/tests/net/smtp/SMTPResponseTest.cpp
+++ b/tests/net/smtp/SMTPResponseTest.cpp
@@ -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
diff --git a/vmime/net/smtp/SMTPResponse.hpp b/vmime/net/smtp/SMTPResponse.hpp
index eea61801..79b25ee7 100644
--- a/vmime/net/smtp/SMTPResponse.hpp
+++ b/vmime/net/smtp/SMTPResponse.hpp
@@ -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;