37 const std::string & peer_socket_name ,
Config config ) :
39 m_verifier(verifier) ,
40 m_pmessage(pmessage) ,
42 m_peer_address(peer_address) ,
43 m_peer_socket_name(peer_socket_name) ,
44 m_fsm(sStart,sEnd,s_Same,s_Any) ,
45 m_authenticated(false) ,
47 m_sasl(
GAuth::SaslServerFactory::newSaslServer(secrets,false,true)) ,
48 m_with_vrfy(config.with_vrfy) ,
49 m_preprocessor_timeout(config.preprocessor_timeout) ,
50 m_bad_client_count(0U) ,
51 m_bad_client_limit(8U) ,
52 m_disconnect_on_overflow(config.disconnect_on_overflow)
59 m_fsm.
addTransition( eQuit , s_Any , sEnd , &GSmtp::ServerProtocol::doQuit ) ;
60 m_fsm.
addTransition( eUnknown , s_Any , s_Same , &GSmtp::ServerProtocol::doUnknown ) ;
61 m_fsm.
addTransition( eRset , sStart , s_Same , &GSmtp::ServerProtocol::doNoop ) ;
62 m_fsm.
addTransition( eRset , s_Any , sIdle , &GSmtp::ServerProtocol::doRset ) ;
63 m_fsm.
addTransition( eNoop , s_Any , s_Same , &GSmtp::ServerProtocol::doNoop ) ;
64 m_fsm.
addTransition( eHelp , s_Any , s_Same , &GSmtp::ServerProtocol::doHelp ) ;
65 m_fsm.
addTransition( eExpn , s_Any , s_Same , &GSmtp::ServerProtocol::doExpn ) ;
66 m_fsm.
addTransition( eVrfy , sStart , sVrfyStart , &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
67 m_fsm.
addTransition( eVrfyReply , sVrfyStart , sStart , &GSmtp::ServerProtocol::doVrfyReply ) ;
68 m_fsm.
addTransition( eVrfy , sIdle , sVrfyIdle , &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
69 m_fsm.
addTransition( eVrfyReply , sVrfyIdle , sIdle , &GSmtp::ServerProtocol::doVrfyReply ) ;
70 m_fsm.
addTransition( eVrfy , sGotMail , sVrfyGotMail, &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
71 m_fsm.
addTransition( eVrfyReply , sVrfyGotMail, sGotMail , &GSmtp::ServerProtocol::doVrfyReply ) ;
72 m_fsm.
addTransition( eVrfy , sGotRcpt , sVrfyGotRcpt, &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
73 m_fsm.
addTransition( eVrfyReply , sVrfyGotRcpt, sGotRcpt , &GSmtp::ServerProtocol::doVrfyReply ) ;
74 m_fsm.
addTransition( eEhlo , s_Any , sIdle , &GSmtp::ServerProtocol::doEhlo , s_Same ) ;
75 m_fsm.
addTransition( eHelo , s_Any , sIdle , &GSmtp::ServerProtocol::doHelo , s_Same ) ;
76 m_fsm.
addTransition( eMail , sIdle , sGotMail , &GSmtp::ServerProtocol::doMail , sIdle ) ;
77 m_fsm.
addTransition( eRcpt , sGotMail , sVrfyTo1 , &GSmtp::ServerProtocol::doRcpt , s_Same ) ;
78 m_fsm.
addTransition( eVrfyReply , sVrfyTo1 , sGotRcpt , &GSmtp::ServerProtocol::doVrfyToReply , sGotMail ) ;
79 m_fsm.
addTransition( eRcpt , sGotRcpt , sVrfyTo2 , &GSmtp::ServerProtocol::doRcpt , s_Same ) ;
80 m_fsm.
addTransition( eVrfyReply , sVrfyTo2 , sGotRcpt , &GSmtp::ServerProtocol::doVrfyToReply ) ;
81 m_fsm.
addTransition( eData , sGotMail , sIdle , &GSmtp::ServerProtocol::doNoRecipients ) ;
82 m_fsm.
addTransition( eData , sGotRcpt , sData , &GSmtp::ServerProtocol::doData ) ;
83 m_fsm.
addTransition( eContent , sData , sData , &GSmtp::ServerProtocol::doContent , sDiscarding ) ;
84 m_fsm.
addTransition( eEot , sData , sProcessing , &GSmtp::ServerProtocol::doEot ) ;
85 m_fsm.
addTransition( eDone , sProcessing , sIdle , &GSmtp::ServerProtocol::doComplete ) ;
86 m_fsm.
addTransition( eTimeout , sProcessing , sIdle , &GSmtp::ServerProtocol::doComplete ) ;
87 m_fsm.
addTransition( eContent , sDiscarding , sDiscarding , &GSmtp::ServerProtocol::doDiscard ) ;
88 m_fsm.
addTransition( eEot , sDiscarding , sIdle , &GSmtp::ServerProtocol::doDiscarded ) ;
91 if( m_sasl->active() )
93 m_fsm.
addTransition( eAuth , sIdle , sAuth , &GSmtp::ServerProtocol::doAuth , sIdle ) ;
94 m_fsm.
addTransition( eAuthData, sAuth , sAuth , &GSmtp::ServerProtocol::doAuthData , sIdle ) ;
99 m_with_ssl = ssl != NULL && ssl->
enabled(
true) ;
102 m_fsm.
addTransition( eStartTls , sIdle , sStartingTls , &GSmtp::ServerProtocol::doStartTls , sIdle ) ;
103 m_fsm.
addTransition( eSecure , sStartingTls , sIdle , &GSmtp::ServerProtocol::doSecure ) ;
109 sendGreeting( m_text.greeting() ) ;
114 m_pmessage.doneSignal().disconnect() ;
115 m_verifier.doneSignal().disconnect() ;
120 State new_state = m_fsm.apply( *
this , eSecure , certificate ) ;
121 if( new_state == s_Any )
122 throw ProtocolDone(
"protocol error" ) ;
125 void GSmtp::ServerProtocol::doSecure(
const std::string & certificate ,
bool & )
127 G_DEBUG(
"GSmtp::ServerProtocol::doSecure" ) ;
129 m_certificate = certificate ;
132 void GSmtp::ServerProtocol::doStartTls(
const std::string & ,
bool & ok )
136 send(
"503 command out of sequence" ) ;
141 send(
"220 ready to start tls" ,
true ) ;
145 void GSmtp::ServerProtocol::sendGreeting(
const std::string & text )
147 send( std::string(
"220 ") + text ) ;
152 Event
event = eUnknown ;
153 State state = m_fsm.state() ;
154 const std::string * event_data = &line ;
155 if( (state == sData || state == sDiscarding) && isEndOfText(line) )
159 else if( state == sData || state == sDiscarding )
163 else if( state == sAuth )
170 event = commandEvent( commandWord(line) ) ;
171 m_buffer = commandLine(line) ;
172 event_data = &m_buffer ;
175 State new_state = m_fsm.apply( *
this , event , *event_data ) ;
176 if( new_state == s_Any )
177 sendOutOfSequence( line ) ;
180 void GSmtp::ServerProtocol::doContent(
const std::string & line ,
bool & ok )
182 if( isEscaped(line) )
183 ok = m_pmessage.addText( line.substr(1U) ) ;
185 ok = m_pmessage.addText( line ) ;
187 if( !ok && m_disconnect_on_overflow )
191 void GSmtp::ServerProtocol::doEot(
const std::string & line ,
bool & )
193 G_LOG(
"GSmtp::ServerProtocol: rx<<: [message content not logged]" ) ;
195 if( m_preprocessor_timeout != 0U )
197 G_DEBUG(
"GSmtp::ServerProtocol: starting preprocessor timer: " << m_preprocessor_timeout ) ;
198 startTimer( m_preprocessor_timeout ) ;
200 m_pmessage.process( m_sasl->id() , m_peer_address.displayString(
false) , m_peer_socket_name , m_certificate ) ;
203 void GSmtp::ServerProtocol::processDone(
bool success ,
unsigned long , std::string reason )
205 G_DEBUG(
"GSmtp::ServerProtocol::processDone: " << success <<
", \"" << reason <<
"\"" ) ;
207 reason = success ? std::string() : ( reason.empty() ? std::string(
"error") : reason ) ;
209 State new_state = m_fsm.apply( *
this , eDone , reason ) ;
210 if( new_state == s_Any )
211 throw ProtocolDone(
"protocol error" ) ;
216 G_WARNING(
"GSmtp::ServerProtocol::onTimeout: message processing timed out" ) ;
217 State new_state = m_fsm.apply( *
this , eTimeout ,
"message processing timed out" ) ;
218 if( new_state == s_Any )
219 throw ProtocolDone(
"protocol error" ) ;
224 G_IGNORE_PARAMETER(std::exception,e) ;
225 G_DEBUG(
"GSmtp::ServerProtocol::onTimeoutException: exception: " << e.what() ) ;
229 void GSmtp::ServerProtocol::doComplete(
const std::string & reason ,
bool & )
232 sendCompletionReply( reason.empty() , reason ) ;
235 void GSmtp::ServerProtocol::doQuit(
const std::string & ,
bool & )
239 throw ProtocolDone() ;
242 void GSmtp::ServerProtocol::doDiscard(
const std::string & ,
bool & )
244 if( m_disconnect_on_overflow )
248 throw ProtocolDone() ;
252 void GSmtp::ServerProtocol::doNoop(
const std::string & ,
bool & )
257 void GSmtp::ServerProtocol::doNothing(
const std::string & ,
bool & )
261 void GSmtp::ServerProtocol::doDiscarded(
const std::string & ,
bool & )
267 void GSmtp::ServerProtocol::doExpn(
const std::string & ,
bool & )
269 sendNotImplemented() ;
272 void GSmtp::ServerProtocol::doHelp(
const std::string & ,
bool & )
274 sendNotImplemented() ;
277 void GSmtp::ServerProtocol::doVrfy(
const std::string & line ,
bool & predicate )
281 std::string to = parseToParameter( line ) ;
285 sendNotVerified( to ,
false ) ;
295 sendNotImplemented() ;
299 void GSmtp::ServerProtocol::verify(
const std::string & to ,
const std::string & from )
301 std::string mechanism = m_sasl->active() ? m_sasl->mechanism() : std::string() ;
302 std::string
id = m_sasl->active() ? m_sasl->id() : std::string() ;
303 if( m_sasl->active() && !m_authenticated )
305 m_verifier.verify( to , from , m_peer_address , mechanism ,
id ) ;
308 void GSmtp::ServerProtocol::verifyDone( std::string mbox , VerifierStatus status )
310 State new_state = m_fsm.apply( *
this , eVrfyReply , status.str(mbox) ) ;
311 if( new_state == s_Any )
312 throw ProtocolDone(
"protocol error" ) ;
315 void GSmtp::ServerProtocol::doVrfyReply(
const std::string & line ,
bool & )
320 if( rc.is_valid && rc.is_local )
321 sendVerified( rc.full_name ) ;
322 else if( rc.is_valid )
323 sendWillAccept( mbox ) ;
325 sendNotVerified( mbox , rc.temporary ) ;
328 std::string GSmtp::ServerProtocol::parseToParameter(
const std::string & line )
const
331 size_t pos = line.find_first_of(
" \t" ) ;
332 if( pos != std::string::npos )
333 to = line.substr(pos) ;
339 void GSmtp::ServerProtocol::doEhlo(
const std::string & line ,
bool & predicate )
341 std::string smtp_peer_name = parsePeerName( line ) ;
342 if( smtp_peer_name.empty() )
345 sendMissingParameter() ;
349 m_smtp_peer_name = smtp_peer_name ;
355 void GSmtp::ServerProtocol::doHelo(
const std::string & line ,
bool & predicate )
357 std::string smtp_peer_name = parsePeerName( line ) ;
358 if( smtp_peer_name.empty() )
361 sendMissingParameter() ;
365 m_smtp_peer_name = smtp_peer_name ;
371 bool GSmtp::ServerProtocol::sensitive()
const
374 return m_sasl->active() && m_sasl->requiresEncryption() && !m_secure ;
378 void GSmtp::ServerProtocol::doAuth(
const std::string & line ,
bool & predicate )
383 std::string mechanism = word_array.size() > 1U ? word_array[1U] : std::string() ;
385 std::string initial_response = word_array.size() > 2U ? word_array[2U] : std::string() ;
386 bool got_initial_response = word_array.size() > 2U ;
388 G_DEBUG(
"ServerProtocol::doAuth: [" << mechanism <<
"], [" << initial_response <<
"]" ) ;
392 G_WARNING(
"GSmtp::ServerProtocol: rejecting authentication attempt without encryption" ) ;
394 send(
"504 Unsupported authentication mechanism" ) ;
396 else if( m_authenticated )
398 G_WARNING(
"GSmtp::ServerProtocol: too many AUTHs" ) ;
400 sendOutOfSequence(line) ;
402 else if( ! m_sasl->init(mechanism) )
404 G_WARNING(
"GSmtp::ServerProtocol: request for unsupported AUTH mechanism: " << mechanism ) ;
406 send(
"504 Unsupported authentication mechanism" ) ;
410 G_WARNING(
"GSmtp::ServerProtocol: invalid base64 encoding of AUTH parameter" ) ;
412 send(
"501 Invalid argument" ) ;
414 else if( got_initial_response )
416 std::string s = initial_response ==
"=" ? std::string() :
G::Base64::decode(initial_response) ;
418 std::string next_challenge = m_sasl->apply( s , done ) ;
422 m_authenticated = m_sasl->authenticated() ;
423 sendAuthDone( m_sasl->authenticated() ) ;
427 sendChallenge( next_challenge ) ;
432 sendChallenge( m_sasl->initialChallenge() ) ;
437 void GSmtp::ServerProtocol::sendAuthDone(
bool ok )
440 send(
"235 Authentication sucessful" ) ;
442 send(
"535 Authentication failed" ) ;
446 void GSmtp::ServerProtocol::doAuthData(
const std::string & line ,
bool & predicate )
448 G_LOG(
"GSmtp::ServerProtocol: rx<<: [authentication response not logged]" ) ;
452 send(
"501 authentication cancelled" ) ;
456 G_WARNING(
"GSmtp::ServerProtocol: invalid base64 encoding of authentication response" ) ;
458 sendAuthDone(
false ) ;
467 m_authenticated = m_sasl->authenticated() ;
468 sendAuthDone( m_sasl->authenticated() ) ;
472 sendChallenge( next_challenge ) ;
478 void GSmtp::ServerProtocol::sendChallenge(
const std::string & s )
483 void GSmtp::ServerProtocol::doMail(
const std::string & line ,
bool & predicate )
485 if( m_sasl->active() && !m_authenticated && ( !m_sasl->trusted(m_peer_address) || sensitive() ) )
493 std::pair<std::string,std::string> from_pair = parseFrom( line ) ;
494 bool ok = from_pair.second.empty() && m_pmessage.setFrom( from_pair.first ) ;
502 sendBadFrom( from_pair.second ) ;
507 void GSmtp::ServerProtocol::doRcpt(
const std::string & line ,
bool & predicate )
509 std::pair<std::string,std::string> to_pair = parseTo( line ) ;
510 std::string reason = to_pair.second ;
511 bool ok = reason.empty() ;
515 verify( to_pair.first , m_pmessage.from() ) ;
520 sendBadTo( reason ,
false ) ;
524 void GSmtp::ServerProtocol::doVrfyToReply(
const std::string & line ,
bool & predicate )
529 bool ok = m_pmessage.addTo( to , status ) ;
541 void GSmtp::ServerProtocol::doUnknown(
const std::string & line ,
bool & )
543 sendUnrecognised( line ) ;
546 void GSmtp::ServerProtocol::reset()
551 m_bad_client_count = 0U ;
554 void GSmtp::ServerProtocol::doRset(
const std::string & ,
bool & )
561 void GSmtp::ServerProtocol::doNoRecipients(
const std::string & ,
bool & )
566 void GSmtp::ServerProtocol::doData(
const std::string & ,
bool & )
568 std::string received_line = m_text.received(m_smtp_peer_name) ;
569 if( received_line.length() )
570 m_pmessage.addReceived( received_line ) ;
575 void GSmtp::ServerProtocol::sendOutOfSequence(
const std::string & )
577 send(
"503 command out of sequence -- use RSET to resynchronise" ) ;
581 void GSmtp::ServerProtocol::sendMissingParameter()
583 send(
"501 parameter required" ) ;
586 bool GSmtp::ServerProtocol::isEndOfText(
const std::string & line )
const
588 return line.length() == 1U && line[0U] ==
'.' ;
591 bool GSmtp::ServerProtocol::isEscaped(
const std::string & line )
const
593 return line.length() > 1U && line[0U] ==
'.' ;
596 std::string GSmtp::ServerProtocol::commandWord(
const std::string & line_in )
const
598 std::string line( line_in ) ;
601 size_t pos = line.find_first_of(
" \t" ) ;
602 std::string command = line.substr( 0U , pos ) ;
608 std::string GSmtp::ServerProtocol::commandLine(
const std::string & line_in )
const
610 std::string line( line_in ) ;
615 GSmtp::ServerProtocol::Event GSmtp::ServerProtocol::commandEvent(
const std::string & command )
const
617 if( command ==
"QUIT" )
return eQuit ;
618 if( command ==
"HELO" )
return eHelo ;
619 if( command ==
"EHLO" )
return eEhlo ;
620 if( command ==
"RSET" )
return eRset ;
621 if( command ==
"DATA" )
return eData ;
622 if( command ==
"RCPT" )
return eRcpt ;
623 if( command ==
"MAIL" )
return eMail ;
624 if( command ==
"VRFY" )
return eVrfy ;
625 if( command ==
"NOOP" )
return eNoop ;
626 if( command ==
"EXPN" )
return eExpn ;
627 if( command ==
"HELP" )
return eHelp ;
628 if( command ==
"STARTTLS" )
return eStartTls ;
629 if( m_sasl->active() && command ==
"AUTH" )
return eAuth ;
633 void GSmtp::ServerProtocol::sendClosing()
635 send(
"221 closing connection" ) ;
638 void GSmtp::ServerProtocol::sendVerified(
const std::string & user )
640 send( std::string(
"250 ") + user ) ;
643 void GSmtp::ServerProtocol::sendNotVerified(
const std::string & user ,
bool temporary )
645 send( std::string() + (temporary?
"450":
"550") +
" no such mailbox: " +
G::Str::printable(user) ) ;
648 void GSmtp::ServerProtocol::sendWillAccept(
const std::string & user )
650 send( std::string(
"252 cannot verify but will accept: ") +
G::Str::printable(user) ) ;
653 void GSmtp::ServerProtocol::sendUnrecognised(
const std::string & line )
655 send(
"500 command unrecognized: \"" +
G::Str::printable(line) + std::string(
"\"") ) ;
659 void GSmtp::ServerProtocol::sendNotImplemented()
661 send(
"502 command not implemented" ) ;
664 void GSmtp::ServerProtocol::sendAuthRequired()
666 std::string more_help = sensitive() ?
": use starttls" :
"" ;
667 send( std::string() +
"530 authentication required" + more_help ) ;
670 void GSmtp::ServerProtocol::sendNoRecipients()
672 send(
"554 no valid recipients" ) ;
675 void GSmtp::ServerProtocol::sendTooBig(
bool disconnecting )
677 send( disconnecting ?
"554 message too big, disconnecting" :
"554 message too big" ) ;
680 void GSmtp::ServerProtocol::sendDataReply()
682 send(
"354 start mail input -- end with <CRLF>.<CRLF>" ) ;
685 void GSmtp::ServerProtocol::sendRsetReply()
687 send(
"250 state reset" ) ;
690 void GSmtp::ServerProtocol::sendMailReply()
695 void GSmtp::ServerProtocol::sendCompletionReply(
bool ok ,
const std::string & reason )
700 send( std::string(
"452 message processing failed: ") + reason ) ;
703 void GSmtp::ServerProtocol::sendRcptReply()
708 void GSmtp::ServerProtocol::sendBadFrom( std::string reason )
710 std::string msg(
"553 mailbox name not allowed") ;
711 if( ! reason.empty() )
714 msg.append( reason ) ;
719 void GSmtp::ServerProtocol::sendBadTo(
const std::string & text ,
bool temporary )
721 send( std::string() + (temporary?
"450":
"550") +
" mailbox unavailable: " + text ) ;
724 void GSmtp::ServerProtocol::sendEhloReply()
726 std::ostringstream ss ;
727 ss <<
"250-" << m_text.hello(m_smtp_peer_name) << crlf() ;
730 if( m_sasl->active() && !sensitive() )
731 ss <<
"250-AUTH " << m_sasl->mechanisms() << crlf() ;
733 if( m_with_ssl && !m_secure )
734 ss <<
"250-STARTTLS" << crlf() ;
737 ss <<
"250-VRFY" << crlf() ;
739 ss <<
"250 8BITMIME" ;
743 void GSmtp::ServerProtocol::sendHeloReply()
748 void GSmtp::ServerProtocol::sendOk()
753 const std::string & GSmtp::ServerProtocol::crlf()
755 static const std::string s(
"\015\012" ) ;
759 void GSmtp::ServerProtocol::send( std::string line ,
bool go_secure )
762 line.append( crlf() ) ;
763 m_sender.protocolSend( line , go_secure ) ;
766 std::pair<std::string,std::string> GSmtp::ServerProtocol::parseFrom(
const std::string & line )
const
769 return parse( line ) ;
772 std::pair<std::string,std::string> GSmtp::ServerProtocol::parseTo(
const std::string & line )
const
776 return parse( line ) ;
779 std::pair<std::string,std::string> GSmtp::ServerProtocol::parse(
const std::string & line )
const
781 size_t start = line.find(
'<' ) ;
782 size_t end = line.find(
'>' ) ;
783 if( start == std::string::npos || end == std::string::npos || end < start )
785 std::string reason(
"missing or invalid angle brackets in mailbox name" ) ;
786 return std::make_pair(std::string(),reason) ;
789 std::string s = line.substr( start + 1U , end - start - 1U ) ;
793 if( s.length() > 0U && s.at(0U) ==
'@' )
795 size_t colon_pos = s.find(
':' ) ;
796 if( colon_pos == std::string::npos )
798 std::string reason(
"invalid mailbox name: no colon after leading at character" ) ;
799 return std::make_pair(std::string(),reason) ;
801 s = s.substr( colon_pos + 1U ) ;
804 return std::make_pair(s,std::string()) ;
807 std::string GSmtp::ServerProtocol::parsePeerName(
const std::string & line )
const
809 size_t pos = line.find_first_of(
" \t" ) ;
810 if( pos == std::string::npos )
811 return std::string() ;
813 std::string smtp_peer_name = line.substr( pos + 1U ) ;
815 return smtp_peer_name ;
818 void GSmtp::ServerProtocol::badClientEvent()
820 m_bad_client_count++ ;
821 if( m_bad_client_limit && m_bad_client_count >= m_bad_client_limit )
823 std::string reason =
"too many protocol errors from the client" ;
824 G_DEBUG(
"GSmtp::ServerProtocol::badClientEvent: " << reason <<
": dropping the connection" ) ;
825 throw ProtocolDone( reason ) ;
832 const GNet::Address & peer_address ,
const std::string & peer_socket_name ) :
834 m_thishost(thishost) ,
835 m_peer_address(peer_address) ,
836 m_peer_socket_name(peer_socket_name)
842 return m_thishost +
" -- " + m_ident +
" -- Service ready" ;
847 return m_thishost +
" says hello" ;
852 return receivedLine( smtp_peer_name , m_peer_address.displayString(
false) , m_peer_socket_name , m_thishost ) ;
855 std::string GSmtp::ServerProtocolText::shortened( std::string prefix , std::string s )
860 s.empty() || pos == std::string::npos || (pos+1U) == s.length() ?
862 ( prefix +
G::Str::printable(s.substr(pos+1U),
'^') ) ;
866 const std::string & peer_address ,
const std::string & peer_socket_name ,
const std::string & thishost )
874 std::ostringstream ss ;
876 <<
"Received: from " << smtp_peer_name
878 <<
"[" << peer_address <<
"]"
879 << shortened(
"," , peer_socket_name )
880 <<
") by " << thishost <<
" with ESMTP ; "
884 << date.
yyyy() <<
" "
885 << time.
hhmmss(
":") <<
" "
906 preprocessor_timeout(i) ,
907 disconnect_on_overflow(true)
void secure(const std::string &certificate)
To be called when the transport protocol goes into secure mode.
ServerProtocolText(const std::string &ident, const std::string &thishost, const GNet::Address &peer_address, const std::string &peer_socket_name)
Constructor.
An interface used by ServerProtocol to send protocol replies.
static EpochTime now()
Returns the current epoch time.
static Library * instance()
Returns a pointer to a library object, if any.
static bool valid(const std::string &)
Returns true if the string can be decoded.
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
virtual void onTimeout()
Final override from GNet::AbstractTimer.
A date (dd/mm/yyyy) class.
std::string monthName(bool brief=false) const
Returns the month as a string (in english).
virtual void onTimeoutException(std::exception &)
Final override from GNet::AbstractTimer.
An interface used by ServerProtocol to provide response text strings.
static Offset offset(EpochTime epoch_time)
Returns the offset between UTC and localtime as at 'epoch_time'.
virtual std::string received(const std::string &smtp_peer_name_from_helo) const
Final override from GSmtp::ServerProtocol::Text.
ServerProtocol(Sender &sender, Verifier &verifier, ProtocolMessage &pmessage, const GAuth::Secrets &secrets, Text &text, GNet::Address peer_address, const std::string &peer_socket_name, Config config)
Constructor.
static BrokenDownTime local(EpochTime epoch_time)
Converts from epoch time to local broken-down-time.
void connect(Slot3< P1, P2, P3 > slot)
The Address class encapsulates an IP transport address.
int monthday() const
Returns the day of the month.
std::vector< std::string > StringArray
A std::vector of std::strings.
Slot0 slot(T &object, void(T::*fn)())
Part of the slot/signal system.
void apply(const std::string &line)
Called on receipt of a string from the client.
std::string::size_type size_type
A std::size_t type.
A simple time-of-day (hh/mm/ss) class.
static void splitIntoTokens(const std::string &in, Strings &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
static VerifierStatus parse(const std::string &str, std::string &to_ref)
Parses a str() string into a structure and a recipient 'to' address (by reference).
static void trim(std::string &s, const std::string &ws)
Trims both ends of s, taking off any of the 'ws' characters.
An asynchronous interface that verifies recipient 'to' addresses.
Config(bool, unsigned int)
virtual G::Signal2< std::string, VerifierStatus > & doneSignal()=0
Returns a signal that is emit()ed when the verify() request is complete.
static void trimLeft(std::string &s, const std::string &ws, size_type limit=0U)
Trims the lhs of s, taking off up to 'limit' of the 'ws' characters.
void init()
Starts the protocol. Use only once after construction.
A simple interface to a store of secrets as used in authentication.
virtual ~ServerProtocol()
Destructor.
std::string yyyy() const
Returns the year as a four-digit decimal string.
std::string weekdayName(bool brief=false) const
Returns an english string representation of the day of the week.
virtual G::Signal3< bool, unsigned long, std::string > & doneSignal()=0
Returns a signal which is raised once process() has completed.
static std::string offsetString(Offset offset)
Converts the given utc/localtime offset into a five-character "+/-hhmm" string.
A structure containing configuration parameters for ServerProtocol.
An interface used by the ServerProtocol class to assemble and process an incoming message...
A RAII class for initialising the underlying ssl library.
bool enabled(bool for_serving=false) const
Returns true if this is a real and enabled ssl library.
void addTransition(Event event, State from, State to, Action action)
Adds a transition.
struct std::tm BrokenDownTime
std::string hhmmss(const char *sep=NULL) const
Returns a hhmmss string.
static std::string decode(const std::string &)
Decodes the given string.
SASL authentication classes.
virtual std::string hello(const std::string &smtp_peer_name_from_helo) const
Final override from GSmtp::ServerProtocol::Text.
static std::string encode(const std::string &s, const std::string &line_break)
Encodes the given string.
static std::string receivedLine(const std::string &smtp_peer_name_from_helo, const std::string &peer_address, const std::string &peer_socket_name, const std::string &thishost)
Returns a standard "Received:" line.
virtual std::string greeting() const
Final override from GSmtp::ServerProtocol::Text.
static void toUpper(std::string &s)
Replaces all lowercase characters in string 's' by uppercase characters.