42 explicit AnonymousText(
const std::string & = std::string() ) ;
43 std::string
greeting()
const override ;
44 std::string
hello(
const std::string & peer_name )
const override ;
45 std::string
received(
const std::string & smtp_peer_name ,
46 bool auth ,
bool secure ,
const std::string & protocol ,
47 const std::string & cipher )
const override ;
48 std::string m_thishost ;
52GSmtp::AnonymousText::AnonymousText(
const std::string & thishost ) :
55 if( m_thishost.empty() )
66 return m_thishost +
" says hello" ;
70 const std::string & ,
const std::string & )
const
72 return std::string() ;
80 std::unique_ptr<ServerProtocol::Text> ptext ) :
83 m_block(*this,esu.bind(this),server_config.dnsbl_config) ,
84 m_flush_timer(*this,&
ServerPeer::onFlushTimeout,esu.bind(this)) ,
85 m_check_timer(*this,&
ServerPeer::onCheckTimeout,esu.bind(this)) ,
87 server_config.verifier_address,server_config.verifier_timeout)) ,
88 m_pmessage(server.newProtocolMessage(esu.bind(this))) ,
89 m_ptext(ptext.release()) ,
90 m_line_buffer(
GNet::LineBufferConfig::smtp()) ,
91 m_protocol(*this,*m_verifier,*m_pmessage,server_secrets,server_config.sasl_server_config,
92 *m_ptext,peer_info.m_address,server_config.protocol_config)
94 G_LOG_S(
"GSmtp::ServerPeer: smtp connection from " << peer_info.m_address.
displayString() ) ;
95 if( server_config.dnsbl_config.empty() )
98 m_block.
start( peer_info.m_address ) ;
100 if( !server_config.protocol_config.tls_connection )
101 m_check_timer.startTimer( 1U ) ;
104void GSmtp::ServerPeer::onDelete(
const std::string & reason )
106 G_LOG_S(
"GSmtp::ServerPeer: smtp connection closed: " << reason << (reason.empty()?
"":
": ")
107 << peerAddress().second.displayString() ) ;
109 m_server.eventSignal().emit(
"done" , std::string(reason) ) ;
112void GSmtp::ServerPeer::onSendComplete()
117void GSmtp::ServerPeer::onData(
const char * data , std::size_t size )
124 if( m_protocol.halfDuplexBusy(data,size) )
126 m_line_buffer.add( data , size ) ;
133bool GSmtp::ServerPeer::onReceive(
const char * data , std::size_t size , std::size_t , std::size_t ,
char )
135 G_ASSERT( size != 0U ) ;
if( size == 0U )
return true ;
141 if( m_protocol.halfDuplexBusy() && !m_line_buffer.state().empty() )
143 G_WARNING(
"GSmtp::ServerPeer::onReceive: smtp client protocol violation: pipelining detected" ) ;
150void GSmtp::ServerPeer::onFlushTimeout()
156void GSmtp::ServerPeer::onSecure(
const std::string & certificate ,
const std::string & protocol ,
157 const std::string & cipher )
159 m_protocol.secure( certificate , protocol , cipher ) ;
162void GSmtp::ServerPeer::protocolSend(
const std::string & line ,
bool go_secure )
164 if( !send( line , 0U ) )
170 if( m_flush_timer.active() )
172 G_DEBUG(
"GSmtp::ServerPeer::protocolSend: pipeline released (" << m_line_buffer.state().size() <<
")" ) ;
173 m_flush_timer.startTimer( 0U ) ;
177void GSmtp::ServerPeer::protocolShutdown()
179 m_flush_timer.cancelTimer() ;
180 socket().shutdown() ;
193void GSmtp::ServerPeer::onCheckTimeout()
197 std::string head = m_line_buffer.state().head() ;
198 if( head.size() > 6U && head.at(0U) ==
'\x16' && head.at(1U) ==
'\x03' &&
199 ( head.at(2U) ==
'\x03' || head.at(2U) ==
'\x02' || head.at(2U) ==
'\01' ) )
200 G_WARNING(
"GSmtp::ServerPeer::doCheck: received unexpected tls handshake packet from remote client: "
201 "try enabling implicit tls (smtps)" ) ;
208 const Config & server_config ,
const std::string & forward_to ,
210 GNet::MultiServer(es,server_config.interfaces,server_config.port,
"smtp",server_config.server_peer_config,server_config.server_config) ,
213 m_server_config(server_config) ,
214 m_client_config(client_config) ,
215 m_server_secrets(server_secrets) ,
216 m_forward_to(forward_to) ,
217 m_client_secrets(client_secrets)
228 return m_event_signal ;
241 std::unique_ptr<ServerPeer> ptr ;
247 G_WARNING(
"GSmtp::Server: "
248 << format(
gettext(
"configured to reject non-local smtp connection: %1%")) % reason ) ;
252 ptr = std::make_unique<ServerPeer>( esu , peer_info , *
this ,
253 m_server_secrets , m_server_config ,
254 newProtocolText(m_server_config.anonymous,peer_info.m_address) ) ;
257 catch( std::exception & e )
259 G_WARNING(
"GSmtp::Server: new connection error: " << e.what() ) ;
261 return std::unique_ptr<GNet::ServerPeer>( ptr.release() ) ;
264std::unique_ptr<GSmtp::ServerProtocol::Text> GSmtp::Server::newProtocolText(
bool anonymous ,
268 return std::make_unique<AnonymousText>() ;
270 return std::make_unique<ServerProtocolText>( m_server_config.ident ,
276 return m_ff.newFilter( es ,
true , m_server_config.filter_address , m_server_config.filter_timeout ) ;
279std::unique_ptr<GSmtp::ProtocolMessage> GSmtp::Server::newProtocolMessageStore( std::unique_ptr<Filter> filter )
281 return std::make_unique<ProtocolMessageStore>( m_store , std::move(filter) ) ;
284std::unique_ptr<GSmtp::ProtocolMessage> GSmtp::Server::newProtocolMessageForward(
GNet::ExceptionSink es ,
285 std::unique_ptr<ProtocolMessage> pm )
288 return std::make_unique<ProtocolMessageForward>( es , m_store , m_ff , std::move(pm) , m_client_config ,
289 m_client_secrets , m_forward_to ) ;
294 const bool do_forward = ! m_forward_to.empty() ;
296 newProtocolMessageForward( es , newProtocolMessageStore(newFilter(es)) ) :
297 newProtocolMessageStore( newFilter(es) ) ;
302GSmtp::Server::Config::Config()
305GSmtp::Server::Config::Config(
bool allow_remote_ ,
const G::StringArray & interfaces_ ,
307 const std::string & ident_ ,
bool anonymous_ ,
308 const std::string & filter_address_ ,
309 unsigned int filter_timeout_ ,
310 const std::string & verifier_address_ ,
311 unsigned int verifier_timeout_ ,
314 const std::string & sasl_server_config_ ,
315 const std::string & dnsbl_config_ ) :
316 allow_remote(allow_remote_) ,
317 interfaces(interfaces_) ,
320 anonymous(anonymous_) ,
321 filter_address(filter_address_) ,
322 filter_timeout(filter_timeout_) ,
323 verifier_address(verifier_address_) ,
324 verifier_timeout(verifier_timeout_) ,
325 server_peer_config(server_peer_config_) ,
326 protocol_config(protocol_config_) ,
327 sasl_server_config(sasl_server_config_) ,
328 dnsbl_config(dnsbl_config_)
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
An interface used by GAuth::SaslServer to obtain authentication secrets.
The GNet::Address class encapsulates a TCP/UDP transport address.
std::string displayString(bool with_scope_id=false) const
Returns a string which represents the transport address.
A result structure for GNet::DnsBlock, as delivered by the DnsBlockCallback interface.
void warn() const
Emits warnings.
bool allow() const
Returns true if the type is Inactive, Local, TimeoutAllow or Allow.
void log() const
Logs the results.
void start(const Address &)
Starts an asychronous check on the given address.
An exception class that is detected by GNet::EventHandlerList and results in onException() being call...
A potential ExceptionSink that is realised by bind()ing an exception source pointer.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
static bool isLocal(const Address &, std::string &reason)
Returns true if the given address appears to be 'local', or a helpful error message if not.
static std::string canonicalName()
Returns the canonical network name assiciated with hostname().
A structure that GNet::Server uses to configure its ServerPeer objects.
A structure used in GNet::Server::newPeer().
void onData(const char *, std::size_t) override
Override from GNet::SocketProtocolSink.
A factory interface for GSmtp::Filter message processors.
A class which allows SMTP messages to be stored and retrieved.
Handles a connection from a remote SMTP client.
ServerPeer(GNet::ExceptionSinkUnbound, const GNet::ServerPeerInfo &peer_info, Server &server, const GAuth::SaslServerSecrets &server_secrets, const Server::Config &server_config, std::unique_ptr< ServerProtocol::Text > ptext)
Constructor.
An interface used by ServerProtocol to provide response text strings.
bool apply(const char *line_data, std::size_t line_size, std::size_t eolsize, std::size_t linesize, char c0)
Called on receipt of a line of text from the remote client.
void init()
Starts the protocol.
bool inDataState() const
Returns true if currently in the data-transfer state.
G::Slot::Signal< const std::string &, const std::string & > & eventSignal()
Returns a signal that indicates that something has happened.
~Server() override
Destructor.
Server(GNet::ExceptionSink es, MessageStore &store, FilterFactory &, const GAuth::SaslClientSecrets &client_secrets, const GAuth::SaslServerSecrets &server_secrets, const Config &server_config, const std::string &forward_to, const GSmtp::Client::Config &client_config)
Constructor.
std::unique_ptr< ProtocolMessage > newProtocolMessage(GNet::ExceptionSink)
Called by GSmtp::ServerPeer to construct a ProtocolMessage.
void report() const
Generates helpful diagnostics after construction.
A factory for addresss verifiers.
static TimeInterval limit()
Factory function for the maximum valid interval.
SMTP and message-store classes.
std::vector< std::string > StringArray
A std::vector of std::strings.
const char * gettext(const char *)
Returns the message translation in the current locale's codeset, eg.
A structure used in GNet::MultiServer::newPeer().
Provides anodyne SMTP protocol text.
std::string greeting() const override
Returns a system identifier for the initial greeting.
std::string received(const std::string &smtp_peer_name, bool auth, bool secure, const std::string &protocol, const std::string &cipher) const override
Returns a complete 'Received' line.
std::string hello(const std::string &peer_name) const override
Returns a hello response.
A structure containing GSmtp::Client configuration parameters.
A structure containing configuration parameters for ServerProtocol.
A structure containing GSmtp::Server configuration parameters.