Moved POP3 connection-related things to POP3Connection object.
This commit is contained in:
parent
dfe563f391
commit
7ab35173bc
@ -239,6 +239,7 @@ libvmime_messaging_proto_sources = [
|
|||||||
'pop3',
|
'pop3',
|
||||||
[
|
[
|
||||||
'net/pop3/POP3Command.cpp', 'net/pop3/POP3Command.hpp',
|
'net/pop3/POP3Command.cpp', 'net/pop3/POP3Command.hpp',
|
||||||
|
'net/pop3/POP3Connection.cpp', 'net/pop3/POP3Connection.hpp',
|
||||||
'net/pop3/POP3ServiceInfos.cpp', 'net/pop3/POP3ServiceInfos.hpp',
|
'net/pop3/POP3ServiceInfos.cpp', 'net/pop3/POP3ServiceInfos.hpp',
|
||||||
'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
|
'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
|
||||||
'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp',
|
'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp',
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Command.hpp"
|
#include "vmime/net/pop3/POP3Command.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Connection.hpp"
|
||||||
|
|
||||||
#include "vmime/net/socket.hpp"
|
#include "vmime/net/socket.hpp"
|
||||||
|
|
||||||
@ -214,9 +215,9 @@ const string POP3Command::getText() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void POP3Command::writeToSocket(ref <socket> sok)
|
void POP3Command::send(ref <POP3Connection> conn)
|
||||||
{
|
{
|
||||||
sok->send(m_text + "\r\n");
|
conn->getSocket()->send(m_text + "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
642
src/net/pop3/POP3Connection.cpp
Normal file
642
src/net/pop3/POP3Connection.cpp
Normal file
@ -0,0 +1,642 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 3 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/pop3/POP3Connection.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Store.hpp"
|
||||||
|
|
||||||
|
#include "vmime/exception.hpp"
|
||||||
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
|
#include "vmime/security/digest/messageDigestFactory.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/defaultConnectionInfos.hpp"
|
||||||
|
|
||||||
|
#if VMIME_HAVE_SASL_SUPPORT
|
||||||
|
#include "vmime/security/sasl/SASLContext.hpp"
|
||||||
|
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||||
|
|
||||||
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
|
#include "vmime/net/tls/TLSSession.hpp"
|
||||||
|
#include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
|
||||||
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helpers for service properties
|
||||||
|
#define GET_PROPERTY(type, prop) \
|
||||||
|
(m_store.acquire()->getInfos().getPropertyValue <type>(getSession(), \
|
||||||
|
dynamic_cast <const POP3ServiceInfos&>(m_store.acquire()->getInfos()).getProperties().prop))
|
||||||
|
#define HAS_PROPERTY(prop) \
|
||||||
|
(m_store.acquire()->getInfos().hasProperty(getSession(), \
|
||||||
|
dynamic_cast <const POP3ServiceInfos&>(m_store.acquire()->getInfos()).getProperties().prop))
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
POP3Connection::POP3Connection(ref <POP3Store> store, ref <security::authenticator> auth)
|
||||||
|
: m_store(store), m_auth(auth), m_socket(NULL), m_timeoutHandler(NULL),
|
||||||
|
m_authenticated(false), m_secured(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
POP3Connection::~POP3Connection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
disconnect();
|
||||||
|
else if (m_socket)
|
||||||
|
internalDisconnect();
|
||||||
|
}
|
||||||
|
catch (vmime::exception&)
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3Connection::connect()
|
||||||
|
{
|
||||||
|
if (isConnected())
|
||||||
|
throw exceptions::already_connected();
|
||||||
|
|
||||||
|
const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS);
|
||||||
|
const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT);
|
||||||
|
|
||||||
|
ref <POP3Store> store = m_store.acquire();
|
||||||
|
|
||||||
|
// Create the time-out handler
|
||||||
|
if (store->getTimeoutHandlerFactory())
|
||||||
|
m_timeoutHandler = store->getTimeoutHandlerFactory()->create();
|
||||||
|
|
||||||
|
// Create and connect the socket
|
||||||
|
m_socket = store->getSocketFactory()->create(m_timeoutHandler);
|
||||||
|
|
||||||
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
|
if (store->isPOP3S()) // dedicated port/POP3S
|
||||||
|
{
|
||||||
|
ref <tls::TLSSession> tlsSession =
|
||||||
|
tls::TLSSession::create(store->getCertificateVerifier());
|
||||||
|
|
||||||
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
|
tlsSession->getSocket(m_socket);
|
||||||
|
|
||||||
|
m_socket = tlsSocket;
|
||||||
|
|
||||||
|
m_secured = true;
|
||||||
|
m_cntInfos = vmime::create <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
{
|
||||||
|
m_cntInfos = vmime::create <defaultConnectionInfos>(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_socket->connect(address, port);
|
||||||
|
|
||||||
|
// Connection
|
||||||
|
//
|
||||||
|
// eg: C: <connection to server>
|
||||||
|
// --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com>
|
||||||
|
|
||||||
|
ref <POP3Response> response = POP3Response::readResponse
|
||||||
|
(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
if (!response->isSuccess())
|
||||||
|
{
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::connection_greeting_error(response->getFirstLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
|
// Setup secured connection, if requested
|
||||||
|
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
|
||||||
|
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
|
||||||
|
const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
|
||||||
|
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
|
||||||
|
|
||||||
|
if (!store->isPOP3S() && tls) // only if not POP3S
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
startTLS();
|
||||||
|
}
|
||||||
|
// Non-fatal error
|
||||||
|
catch (exceptions::command_error&)
|
||||||
|
{
|
||||||
|
if (tlsRequired)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TLS is not required, so don't bother
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fatal error
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
// Start authentication process
|
||||||
|
authenticate(messageId(response->getText()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3Connection::disconnect()
|
||||||
|
{
|
||||||
|
if (!isConnected())
|
||||||
|
throw exceptions::not_connected();
|
||||||
|
|
||||||
|
internalDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3Connection::internalDisconnect()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
POP3Command::QUIT()->send(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
POP3Response::readResponse(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
}
|
||||||
|
catch (exception&)
|
||||||
|
{
|
||||||
|
// Not important
|
||||||
|
}
|
||||||
|
|
||||||
|
m_socket->disconnect();
|
||||||
|
m_socket = NULL;
|
||||||
|
|
||||||
|
m_timeoutHandler = NULL;
|
||||||
|
|
||||||
|
m_authenticated = false;
|
||||||
|
m_secured = false;
|
||||||
|
|
||||||
|
m_cntInfos = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3Connection::authenticate(const messageId& randomMID)
|
||||||
|
{
|
||||||
|
getAuthenticator()->setService(thisRef().dynamicCast <service>());
|
||||||
|
|
||||||
|
#if VMIME_HAVE_SASL_SUPPORT
|
||||||
|
// First, try SASL authentication
|
||||||
|
if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticateSASL();
|
||||||
|
|
||||||
|
m_authenticated = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (exceptions::authentication_error& e)
|
||||||
|
{
|
||||||
|
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK))
|
||||||
|
{
|
||||||
|
// Can't fallback on APOP/normal authentication
|
||||||
|
internalDisconnect();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ignore, will try APOP/normal authentication
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exception& e)
|
||||||
|
{
|
||||||
|
internalDisconnect();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||||
|
|
||||||
|
// Secured authentication with APOP (if requested and if available)
|
||||||
|
//
|
||||||
|
// eg: C: APOP vincent <digest>
|
||||||
|
// --- S: +OK vincent is a valid mailbox
|
||||||
|
|
||||||
|
const string username = getAuthenticator()->getUsername();
|
||||||
|
const string password = getAuthenticator()->getPassword();
|
||||||
|
|
||||||
|
ref <POP3Connection> conn = thisRef().dynamicCast <POP3Connection>();
|
||||||
|
ref <POP3Response> response;
|
||||||
|
|
||||||
|
if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP))
|
||||||
|
{
|
||||||
|
if (randomMID.getLeft().length() != 0 &&
|
||||||
|
randomMID.getRight().length() != 0)
|
||||||
|
{
|
||||||
|
// <digest> is the result of MD5 applied to "<message-id>password"
|
||||||
|
ref <security::digest::messageDigest> md5 =
|
||||||
|
security::digest::messageDigestFactory::getInstance()->create("md5");
|
||||||
|
|
||||||
|
md5->update(randomMID.generate() + password);
|
||||||
|
md5->finalize();
|
||||||
|
|
||||||
|
POP3Command::APOP(username, md5->getHexDigest())->send(conn);
|
||||||
|
response = POP3Response::readResponse(conn);
|
||||||
|
|
||||||
|
if (response->isSuccess())
|
||||||
|
{
|
||||||
|
m_authenticated = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Some servers close the connection after an unsuccessful APOP
|
||||||
|
// command, so the fallback may not always work...
|
||||||
|
//
|
||||||
|
// S: +OK Qpopper (version 4.0.5) at xxx starting. <30396.1126730747@xxx>
|
||||||
|
// C: APOP plop c5e0a87d088ec71d60e32692d4c5bdf4
|
||||||
|
// S: -ERR [AUTH] Password supplied for "plop" is incorrect.
|
||||||
|
// S: +OK Pop server at xxx signing off.
|
||||||
|
// [Connection closed by foreign host.]
|
||||||
|
|
||||||
|
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK))
|
||||||
|
{
|
||||||
|
// Can't fallback on basic authentication
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::authentication_error(response->getFirstLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure connection is valid (cf. note above)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
POP3Command::NOOP()->send(conn);
|
||||||
|
POP3Response::readResponse(conn);
|
||||||
|
}
|
||||||
|
catch (exceptions::socket_exception&)
|
||||||
|
{
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::authentication_error(response->getFirstLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// APOP not supported
|
||||||
|
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK))
|
||||||
|
{
|
||||||
|
// Can't fallback on basic authentication
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::authentication_error("APOP not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic authentication
|
||||||
|
//
|
||||||
|
// eg: C: USER vincent
|
||||||
|
// --- S: +OK vincent is a valid mailbox
|
||||||
|
//
|
||||||
|
// C: PASS couic
|
||||||
|
// S: +OK vincent's maildrop has 2 messages (320 octets)
|
||||||
|
POP3Command::USER(username)->send(conn);
|
||||||
|
response = POP3Response::readResponse(conn);
|
||||||
|
|
||||||
|
if (!response->isSuccess())
|
||||||
|
{
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::authentication_error(response->getFirstLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
POP3Command::PASS(password)->send(conn);
|
||||||
|
response = POP3Response::readResponse(conn);
|
||||||
|
|
||||||
|
if (!response->isSuccess())
|
||||||
|
{
|
||||||
|
internalDisconnect();
|
||||||
|
throw exceptions::authentication_error(response->getFirstLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_authenticated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_SASL_SUPPORT
|
||||||
|
|
||||||
|
void POP3Connection::authenticateSASL()
|
||||||
|
{
|
||||||
|
if (!getAuthenticator().dynamicCast <security::sasl::SASLAuthenticator>())
|
||||||
|
throw exceptions::authentication_error("No SASL authenticator available.");
|
||||||
|
|
||||||
|
std::vector <string> capa = getCapabilities();
|
||||||
|
std::vector <string> saslMechs;
|
||||||
|
|
||||||
|
for (unsigned int i = 0 ; i < capa.size() ; ++i)
|
||||||
|
{
|
||||||
|
const string& x = capa[i];
|
||||||
|
|
||||||
|
// C: CAPA
|
||||||
|
// S: +OK List of capabilities follows
|
||||||
|
// S: LOGIN-DELAY 0
|
||||||
|
// S: PIPELINING
|
||||||
|
// S: UIDL
|
||||||
|
// S: ...
|
||||||
|
// S: SASL DIGEST-MD5 CRAM-MD5 <-----
|
||||||
|
// S: EXPIRE NEVER
|
||||||
|
// S: ...
|
||||||
|
|
||||||
|
if (x.length() > 5 &&
|
||||||
|
(x[0] == 'S' || x[0] == 's') &&
|
||||||
|
(x[1] == 'A' || x[1] == 'a') &&
|
||||||
|
(x[2] == 'S' || x[2] == 's') &&
|
||||||
|
(x[3] == 'L' || x[3] == 'l') &&
|
||||||
|
(x[4] == ' ' || x[4] == '\t'))
|
||||||
|
{
|
||||||
|
const string list(x.begin() + 5, x.end());
|
||||||
|
|
||||||
|
std::istringstream iss(list);
|
||||||
|
string mech;
|
||||||
|
|
||||||
|
while (iss >> mech)
|
||||||
|
saslMechs.push_back(mech);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saslMechs.empty())
|
||||||
|
throw exceptions::authentication_error("No SASL mechanism available.");
|
||||||
|
|
||||||
|
std::vector <ref <security::sasl::SASLMechanism> > mechList;
|
||||||
|
|
||||||
|
ref <security::sasl::SASLContext> saslContext =
|
||||||
|
vmime::create <security::sasl::SASLContext>();
|
||||||
|
|
||||||
|
for (unsigned int i = 0 ; i < saslMechs.size() ; ++i)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mechList.push_back
|
||||||
|
(saslContext->createMechanism(saslMechs[i]));
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_mechanism&)
|
||||||
|
{
|
||||||
|
// Ignore mechanism
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mechList.empty())
|
||||||
|
throw exceptions::authentication_error("No SASL mechanism available.");
|
||||||
|
|
||||||
|
// Try to suggest a mechanism among all those supported
|
||||||
|
ref <security::sasl::SASLMechanism> suggestedMech =
|
||||||
|
saslContext->suggestMechanism(mechList);
|
||||||
|
|
||||||
|
if (!suggestedMech)
|
||||||
|
throw exceptions::authentication_error("Unable to suggest SASL mechanism.");
|
||||||
|
|
||||||
|
// Allow application to choose which mechanisms to use
|
||||||
|
mechList = getAuthenticator().dynamicCast <security::sasl::SASLAuthenticator>()->
|
||||||
|
getAcceptableMechanisms(mechList, suggestedMech);
|
||||||
|
|
||||||
|
if (mechList.empty())
|
||||||
|
throw exceptions::authentication_error("No SASL mechanism available.");
|
||||||
|
|
||||||
|
// Try each mechanism in the list in turn
|
||||||
|
for (unsigned int i = 0 ; i < mechList.size() ; ++i)
|
||||||
|
{
|
||||||
|
ref <security::sasl::SASLMechanism> mech = mechList[i];
|
||||||
|
|
||||||
|
ref <security::sasl::SASLSession> saslSession =
|
||||||
|
saslContext->createSession("pop3", getAuthenticator(), mech);
|
||||||
|
|
||||||
|
saslSession->init();
|
||||||
|
|
||||||
|
POP3Command::AUTH(mech->getName())->send(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
for (bool cont = true ; cont ; )
|
||||||
|
{
|
||||||
|
ref <POP3Response> response =
|
||||||
|
POP3Response::readResponse(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
switch (response->getCode())
|
||||||
|
{
|
||||||
|
case POP3Response::CODE_OK:
|
||||||
|
{
|
||||||
|
m_socket = saslSession->getSecuredSocket(m_socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case POP3Response::CODE_READY:
|
||||||
|
{
|
||||||
|
byte_t* challenge = 0;
|
||||||
|
long challengeLen = 0;
|
||||||
|
|
||||||
|
byte_t* resp = 0;
|
||||||
|
long respLen = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Extract challenge
|
||||||
|
saslContext->decodeB64(response->getText(), &challenge, &challengeLen);
|
||||||
|
|
||||||
|
// Prepare response
|
||||||
|
saslSession->evaluateChallenge
|
||||||
|
(challenge, challengeLen, &resp, &respLen);
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
|
||||||
|
}
|
||||||
|
catch (exceptions::sasl_exception& e)
|
||||||
|
{
|
||||||
|
if (challenge)
|
||||||
|
{
|
||||||
|
delete [] challenge;
|
||||||
|
challenge = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp)
|
||||||
|
{
|
||||||
|
delete [] resp;
|
||||||
|
resp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel SASL exchange
|
||||||
|
m_socket->sendRaw("*\r\n", 3);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
if (challenge)
|
||||||
|
delete [] challenge;
|
||||||
|
|
||||||
|
if (resp)
|
||||||
|
delete [] resp;
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (challenge)
|
||||||
|
delete [] challenge;
|
||||||
|
|
||||||
|
if (resp)
|
||||||
|
delete [] resp;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
|
||||||
|
cont = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw exceptions::authentication_error
|
||||||
|
("Could not authenticate using SASL: all mechanisms failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
void POP3Connection::startTLS()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
POP3Command::STLS()->send(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
ref <POP3Response> response =
|
||||||
|
POP3Response::readResponse(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
if (!response->isSuccess())
|
||||||
|
throw exceptions::command_error("STLS", response->getFirstLine());
|
||||||
|
|
||||||
|
ref <tls::TLSSession> tlsSession =
|
||||||
|
tls::TLSSession::create(m_store.acquire()->getCertificateVerifier());
|
||||||
|
|
||||||
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
|
tlsSession->getSocket(m_socket);
|
||||||
|
|
||||||
|
tlsSocket->handshake(m_timeoutHandler);
|
||||||
|
|
||||||
|
m_socket = tlsSocket;
|
||||||
|
|
||||||
|
m_secured = true;
|
||||||
|
m_cntInfos = vmime::create <tls::TLSSecuredConnectionInfos>
|
||||||
|
(m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket);
|
||||||
|
}
|
||||||
|
catch (exceptions::command_error&)
|
||||||
|
{
|
||||||
|
// Non-fatal error
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (exception&)
|
||||||
|
{
|
||||||
|
// Fatal error
|
||||||
|
internalDisconnect();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector <string> POP3Connection::getCapabilities()
|
||||||
|
{
|
||||||
|
POP3Command::CAPA()->send(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
ref <POP3Response> response =
|
||||||
|
POP3Response::readMultilineResponse(thisRef().dynamicCast <POP3Connection>());
|
||||||
|
|
||||||
|
std::vector <string> res;
|
||||||
|
|
||||||
|
if (response->isSuccess())
|
||||||
|
{
|
||||||
|
for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i)
|
||||||
|
res.push_back(response->getLineAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool POP3Connection::isConnected() const
|
||||||
|
{
|
||||||
|
return m_socket && m_socket->isConnected() && m_authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool POP3Connection::isSecuredConnection() const
|
||||||
|
{
|
||||||
|
return m_secured;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <connectionInfos> POP3Connection::getConnectionInfos() const
|
||||||
|
{
|
||||||
|
return m_cntInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <POP3Store> POP3Connection::getStore()
|
||||||
|
{
|
||||||
|
return m_store.acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <session> POP3Connection::getSession()
|
||||||
|
{
|
||||||
|
return m_store.acquire()->getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <socket> POP3Connection::getSocket()
|
||||||
|
{
|
||||||
|
return m_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <timeoutHandler> POP3Connection::getTimeoutHandler()
|
||||||
|
{
|
||||||
|
return m_timeoutHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <security::authenticator> POP3Connection::getAuthenticator()
|
||||||
|
{
|
||||||
|
return m_auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // pop3
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
@ -131,10 +131,9 @@ void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable)
|
|||||||
}
|
}
|
||||||
else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")
|
else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")
|
||||||
{
|
{
|
||||||
store->sendRequest(POP3Command::STAT());
|
POP3Command::STAT()->send(store->getConnection());
|
||||||
|
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response = POP3Response::readResponse(store->getConnection());
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("STAT", response->getFirstLine());
|
throw exceptions::command_error("STAT", response->getFirstLine());
|
||||||
@ -166,8 +165,8 @@ void POP3Folder::close(const bool expunge)
|
|||||||
|
|
||||||
if (!expunge)
|
if (!expunge)
|
||||||
{
|
{
|
||||||
store->sendRequest(POP3Command::RSET());
|
POP3Command::RSET()->send(store->getConnection());
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_open = false;
|
m_open = false;
|
||||||
@ -363,11 +362,11 @@ void POP3Folder::fetchMessages(std::vector <ref <message> >& msg, const int opti
|
|||||||
if (options & FETCH_SIZE)
|
if (options & FETCH_SIZE)
|
||||||
{
|
{
|
||||||
// Send the "LIST" command
|
// Send the "LIST" command
|
||||||
store->sendRequest(POP3Command::LIST());
|
POP3Command::LIST()->send(store->getConnection());
|
||||||
|
|
||||||
// Get the response
|
// Get the response
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readMultilineResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readMultilineResponse(store->getConnection());
|
||||||
|
|
||||||
if (response->isSuccess())
|
if (response->isSuccess())
|
||||||
{
|
{
|
||||||
@ -403,11 +402,11 @@ void POP3Folder::fetchMessages(std::vector <ref <message> >& msg, const int opti
|
|||||||
if (options & FETCH_UID)
|
if (options & FETCH_UID)
|
||||||
{
|
{
|
||||||
// Send the "UIDL" command
|
// Send the "UIDL" command
|
||||||
store->sendRequest(POP3Command::UIDL());
|
POP3Command::UIDL()->send(store->getConnection());
|
||||||
|
|
||||||
// Get the response
|
// Get the response
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readMultilineResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readMultilineResponse(store->getConnection());
|
||||||
|
|
||||||
if (response->isSuccess())
|
if (response->isSuccess())
|
||||||
{
|
{
|
||||||
@ -452,11 +451,11 @@ void POP3Folder::fetchMessage(ref <message> msg, const int options)
|
|||||||
if (options & FETCH_SIZE)
|
if (options & FETCH_SIZE)
|
||||||
{
|
{
|
||||||
// Send the "LIST" command
|
// Send the "LIST" command
|
||||||
store->sendRequest(POP3Command::LIST(msg->getNumber()));
|
POP3Command::LIST(msg->getNumber())->send(store->getConnection());
|
||||||
|
|
||||||
// Get the response
|
// Get the response
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (response->isSuccess())
|
if (response->isSuccess())
|
||||||
{
|
{
|
||||||
@ -485,11 +484,11 @@ void POP3Folder::fetchMessage(ref <message> msg, const int options)
|
|||||||
if (options & FETCH_UID)
|
if (options & FETCH_UID)
|
||||||
{
|
{
|
||||||
// Send the "UIDL" command
|
// Send the "UIDL" command
|
||||||
store->sendRequest(POP3Command::UIDL(msg->getNumber()));
|
POP3Command::UIDL(msg->getNumber())->send(store->getConnection());
|
||||||
|
|
||||||
// Get the response
|
// Get the response
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (response->isSuccess())
|
if (response->isSuccess())
|
||||||
{
|
{
|
||||||
@ -569,10 +568,10 @@ void POP3Folder::deleteMessage(const int num)
|
|||||||
else if (!isOpen())
|
else if (!isOpen())
|
||||||
throw exceptions::illegal_state("Folder not open");
|
throw exceptions::illegal_state("Folder not open");
|
||||||
|
|
||||||
store->sendRequest(POP3Command::DELE(num));
|
POP3Command::DELE(num)->send(store->getConnection());
|
||||||
|
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("DELE", response->getFirstLine());
|
throw exceptions::command_error("DELE", response->getFirstLine());
|
||||||
@ -615,10 +614,10 @@ void POP3Folder::deleteMessages(const int from, const int to)
|
|||||||
|
|
||||||
for (int i = from ; i <= to2 ; ++i)
|
for (int i = from ; i <= to2 ; ++i)
|
||||||
{
|
{
|
||||||
store->sendRequest(POP3Command::DELE(i));
|
POP3Command::DELE(i)->send(store->getConnection());
|
||||||
|
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("DELE", response->getFirstLine());
|
throw exceptions::command_error("DELE", response->getFirstLine());
|
||||||
@ -663,10 +662,10 @@ void POP3Folder::deleteMessages(const std::vector <int>& nums)
|
|||||||
for (std::vector <int>::const_iterator
|
for (std::vector <int>::const_iterator
|
||||||
it = nums.begin() ; it != nums.end() ; ++it)
|
it = nums.begin() ; it != nums.end() ; ++it)
|
||||||
{
|
{
|
||||||
store->sendRequest(POP3Command::DELE(*it));
|
POP3Command::DELE(*it)->send(store->getConnection());
|
||||||
|
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("DELE", response->getFirstLine());
|
throw exceptions::command_error("DELE", response->getFirstLine());
|
||||||
@ -760,10 +759,10 @@ void POP3Folder::status(int& count, int& unseen)
|
|||||||
else if (!isOpen())
|
else if (!isOpen())
|
||||||
throw exceptions::illegal_state("Folder not open");
|
throw exceptions::illegal_state("Folder not open");
|
||||||
|
|
||||||
store->sendRequest(POP3Command::STAT());
|
POP3Command::STAT()->send(store->getConnection());
|
||||||
|
|
||||||
ref <POP3Response> response =
|
ref <POP3Response> response =
|
||||||
POP3Response::readResponse(store->m_socket, store->m_timeoutHandler);
|
POP3Response::readResponse(store->getConnection());
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("STAT", response->getFirstLine());
|
throw exceptions::command_error("STAT", response->getFirstLine());
|
||||||
|
@ -142,12 +142,12 @@ void POP3Message::extract(utility::outputStream& os,
|
|||||||
// Emit the "RETR" command
|
// Emit the "RETR" command
|
||||||
ref <POP3Store> store = folder.constCast <POP3Folder>()->m_store.acquire();
|
ref <POP3Store> store = folder.constCast <POP3Folder>()->m_store.acquire();
|
||||||
|
|
||||||
store->sendRequest(POP3Command::RETR(m_num));
|
POP3Command::RETR(m_num)->send(store->getConnection());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
POP3Response::readLargeResponse
|
POP3Response::readLargeResponse
|
||||||
(store->m_socket, store->m_timeoutHandler, os, progress, m_size);
|
(store->getConnection(), os, progress, m_size);
|
||||||
}
|
}
|
||||||
catch (exceptions::command_error& e)
|
catch (exceptions::command_error& e)
|
||||||
{
|
{
|
||||||
@ -198,14 +198,14 @@ void POP3Message::fetch(ref <POP3Folder> msgFolder, const int options)
|
|||||||
// Emit the "TOP" command
|
// Emit the "TOP" command
|
||||||
ref <POP3Store> store = folder->m_store.acquire();
|
ref <POP3Store> store = folder->m_store.acquire();
|
||||||
|
|
||||||
store->sendRequest(POP3Command::TOP(m_num, 0));
|
POP3Command::TOP(m_num, 0)->send(store->getConnection());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string buffer;
|
string buffer;
|
||||||
utility::outputStreamStringAdapter bufferStream(buffer);
|
utility::outputStreamStringAdapter bufferStream(buffer);
|
||||||
|
|
||||||
POP3Response::readLargeResponse(store->m_socket, store->m_timeoutHandler,
|
POP3Response::readLargeResponse(store->getConnection(),
|
||||||
bufferStream, /* progress */ NULL, /* predictedSize */ 0);
|
bufferStream, /* progress */ NULL, /* predictedSize */ 0);
|
||||||
|
|
||||||
m_header = vmime::create <header>();
|
m_header = vmime::create <header>();
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Response.hpp"
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Connection.hpp"
|
||||||
|
|
||||||
#include "vmime/platform.hpp"
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
@ -52,10 +53,10 @@ POP3Response::POP3Response(ref <socket> sok, ref <timeoutHandler> toh)
|
|||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ref <POP3Response> POP3Response::readResponse
|
ref <POP3Response> POP3Response::readResponse(ref <POP3Connection> conn)
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh)
|
|
||||||
{
|
{
|
||||||
ref <POP3Response> resp = vmime::create <POP3Response>(sok, toh);
|
ref <POP3Response> resp = vmime::create <POP3Response>
|
||||||
|
(conn->getSocket(), conn->getTimeoutHandler());
|
||||||
|
|
||||||
string buffer;
|
string buffer;
|
||||||
resp->readResponseImpl(buffer, /* multiLine */ false);
|
resp->readResponseImpl(buffer, /* multiLine */ false);
|
||||||
@ -69,10 +70,10 @@ ref <POP3Response> POP3Response::readResponse
|
|||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ref <POP3Response> POP3Response::readMultilineResponse
|
ref <POP3Response> POP3Response::readMultilineResponse(ref <POP3Connection> conn)
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh)
|
|
||||||
{
|
{
|
||||||
ref <POP3Response> resp = vmime::create <POP3Response>(sok, toh);
|
ref <POP3Response> resp = vmime::create <POP3Response>
|
||||||
|
(conn->getSocket(), conn->getTimeoutHandler());
|
||||||
|
|
||||||
string buffer;
|
string buffer;
|
||||||
resp->readResponseImpl(buffer, /* multiLine */ true);
|
resp->readResponseImpl(buffer, /* multiLine */ true);
|
||||||
@ -96,10 +97,11 @@ ref <POP3Response> POP3Response::readMultilineResponse
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
ref <POP3Response> POP3Response::readLargeResponse
|
ref <POP3Response> POP3Response::readLargeResponse
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh,
|
(ref <POP3Connection> conn, utility::outputStream& os,
|
||||||
utility::outputStream& os, utility::progressListener* progress, const long predictedSize)
|
utility::progressListener* progress, const long predictedSize)
|
||||||
{
|
{
|
||||||
ref <POP3Response> resp = vmime::create <POP3Response>(sok, toh);
|
ref <POP3Response> resp = vmime::create <POP3Response>
|
||||||
|
(conn->getSocket(), conn->getTimeoutHandler());
|
||||||
|
|
||||||
string firstLine;
|
string firstLine;
|
||||||
resp->readResponseImpl(firstLine, os, progress, predictedSize);
|
resp->readResponseImpl(firstLine, os, progress, predictedSize);
|
||||||
|
@ -33,42 +33,17 @@
|
|||||||
#include "vmime/net/pop3/POP3Response.hpp"
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
|
||||||
#include "vmime/exception.hpp"
|
#include "vmime/exception.hpp"
|
||||||
#include "vmime/platform.hpp"
|
|
||||||
#include "vmime/messageId.hpp"
|
|
||||||
#include "vmime/security/digest/messageDigestFactory.hpp"
|
|
||||||
|
|
||||||
#include "vmime/net/defaultConnectionInfos.hpp"
|
|
||||||
|
|
||||||
#if VMIME_HAVE_SASL_SUPPORT
|
|
||||||
#include "vmime/security/sasl/SASLContext.hpp"
|
|
||||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
|
||||||
#include "vmime/net/tls/TLSSession.hpp"
|
|
||||||
#include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
|
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
// Helpers for service properties
|
|
||||||
#define GET_PROPERTY(type, prop) \
|
|
||||||
(getInfos().getPropertyValue <type>(getSession(), \
|
|
||||||
dynamic_cast <const POP3ServiceInfos&>(getInfos()).getProperties().prop))
|
|
||||||
#define HAS_PROPERTY(prop) \
|
|
||||||
(getInfos().hasProperty(getSession(), \
|
|
||||||
dynamic_cast <const POP3ServiceInfos&>(getInfos()).getProperties().prop))
|
|
||||||
|
|
||||||
|
|
||||||
namespace vmime {
|
namespace vmime {
|
||||||
namespace net {
|
namespace net {
|
||||||
namespace pop3 {
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
POP3Store::POP3Store(ref <session> sess, ref <security::authenticator> auth, const bool secured)
|
POP3Store::POP3Store(ref <session> sess, ref <security::authenticator> auth, const bool secured)
|
||||||
: store(sess, getInfosInstance(), auth), m_socket(NULL),
|
: store(sess, getInfosInstance(), auth), m_isPOP3S(secured)
|
||||||
m_authentified(false), m_timeoutHandler(NULL),
|
|
||||||
m_isPOP3S(secured), m_secured(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +54,6 @@ POP3Store::~POP3Store()
|
|||||||
{
|
{
|
||||||
if (isConnected())
|
if (isConnected())
|
||||||
disconnect();
|
disconnect();
|
||||||
else if (m_socket)
|
|
||||||
internalDisconnect();
|
|
||||||
}
|
}
|
||||||
catch (vmime::exception&)
|
catch (vmime::exception&)
|
||||||
{
|
{
|
||||||
@ -136,458 +109,54 @@ void POP3Store::connect()
|
|||||||
if (isConnected())
|
if (isConnected())
|
||||||
throw exceptions::already_connected();
|
throw exceptions::already_connected();
|
||||||
|
|
||||||
const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS);
|
m_connection = vmime::create <POP3Connection>
|
||||||
const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT);
|
(thisRef().dynamicCast <POP3Store>(), getAuthenticator());
|
||||||
|
|
||||||
// Create the time-out handler
|
|
||||||
if (getTimeoutHandlerFactory())
|
|
||||||
m_timeoutHandler = getTimeoutHandlerFactory()->create();
|
|
||||||
|
|
||||||
// Create and connect the socket
|
|
||||||
m_socket = getSocketFactory()->create(m_timeoutHandler);
|
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
|
||||||
if (m_isPOP3S) // dedicated port/POP3S
|
|
||||||
{
|
|
||||||
ref <tls::TLSSession> tlsSession =
|
|
||||||
tls::TLSSession::create(getCertificateVerifier());
|
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
|
||||||
tlsSession->getSocket(m_socket);
|
|
||||||
|
|
||||||
m_socket = tlsSocket;
|
|
||||||
|
|
||||||
m_secured = true;
|
|
||||||
m_cntInfos = vmime::create <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
|
||||||
{
|
|
||||||
m_cntInfos = vmime::create <defaultConnectionInfos>(address, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_socket->connect(address, port);
|
|
||||||
|
|
||||||
// Connection
|
|
||||||
//
|
|
||||||
// eg: C: <connection to server>
|
|
||||||
// --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com>
|
|
||||||
|
|
||||||
ref <POP3Response> response = readResponse();
|
|
||||||
|
|
||||||
if (!response->isSuccess())
|
|
||||||
{
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::connection_greeting_error(response->getFirstLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
|
||||||
// Setup secured connection, if requested
|
|
||||||
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
|
|
||||||
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
|
|
||||||
const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
|
|
||||||
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
|
|
||||||
|
|
||||||
if (!m_isPOP3S && tls) // only if not POP3S
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
startTLS();
|
|
||||||
}
|
|
||||||
// Non-fatal error
|
|
||||||
catch (exceptions::command_error&)
|
|
||||||
{
|
|
||||||
if (tlsRequired)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TLS is not required, so don't bother
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fatal error
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
|
||||||
|
|
||||||
// Start authentication process
|
|
||||||
authenticate(messageId(response->getText()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void POP3Store::authenticate(const messageId& randomMID)
|
|
||||||
{
|
|
||||||
getAuthenticator()->setService(thisRef().dynamicCast <service>());
|
|
||||||
|
|
||||||
#if VMIME_HAVE_SASL_SUPPORT
|
|
||||||
// First, try SASL authentication
|
|
||||||
if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
authenticateSASL();
|
|
||||||
|
|
||||||
m_authentified = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (exceptions::authentication_error& e)
|
|
||||||
{
|
|
||||||
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK))
|
|
||||||
{
|
|
||||||
// Can't fallback on APOP/normal authentication
|
|
||||||
internalDisconnect();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Ignore, will try APOP/normal authentication
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (exception& e)
|
|
||||||
{
|
|
||||||
internalDisconnect();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
|
||||||
|
|
||||||
// Secured authentication with APOP (if requested and if available)
|
|
||||||
//
|
|
||||||
// eg: C: APOP vincent <digest>
|
|
||||||
// --- S: +OK vincent is a valid mailbox
|
|
||||||
|
|
||||||
const string username = getAuthenticator()->getUsername();
|
|
||||||
const string password = getAuthenticator()->getPassword();
|
|
||||||
|
|
||||||
ref <POP3Response> response;
|
|
||||||
|
|
||||||
if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP))
|
|
||||||
{
|
|
||||||
if (randomMID.getLeft().length() != 0 &&
|
|
||||||
randomMID.getRight().length() != 0)
|
|
||||||
{
|
|
||||||
// <digest> is the result of MD5 applied to "<message-id>password"
|
|
||||||
ref <security::digest::messageDigest> md5 =
|
|
||||||
security::digest::messageDigestFactory::getInstance()->create("md5");
|
|
||||||
|
|
||||||
md5->update(randomMID.generate() + password);
|
|
||||||
md5->finalize();
|
|
||||||
|
|
||||||
sendRequest(POP3Command::APOP(username, md5->getHexDigest()));
|
|
||||||
response = readResponse();
|
|
||||||
|
|
||||||
if (response->isSuccess())
|
|
||||||
{
|
|
||||||
m_authentified = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Some servers close the connection after an unsuccessful APOP
|
|
||||||
// command, so the fallback may not always work...
|
|
||||||
//
|
|
||||||
// S: +OK Qpopper (version 4.0.5) at xxx starting. <30396.1126730747@xxx>
|
|
||||||
// C: APOP plop c5e0a87d088ec71d60e32692d4c5bdf4
|
|
||||||
// S: -ERR [AUTH] Password supplied for "plop" is incorrect.
|
|
||||||
// S: +OK Pop server at xxx signing off.
|
|
||||||
// [Connection closed by foreign host.]
|
|
||||||
|
|
||||||
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK))
|
|
||||||
{
|
|
||||||
// Can't fallback on basic authentication
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::authentication_error(response->getFirstLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure connection is valid (cf. note above)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sendRequest(POP3Command::NOOP());
|
|
||||||
readResponse();
|
|
||||||
}
|
|
||||||
catch (exceptions::socket_exception&)
|
|
||||||
{
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::authentication_error(response->getFirstLine());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// APOP not supported
|
|
||||||
if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK))
|
|
||||||
{
|
|
||||||
// Can't fallback on basic authentication
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::authentication_error("APOP not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic authentication
|
|
||||||
//
|
|
||||||
// eg: C: USER vincent
|
|
||||||
// --- S: +OK vincent is a valid mailbox
|
|
||||||
//
|
|
||||||
// C: PASS couic
|
|
||||||
// S: +OK vincent's maildrop has 2 messages (320 octets)
|
|
||||||
sendRequest(POP3Command::USER(username));
|
|
||||||
response = readResponse();
|
|
||||||
|
|
||||||
if (!response->isSuccess())
|
|
||||||
{
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::authentication_error(response->getFirstLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRequest(POP3Command::PASS(password));
|
|
||||||
response = readResponse();
|
|
||||||
|
|
||||||
if (!response->isSuccess())
|
|
||||||
{
|
|
||||||
internalDisconnect();
|
|
||||||
throw exceptions::authentication_error(response->getFirstLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_authentified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_SASL_SUPPORT
|
|
||||||
|
|
||||||
void POP3Store::authenticateSASL()
|
|
||||||
{
|
|
||||||
if (!getAuthenticator().dynamicCast <security::sasl::SASLAuthenticator>())
|
|
||||||
throw exceptions::authentication_error("No SASL authenticator available.");
|
|
||||||
|
|
||||||
std::vector <string> capa = getCapabilities();
|
|
||||||
std::vector <string> saslMechs;
|
|
||||||
|
|
||||||
for (unsigned int i = 0 ; i < capa.size() ; ++i)
|
|
||||||
{
|
|
||||||
const string& x = capa[i];
|
|
||||||
|
|
||||||
// C: CAPA
|
|
||||||
// S: +OK List of capabilities follows
|
|
||||||
// S: LOGIN-DELAY 0
|
|
||||||
// S: PIPELINING
|
|
||||||
// S: UIDL
|
|
||||||
// S: ...
|
|
||||||
// S: SASL DIGEST-MD5 CRAM-MD5 <-----
|
|
||||||
// S: EXPIRE NEVER
|
|
||||||
// S: ...
|
|
||||||
|
|
||||||
if (x.length() > 5 &&
|
|
||||||
(x[0] == 'S' || x[0] == 's') &&
|
|
||||||
(x[1] == 'A' || x[1] == 'a') &&
|
|
||||||
(x[2] == 'S' || x[2] == 's') &&
|
|
||||||
(x[3] == 'L' || x[3] == 'l') &&
|
|
||||||
(x[4] == ' ' || x[4] == '\t'))
|
|
||||||
{
|
|
||||||
const string list(x.begin() + 5, x.end());
|
|
||||||
|
|
||||||
std::istringstream iss(list);
|
|
||||||
string mech;
|
|
||||||
|
|
||||||
while (iss >> mech)
|
|
||||||
saslMechs.push_back(mech);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saslMechs.empty())
|
|
||||||
throw exceptions::authentication_error("No SASL mechanism available.");
|
|
||||||
|
|
||||||
std::vector <ref <security::sasl::SASLMechanism> > mechList;
|
|
||||||
|
|
||||||
ref <security::sasl::SASLContext> saslContext =
|
|
||||||
vmime::create <security::sasl::SASLContext>();
|
|
||||||
|
|
||||||
for (unsigned int i = 0 ; i < saslMechs.size() ; ++i)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mechList.push_back
|
|
||||||
(saslContext->createMechanism(saslMechs[i]));
|
|
||||||
}
|
|
||||||
catch (exceptions::no_such_mechanism&)
|
|
||||||
{
|
|
||||||
// Ignore mechanism
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mechList.empty())
|
|
||||||
throw exceptions::authentication_error("No SASL mechanism available.");
|
|
||||||
|
|
||||||
// Try to suggest a mechanism among all those supported
|
|
||||||
ref <security::sasl::SASLMechanism> suggestedMech =
|
|
||||||
saslContext->suggestMechanism(mechList);
|
|
||||||
|
|
||||||
if (!suggestedMech)
|
|
||||||
throw exceptions::authentication_error("Unable to suggest SASL mechanism.");
|
|
||||||
|
|
||||||
// Allow application to choose which mechanisms to use
|
|
||||||
mechList = getAuthenticator().dynamicCast <security::sasl::SASLAuthenticator>()->
|
|
||||||
getAcceptableMechanisms(mechList, suggestedMech);
|
|
||||||
|
|
||||||
if (mechList.empty())
|
|
||||||
throw exceptions::authentication_error("No SASL mechanism available.");
|
|
||||||
|
|
||||||
// Try each mechanism in the list in turn
|
|
||||||
for (unsigned int i = 0 ; i < mechList.size() ; ++i)
|
|
||||||
{
|
|
||||||
ref <security::sasl::SASLMechanism> mech = mechList[i];
|
|
||||||
|
|
||||||
ref <security::sasl::SASLSession> saslSession =
|
|
||||||
saslContext->createSession("pop3", getAuthenticator(), mech);
|
|
||||||
|
|
||||||
saslSession->init();
|
|
||||||
|
|
||||||
sendRequest(POP3Command::AUTH(mech->getName()));
|
|
||||||
|
|
||||||
for (bool cont = true ; cont ; )
|
|
||||||
{
|
|
||||||
ref <POP3Response> response = readResponse();
|
|
||||||
|
|
||||||
switch (response->getCode())
|
|
||||||
{
|
|
||||||
case POP3Response::CODE_OK:
|
|
||||||
{
|
|
||||||
m_socket = saslSession->getSecuredSocket(m_socket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case POP3Response::CODE_READY:
|
|
||||||
{
|
|
||||||
byte_t* challenge = 0;
|
|
||||||
long challengeLen = 0;
|
|
||||||
|
|
||||||
byte_t* resp = 0;
|
|
||||||
long respLen = 0;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Extract challenge
|
|
||||||
saslContext->decodeB64(response->getText(), &challenge, &challengeLen);
|
|
||||||
|
|
||||||
// Prepare response
|
|
||||||
saslSession->evaluateChallenge
|
|
||||||
(challenge, challengeLen, &resp, &respLen);
|
|
||||||
|
|
||||||
// Send response
|
|
||||||
m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
|
|
||||||
}
|
|
||||||
catch (exceptions::sasl_exception& e)
|
|
||||||
{
|
|
||||||
if (challenge)
|
|
||||||
{
|
|
||||||
delete [] challenge;
|
|
||||||
challenge = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resp)
|
|
||||||
{
|
|
||||||
delete [] resp;
|
|
||||||
resp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel SASL exchange
|
|
||||||
m_socket->sendRaw("*\r\n", 3);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
if (challenge)
|
|
||||||
delete [] challenge;
|
|
||||||
|
|
||||||
if (resp)
|
|
||||||
delete [] resp;
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (challenge)
|
|
||||||
delete [] challenge;
|
|
||||||
|
|
||||||
if (resp)
|
|
||||||
delete [] resp;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
|
|
||||||
cont = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw exceptions::authentication_error
|
|
||||||
("Could not authenticate using SASL: all mechanisms failed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
|
||||||
|
|
||||||
void POP3Store::startTLS()
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sendRequest(POP3Command::STLS());
|
m_connection->connect();
|
||||||
|
|
||||||
ref <POP3Response> response = readResponse();
|
|
||||||
|
|
||||||
if (!response->isSuccess())
|
|
||||||
throw exceptions::command_error("STLS", response->getFirstLine());
|
|
||||||
|
|
||||||
ref <tls::TLSSession> tlsSession =
|
|
||||||
tls::TLSSession::create(getCertificateVerifier());
|
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
|
||||||
tlsSession->getSocket(m_socket);
|
|
||||||
|
|
||||||
tlsSocket->handshake(m_timeoutHandler);
|
|
||||||
|
|
||||||
m_socket = tlsSocket;
|
|
||||||
|
|
||||||
m_secured = true;
|
|
||||||
m_cntInfos = vmime::create <tls::TLSSecuredConnectionInfos>
|
|
||||||
(m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket);
|
|
||||||
}
|
}
|
||||||
catch (exceptions::command_error&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
// Non-fatal error
|
m_connection = NULL;
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (exception&)
|
|
||||||
{
|
|
||||||
// Fatal error
|
|
||||||
internalDisconnect();
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
|
||||||
|
bool POP3Store::isPOP3S() const
|
||||||
|
{
|
||||||
|
return m_isPOP3S;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool POP3Store::isConnected() const
|
bool POP3Store::isConnected() const
|
||||||
{
|
{
|
||||||
return (m_socket && m_socket->isConnected() && m_authentified);
|
return m_connection && m_connection->isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool POP3Store::isSecuredConnection() const
|
bool POP3Store::isSecuredConnection() const
|
||||||
{
|
{
|
||||||
return m_secured;
|
if (m_connection == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_connection->isSecuredConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ref <connectionInfos> POP3Store::getConnectionInfos() const
|
ref <connectionInfos> POP3Store::getConnectionInfos() const
|
||||||
{
|
{
|
||||||
return m_cntInfos;
|
if (m_connection == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_connection->getConnectionInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <POP3Connection> POP3Store::getConnection()
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -596,12 +165,6 @@ void POP3Store::disconnect()
|
|||||||
if (!isConnected())
|
if (!isConnected())
|
||||||
throw exceptions::not_connected();
|
throw exceptions::not_connected();
|
||||||
|
|
||||||
internalDisconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void POP3Store::internalDisconnect()
|
|
||||||
{
|
|
||||||
for (std::list <POP3Folder*>::iterator it = m_folders.begin() ;
|
for (std::list <POP3Folder*>::iterator it = m_folders.begin() ;
|
||||||
it != m_folders.end() ; ++it)
|
it != m_folders.end() ; ++it)
|
||||||
{
|
{
|
||||||
@ -610,74 +173,26 @@ void POP3Store::internalDisconnect()
|
|||||||
|
|
||||||
m_folders.clear();
|
m_folders.clear();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sendRequest(POP3Command::QUIT());
|
|
||||||
readResponse();
|
|
||||||
}
|
|
||||||
catch (exception&)
|
|
||||||
{
|
|
||||||
// Not important
|
|
||||||
}
|
|
||||||
|
|
||||||
m_socket->disconnect();
|
m_connection->disconnect();
|
||||||
m_socket = NULL;
|
m_connection = NULL;
|
||||||
|
|
||||||
m_timeoutHandler = NULL;
|
|
||||||
|
|
||||||
m_authentified = false;
|
|
||||||
|
|
||||||
m_secured = false;
|
|
||||||
m_cntInfos = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void POP3Store::noop()
|
void POP3Store::noop()
|
||||||
{
|
{
|
||||||
sendRequest(POP3Command::NOOP());
|
if (!m_connection)
|
||||||
|
throw exceptions::not_connected();
|
||||||
|
|
||||||
ref <POP3Response> response =
|
POP3Command::NOOP()->send(m_connection);
|
||||||
readResponse();
|
|
||||||
|
ref <POP3Response> response = POP3Response::readResponse(m_connection);
|
||||||
|
|
||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("NOOP", response->getFirstLine());
|
throw exceptions::command_error("NOOP", response->getFirstLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::vector <string> POP3Store::getCapabilities()
|
|
||||||
{
|
|
||||||
sendRequest(POP3Command::CAPA());
|
|
||||||
|
|
||||||
ref <POP3Response> response =
|
|
||||||
POP3Response::readMultilineResponse(m_socket, m_timeoutHandler);
|
|
||||||
|
|
||||||
std::vector <string> res;
|
|
||||||
|
|
||||||
if (response->isSuccess())
|
|
||||||
{
|
|
||||||
for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i)
|
|
||||||
res.push_back(response->getLineAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void POP3Store::sendRequest(ref <POP3Command> cmd)
|
|
||||||
{
|
|
||||||
cmd->writeToSocket(m_socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ref <POP3Response> POP3Store::readResponse()
|
|
||||||
{
|
|
||||||
ref <POP3Response> resp =
|
|
||||||
readResponse();
|
|
||||||
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void POP3Store::registerFolder(POP3Folder* folder)
|
void POP3Store::registerFolder(POP3Folder* folder)
|
||||||
{
|
{
|
||||||
m_folders.push_back(folder);
|
m_folders.push_back(folder);
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "tests/testUtils.hpp"
|
#include "tests/testUtils.hpp"
|
||||||
|
|
||||||
|
#include "tests/net/pop3/POP3TestUtils.hpp"
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Command.hpp"
|
#include "vmime/net/pop3/POP3Command.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -212,7 +214,10 @@ VMIME_TEST_SUITE_BEGIN(POP3CommandTest)
|
|||||||
vmime::ref <POP3Command> cmd = POP3Command::createCommand("MY_COMMAND param1 param2");
|
vmime::ref <POP3Command> cmd = POP3Command::createCommand("MY_COMMAND param1 param2");
|
||||||
|
|
||||||
vmime::ref <testSocket> sok = vmime::create <testSocket>();
|
vmime::ref <testSocket> sok = vmime::create <testSocket>();
|
||||||
cmd->writeToSocket(sok);
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(sok.dynamicCast <vmime::net::socket>(), vmime::null);
|
||||||
|
|
||||||
|
cmd->send(conn);
|
||||||
|
|
||||||
vmime::string response;
|
vmime::string response;
|
||||||
sok->localReceive(response);
|
sok->localReceive(response);
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "tests/testUtils.hpp"
|
#include "tests/testUtils.hpp"
|
||||||
|
|
||||||
|
#include "tests/net/pop3/POP3TestUtils.hpp"
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Response.hpp"
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -48,10 +50,13 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Response Text\r\n");
|
socket->localSend("+OK Response Text\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readResponse(socket, toh);
|
POP3Response::readResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
||||||
VASSERT_TRUE("Success", resp->isSuccess());
|
VASSERT_TRUE("Success", resp->isSuccess());
|
||||||
@ -65,10 +70,13 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("-ERR Response Text\r\n");
|
socket->localSend("-ERR Response Text\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readResponse(socket, toh);
|
POP3Response::readResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode());
|
||||||
VASSERT_FALSE("Success", resp->isSuccess());
|
VASSERT_FALSE("Success", resp->isSuccess());
|
||||||
@ -82,10 +90,13 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+ challenge_string\r\n");
|
socket->localSend("+ challenge_string\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readResponse(socket, toh);
|
POP3Response::readResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_READY, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_READY, resp->getCode());
|
||||||
VASSERT_FALSE("Success", resp->isSuccess());
|
VASSERT_FALSE("Success", resp->isSuccess());
|
||||||
@ -99,10 +110,13 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("Invalid Response Text\r\n");
|
socket->localSend("Invalid Response Text\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readResponse(socket, toh);
|
POP3Response::readResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode());
|
||||||
VASSERT_FALSE("Success", resp->isSuccess());
|
VASSERT_FALSE("Success", resp->isSuccess());
|
||||||
@ -116,10 +130,13 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Response terminated by LF\n");
|
socket->localSend("+OK Response terminated by LF\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readResponse(socket, toh);
|
POP3Response::readResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
||||||
VASSERT_TRUE("Success", resp->isSuccess());
|
VASSERT_TRUE("Success", resp->isSuccess());
|
||||||
@ -133,13 +150,16 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Response Text\r\n");
|
socket->localSend("+OK Response Text\r\n");
|
||||||
socket->localSend("Line 1\r\n");
|
socket->localSend("Line 1\r\n");
|
||||||
socket->localSend("Line 2\r\n");
|
socket->localSend("Line 2\r\n");
|
||||||
socket->localSend(".\r\n");
|
socket->localSend(".\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readMultilineResponse(socket, toh);
|
POP3Response::readMultilineResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
||||||
VASSERT_TRUE("Success", resp->isSuccess());
|
VASSERT_TRUE("Success", resp->isSuccess());
|
||||||
@ -155,13 +175,16 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Response Text\n");
|
socket->localSend("+OK Response Text\n");
|
||||||
socket->localSend("Line 1\n");
|
socket->localSend("Line 1\n");
|
||||||
socket->localSend("Line 2\n");
|
socket->localSend("Line 2\n");
|
||||||
socket->localSend(".\n");
|
socket->localSend(".\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readMultilineResponse(socket, toh);
|
POP3Response::readMultilineResponse(conn);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
||||||
VASSERT_TRUE("Success", resp->isSuccess());
|
VASSERT_TRUE("Success", resp->isSuccess());
|
||||||
@ -182,6 +205,9 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Large Response Follows\n");
|
socket->localSend("+OK Large Response Follows\n");
|
||||||
socket->localSend(data.str());
|
socket->localSend(data.str());
|
||||||
socket->localSend("\r\n.\r\n");
|
socket->localSend("\r\n.\r\n");
|
||||||
@ -190,7 +216,7 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest)
|
|||||||
vmime::utility::outputStreamStringAdapter receivedDataStream(receivedData);
|
vmime::utility::outputStreamStringAdapter receivedDataStream(receivedData);
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readLargeResponse(socket, toh, receivedDataStream, NULL, 0);
|
POP3Response::readLargeResponse(conn, receivedDataStream, NULL, 0);
|
||||||
|
|
||||||
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode());
|
||||||
VASSERT_TRUE("Success", resp->isSuccess());
|
VASSERT_TRUE("Success", resp->isSuccess());
|
||||||
|
53
tests/net/pop3/POP3TestUtils.hpp
Normal file
53
tests/net/pop3/POP3TestUtils.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 3 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "vmime/net/pop3/POP3Connection.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Store.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class POP3ConnectionTest : public vmime::net::pop3::POP3Connection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
POP3ConnectionTest(vmime::ref <vmime::net::socket> socket,
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> timeoutHandler)
|
||||||
|
: POP3Connection(NULL, NULL),
|
||||||
|
m_socket(socket), m_timeoutHandler(timeoutHandler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::socket> getSocket()
|
||||||
|
{
|
||||||
|
return m_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> getTimeoutHandler()
|
||||||
|
{
|
||||||
|
return m_timeoutHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::socket> m_socket;
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> m_timeoutHandler;
|
||||||
|
};
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "tests/testUtils.hpp"
|
#include "tests/testUtils.hpp"
|
||||||
|
|
||||||
|
#include "tests/net/pop3/POP3TestUtils.hpp"
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Utils.hpp"
|
#include "vmime/net/pop3/POP3Utils.hpp"
|
||||||
#include "vmime/net/pop3/POP3Response.hpp"
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
|
||||||
@ -42,6 +44,9 @@ VMIME_TEST_SUITE_BEGIN(POP3UtilsTest)
|
|||||||
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
vmime::ref <vmime::net::timeoutHandler> toh = vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
vmime::ref <POP3ConnectionTest> conn = vmime::create <POP3ConnectionTest>
|
||||||
|
(socket.dynamicCast <vmime::net::socket>(), toh);
|
||||||
|
|
||||||
socket->localSend("+OK Response Text\r\n");
|
socket->localSend("+OK Response Text\r\n");
|
||||||
socket->localSend("1 abcdef\r\n");
|
socket->localSend("1 abcdef\r\n");
|
||||||
socket->localSend("23 ghijkl\r\n");
|
socket->localSend("23 ghijkl\r\n");
|
||||||
@ -51,7 +56,7 @@ VMIME_TEST_SUITE_BEGIN(POP3UtilsTest)
|
|||||||
socket->localSend(".\r\n");
|
socket->localSend(".\r\n");
|
||||||
|
|
||||||
vmime::ref <POP3Response> resp =
|
vmime::ref <POP3Response> resp =
|
||||||
POP3Response::readMultilineResponse(socket, toh);
|
POP3Response::readMultilineResponse(conn);
|
||||||
|
|
||||||
std::map <int, vmime::string> result;
|
std::map <int, vmime::string> result;
|
||||||
POP3Utils::parseMultiListOrUidlResponse(resp, result);
|
POP3Utils::parseMultiListOrUidlResponse(resp, result);
|
||||||
|
@ -42,15 +42,12 @@ class mailbox;
|
|||||||
|
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
|
|
||||||
class socket;
|
|
||||||
class timeoutHandler;
|
|
||||||
|
|
||||||
|
|
||||||
namespace pop3 {
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
class POP3Connection;
|
||||||
|
|
||||||
|
|
||||||
/** A POP3 command that will be sent to the server.
|
/** A POP3 command that will be sent to the server.
|
||||||
*/
|
*/
|
||||||
class VMIME_EXPORT POP3Command : public object
|
class VMIME_EXPORT POP3Command : public object
|
||||||
@ -84,11 +81,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
static ref <POP3Command> createCommand(const string& text);
|
static ref <POP3Command> createCommand(const string& text);
|
||||||
|
|
||||||
/** Sends this command to the specified socket.
|
/** Sends this command over the specified connection.
|
||||||
*
|
*
|
||||||
* @param sok socket to which the command will be written
|
* @param conn connection onto which the command will be sent
|
||||||
*/
|
*/
|
||||||
virtual void writeToSocket(ref <socket> sok);
|
virtual void send(ref <POP3Connection> conn);
|
||||||
|
|
||||||
/** Returns the full text of the command, including command name
|
/** Returns the full text of the command, including command name
|
||||||
* and parameters (if any).
|
* and parameters (if any).
|
||||||
|
122
vmime/net/pop3/POP3Connection.hpp
Normal file
122
vmime/net/pop3/POP3Connection.hpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 3 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/messageId.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/socket.hpp"
|
||||||
|
#include "vmime/net/timeoutHandler.hpp"
|
||||||
|
#include "vmime/net/session.hpp"
|
||||||
|
#include "vmime/net/connectionInfos.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/pop3/POP3Command.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
|
||||||
|
#include "vmime/security/authenticator.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
|
||||||
|
|
||||||
|
class socket;
|
||||||
|
class timeoutHandler;
|
||||||
|
|
||||||
|
|
||||||
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
class POP3Store;
|
||||||
|
|
||||||
|
|
||||||
|
/** Manage connection to a POP3 server.
|
||||||
|
*/
|
||||||
|
class VMIME_EXPORT POP3Connection : public object
|
||||||
|
{
|
||||||
|
friend class vmime::creator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
POP3Connection(ref <POP3Store> store, ref <security::authenticator> auth);
|
||||||
|
virtual ~POP3Connection();
|
||||||
|
|
||||||
|
|
||||||
|
virtual void connect();
|
||||||
|
virtual bool isConnected() const;
|
||||||
|
virtual void disconnect();
|
||||||
|
|
||||||
|
bool isSecuredConnection() const;
|
||||||
|
ref <connectionInfos> getConnectionInfos() const;
|
||||||
|
|
||||||
|
virtual ref <POP3Store> getStore();
|
||||||
|
virtual ref <socket> getSocket();
|
||||||
|
virtual ref <timeoutHandler> getTimeoutHandler();
|
||||||
|
virtual ref <security::authenticator> getAuthenticator();
|
||||||
|
virtual ref <session> getSession();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void authenticate(const messageId& randomMID);
|
||||||
|
#if VMIME_HAVE_SASL_SUPPORT
|
||||||
|
void authenticateSASL();
|
||||||
|
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||||
|
|
||||||
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
|
void startTLS();
|
||||||
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
const std::vector <string> getCapabilities();
|
||||||
|
|
||||||
|
void internalDisconnect();
|
||||||
|
|
||||||
|
|
||||||
|
weak_ref <POP3Store> m_store;
|
||||||
|
|
||||||
|
ref <security::authenticator> m_auth;
|
||||||
|
ref <socket> m_socket;
|
||||||
|
ref <timeoutHandler> m_timeoutHandler;
|
||||||
|
|
||||||
|
bool m_authenticated;
|
||||||
|
bool m_secured;
|
||||||
|
|
||||||
|
ref <connectionInfos> m_cntInfos;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // pop3
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
#endif // VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED
|
@ -50,6 +50,9 @@ class timeoutHandler;
|
|||||||
namespace pop3 {
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
class POP3Connection;
|
||||||
|
|
||||||
|
|
||||||
/** A POP3 response, as sent by the server.
|
/** A POP3 response, as sent by the server.
|
||||||
*/
|
*/
|
||||||
class VMIME_EXPORT POP3Response : public object
|
class VMIME_EXPORT POP3Response : public object
|
||||||
@ -68,34 +71,29 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/** Receive and parse a POP3 response from the
|
/** Receive and parse a POP3 response from the
|
||||||
* specified socket.
|
* specified connection.
|
||||||
*
|
*
|
||||||
* @param sok socket from which to read
|
* @param conn connection from which to read
|
||||||
* @param toh time-out handler (can be NULL)
|
|
||||||
* @return POP3 response
|
* @return POP3 response
|
||||||
* @throws exceptions::operation_timed_out if no data
|
* @throws exceptions::operation_timed_out if no data
|
||||||
* has been received within the granted time
|
* has been received within the granted time
|
||||||
*/
|
*/
|
||||||
static ref <POP3Response> readResponse
|
static ref <POP3Response> readResponse(ref <POP3Connection> conn);
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh);
|
|
||||||
|
|
||||||
/** Receive and parse a multiline POP3 response from
|
/** Receive and parse a multiline POP3 response from
|
||||||
* the specified socket.
|
* the specified connection.
|
||||||
*
|
*
|
||||||
* @param sok socket from which to read
|
* @param conn connection from which to read
|
||||||
* @param toh time-out handler (can be NULL)
|
|
||||||
* @return POP3 response
|
* @return POP3 response
|
||||||
* @throws exceptions::operation_timed_out if no data
|
* @throws exceptions::operation_timed_out if no data
|
||||||
* has been received within the granted time
|
* has been received within the granted time
|
||||||
*/
|
*/
|
||||||
static ref <POP3Response> readMultilineResponse
|
static ref <POP3Response> readMultilineResponse(ref <POP3Connection> conn);
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh);
|
|
||||||
|
|
||||||
/** Receive and parse a large POP3 response (eg. message data)
|
/** Receive and parse a large POP3 response (eg. message data)
|
||||||
* from the specified socket.
|
* from the specified connection.
|
||||||
*
|
*
|
||||||
* @param sok socket from which to read
|
* @param conn connection from which to read
|
||||||
* @param toh time-out handler (can be NULL)
|
|
||||||
* @param os output stream to which response data will be written
|
* @param os output stream to which response data will be written
|
||||||
* @param progress progress listener (can be NULL)
|
* @param progress progress listener (can be NULL)
|
||||||
* @param predictedSize estimated size of response data (in bytes)
|
* @param predictedSize estimated size of response data (in bytes)
|
||||||
@ -104,8 +102,7 @@ public:
|
|||||||
* has been received within the granted time
|
* has been received within the granted time
|
||||||
*/
|
*/
|
||||||
static ref <POP3Response> readLargeResponse
|
static ref <POP3Response> readLargeResponse
|
||||||
(ref <socket> sok, ref <timeoutHandler> toh,
|
(ref <POP3Connection> conn, utility::outputStream& os,
|
||||||
utility::outputStream& os,
|
|
||||||
utility::progressListener* progress, const long predictedSize);
|
utility::progressListener* progress, const long predictedSize);
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,13 +31,10 @@
|
|||||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
|
||||||
#include "vmime/messageId.hpp"
|
|
||||||
|
|
||||||
#include "vmime/net/store.hpp"
|
#include "vmime/net/store.hpp"
|
||||||
#include "vmime/net/socket.hpp"
|
|
||||||
#include "vmime/net/timeoutHandler.hpp"
|
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3ServiceInfos.hpp"
|
#include "vmime/net/pop3/POP3ServiceInfos.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3Connection.hpp"
|
||||||
|
|
||||||
#include "vmime/utility/stream.hpp"
|
#include "vmime/utility/stream.hpp"
|
||||||
|
|
||||||
@ -86,24 +83,13 @@ public:
|
|||||||
|
|
||||||
bool isSecuredConnection() const;
|
bool isSecuredConnection() const;
|
||||||
ref <connectionInfos> getConnectionInfos() const;
|
ref <connectionInfos> getConnectionInfos() const;
|
||||||
|
ref <POP3Connection> getConnection();
|
||||||
|
|
||||||
|
bool isPOP3S() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void authenticate(const messageId& randomMID);
|
ref <POP3Connection> m_connection;
|
||||||
#if VMIME_HAVE_SASL_SUPPORT
|
|
||||||
void authenticateSASL();
|
|
||||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
|
||||||
void startTLS();
|
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
|
||||||
|
|
||||||
const std::vector <string> getCapabilities();
|
|
||||||
|
|
||||||
void sendRequest(ref <POP3Command> cmd);
|
|
||||||
ref <POP3Response> readResponse();
|
|
||||||
|
|
||||||
void internalDisconnect();
|
|
||||||
|
|
||||||
|
|
||||||
void registerFolder(POP3Folder* folder);
|
void registerFolder(POP3Folder* folder);
|
||||||
@ -112,16 +98,8 @@ private:
|
|||||||
std::list <POP3Folder*> m_folders;
|
std::list <POP3Folder*> m_folders;
|
||||||
|
|
||||||
|
|
||||||
ref <socket> m_socket;
|
|
||||||
bool m_authentified;
|
|
||||||
|
|
||||||
ref <timeoutHandler> m_timeoutHandler;
|
|
||||||
|
|
||||||
const bool m_isPOP3S;
|
const bool m_isPOP3S;
|
||||||
|
|
||||||
bool m_secured;
|
|
||||||
ref <connectionInfos> m_cntInfos;
|
|
||||||
|
|
||||||
|
|
||||||
// Service infos
|
// Service infos
|
||||||
static POP3ServiceInfos sm_infos;
|
static POP3ServiceInfos sm_infos;
|
||||||
|
Loading…
Reference in New Issue
Block a user