#include #include #include SMTPClient::SMTPClient(void) : mSpace(" ") { createCmds(); } SMTPClient::~SMTPClient() { mSMTPControl.destroy(); } BOOL SMTPClient::open(const String &hostName) { HostEnt hostEntry; ServEnt serverEntry; Block 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 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 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 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 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 &mailData) { String controlData; Block 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)[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 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 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 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 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 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 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 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 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 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 responseStrings; mSMTPControl.receive(responseStrings); return responseStrings.size(); } // virtuals void SMTPClient::message(const String &messageString) { } void SMTPClient::message(Block &messageStrings) { }