345 lines
12 KiB
C++
345 lines
12 KiB
C++
#include <smtp/smtp.hpp>
|
|
#include <socket/hostent.hpp>
|
|
#include <socket/servent.hpp>
|
|
|
|
SMTPClient::SMTPClient(void)
|
|
: mSpace(" ")
|
|
{
|
|
createCmds();
|
|
}
|
|
|
|
SMTPClient::~SMTPClient()
|
|
{
|
|
mSMTPControl.destroy();
|
|
}
|
|
|
|
BOOL SMTPClient::open(const String &hostName)
|
|
{
|
|
HostEnt hostEntry;
|
|
ServEnt serverEntry;
|
|
Block<String> responseLines;
|
|
INETSocketAddress internetSocketAddress;
|
|
|
|
if(hostName.isNull())return FALSE;
|
|
if(mSMTPControl.isConnected())mSMTPControl.destroy();
|
|
message(String("trying ")+hostName+String("..."));
|
|
if(!mWSASystem.isInitialized()){message("WINSOCK initialization failure.");return FALSE;}
|
|
InternetAddress internetAddress(hostName);
|
|
if(!internetAddress.isZero()){if(!hostEntry.hostByAddress(internetAddress)){message(String("no DNS entry for ")+hostName+String("."));return FALSE;}}
|
|
else if(!hostEntry.hostByName(hostName)){message(String("no DNS entry for ")+hostName+String("."));return FALSE;}
|
|
if(!internetAddress.isZero()){if(!hostEntry.hostByAddress(internetAddress)){message(String("no DNS entry for ")+hostName);return FALSE;}}
|
|
else if(!hostEntry.hostByName(hostName)){message(String("no DNS entry for ")+hostName);return FALSE;}
|
|
message(String("connect...")+String("'")+hostEntry.hostName()+String("' (")+(String)(hostEntry.addresses())[0]+String(")"));
|
|
internetSocketAddress.internetAddress((hostEntry.addresses())[0]);
|
|
if(serverEntry.serviceByName("smtp","tcp"))
|
|
{
|
|
if(!mSMTPControl.create()){message("unable to create socket.");return FALSE;}
|
|
internetSocketAddress.family(PF_INET);
|
|
internetSocketAddress.port(serverEntry.port());
|
|
}
|
|
else
|
|
{
|
|
if(!mSMTPControl.create()){message("unable to create socket.");return FALSE;}
|
|
internetSocketAddress.family(PF_INET);
|
|
internetSocketAddress.port(htons(SMTPPort));
|
|
}
|
|
if(!mSMTPControl.connect(internetSocketAddress)){message("unable to connect to smtp server");return FALSE;}
|
|
mSMTPControl.getSocketName(internetSocketAddress);
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
if(!mSMTPControl.receive(responseLines)||!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckConnect))
|
|
{
|
|
mSMTPControl.destroy();
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::helo(const String &domainName)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||domainName.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Helo];
|
|
controlData+=mSpace;
|
|
controlData+=domainName;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckHelo))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::quit(void)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
controlData=mSMTPCmds[Quit];
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckQuit))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::mail(const String &reversePath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||reversePath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Mail];
|
|
controlData+=mSpace;
|
|
controlData+=mSMTPCmds[From];
|
|
controlData+=reversePath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckMail))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::rcpt(const String &forwardPath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||forwardPath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Recipient];
|
|
controlData+=mSpace;
|
|
controlData+=mSMTPCmds[To];
|
|
controlData+=forwardPath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckRecipient))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::data(const Block<String> &mailData)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||!mailData.size())return FALSE;
|
|
controlData=mSMTPCmds[Data];
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckData))return FALSE;
|
|
for(int lineIndex=0;lineIndex<mailData.size();lineIndex++)mSMTPControl.send(((Block<String>&)mailData)[lineIndex]);
|
|
mSMTPControl.send(".");
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckData))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::verify(const String &forwardPath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||forwardPath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Verify];
|
|
controlData+=mSpace;
|
|
controlData+=forwardPath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckVerify))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::expand(const String &mailList)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||mailList.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Expand];
|
|
controlData+=mSpace;
|
|
controlData+=mailList;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckExpand))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::send(const String &reversePath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||reversePath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[Send];
|
|
controlData+=mSpace;
|
|
controlData+=mSMTPCmds[From];
|
|
controlData+=reversePath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckSend))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::sendOrMail(const String &reversePath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||reversePath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[SendOrMail];
|
|
controlData+=mSpace;
|
|
controlData+=mSMTPCmds[From];
|
|
controlData+=reversePath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckSendOrMail))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::sendAndMail(const String &reversePath)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected()||reversePath.isNull())return FALSE;
|
|
controlData=mSMTPCmds[SendAndMail];
|
|
controlData+=mSpace;
|
|
controlData+=mSMTPCmds[From];
|
|
controlData+=reversePath;
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckSendAndMail))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::reset(void)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
controlData=mSMTPCmds[Reset];
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckReset))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::help(const String &commandName)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
controlData=mSMTPCmds[Help];
|
|
if(!commandName.isNull())
|
|
{
|
|
controlData+=mSpace;
|
|
controlData+=commandName;
|
|
}
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckHelp))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::noop(void)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
controlData=mSMTPCmds[Noop];
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckNoop))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMTPClient::turn(void)
|
|
{
|
|
String controlData;
|
|
Block<String> responseLines;
|
|
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
controlData=mSMTPCmds[Turn];
|
|
if(!putControlData(controlData,FALSE))return FALSE;
|
|
if(!mSMTPControl.receive(responseLines))return FALSE;
|
|
message(responseLines);
|
|
if(!responseLines.size()||!isInResponse(responseLines.size()>1?responseLines[0].betweenString(0,'-'):responseLines[0].betweenString(0,' '),SMTPResponse::AckTurn))return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
void SMTPClient::createCmds(void)
|
|
{
|
|
mSMTPCmds.remove();
|
|
mSMTPCmds.insert(&String("HELO"));
|
|
mSMTPCmds.insert(&String("QUIT"));
|
|
mSMTPCmds.insert(&String("MAIL"));
|
|
mSMTPCmds.insert(&String("FROM:"));
|
|
mSMTPCmds.insert(&String("RCPT"));
|
|
mSMTPCmds.insert(&String("TO:"));
|
|
mSMTPCmds.insert(&String("DATA"));
|
|
mSMTPCmds.insert(&String("VRFY"));
|
|
mSMTPCmds.insert(&String("EXPN"));
|
|
mSMTPCmds.insert(&String("SEND"));
|
|
mSMTPCmds.insert(&String("SOML"));
|
|
mSMTPCmds.insert(&String("SAML"));
|
|
mSMTPCmds.insert(&String("TURN"));
|
|
mSMTPCmds.insert(&String("RSET"));
|
|
mSMTPCmds.insert(&String("HELP"));
|
|
mSMTPCmds.insert(&String("NOOP"));
|
|
}
|
|
|
|
WORD SMTPClient::putControlData(const String &stringData,WORD waitForResponse)
|
|
{
|
|
if(!mSMTPControl.isConnected())return FALSE;
|
|
if(!mSMTPControl.send(stringData))
|
|
{
|
|
mSMTPControl.destroy();
|
|
String errorString(String("error sending '")+stringData+String("' to SMTP server."));
|
|
message(errorString);
|
|
errorString+="\n";
|
|
::OutputDebugString(errorString);
|
|
return FALSE;
|
|
}
|
|
if(waitForResponse&&!getControlData())
|
|
{
|
|
mSMTPControl.destroy();
|
|
String errorString(String("error reading result of '")+stringData+String("' command from NNTP server."));
|
|
message(errorString);
|
|
errorString+="\n";
|
|
::OutputDebugString(errorString);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
WORD SMTPClient::getControlData(void)
|
|
{
|
|
Block<String> responseStrings;
|
|
mSMTPControl.receive(responseStrings);
|
|
return responseStrings.size();
|
|
}
|
|
|
|
// virtuals
|
|
|
|
void SMTPClient::message(const String &messageString)
|
|
{
|
|
}
|
|
|
|
void SMTPClient::message(Block<String> &messageStrings)
|
|
{
|
|
}
|