39 std::unique_ptr<ServerProtocol::Text> ptext ) :
42 m_server_config(server_config) ,
43 m_block(
std::bind(&
ServerPeer::onDnsBlockResult,this,
std::placeholders::_1),esbind(esu,this),server_config.dnsbl_config) ,
44 m_check_timer(*this,&
ServerPeer::onCheckTimeout,esbind(esu,this)) ,
45 m_verifier(vf.newVerifier(esbind(esu,this),server_config.verifier_config,server_config.verifier_spec)) ,
46 m_pmessage(server.newProtocolMessage(esbind(esu,this))) ,
47 m_ptext(ptext.release()) ,
48 m_protocol(*this,*m_verifier,*m_pmessage,server_secrets,
49 *m_ptext,peerAddress(),
50 server_config.protocol_config,
enabled) ,
51 m_input_buffer(esbind(esu,this),m_protocol,server_config.buffer_config)
53 G_LOG_S(
"GSmtp::ServerPeer: smtp connection from " <<
peerAddress().displayString() ) ;
55 if( !server_config.protocol_config.tls_connection )
56 m_check_timer.startTimer( 1U ) ;
58 if( server_config.dnsbl_config.empty() )
68 m_input_buffer.flowSignal().disconnect() ;
71void GSmtp::ServerPeer::onDelete(
const std::string & reason )
73 G_LOG_S(
"GSmtp::ServerPeer: smtp connection closed: " << reason << (reason.empty()?
"":
": ")
74 << peerAddress().displayString() ) ;
76 m_server.eventSignal().emit(
"done" , std::string(reason) ) ;
79void GSmtp::ServerPeer::onData(
const char * data , std::size_t size )
81 G_ASSERT( data !=
nullptr && size != 0U ) ;
95bool GSmtp::ServerPeer::onReceive(
const char * data , std::size_t size , std::size_t , std::size_t ,
char )
97 G_ASSERT( data !=
nullptr && size != 0U ) ;
98 m_input_buffer.apply( data , size ) ;
102void GSmtp::ServerPeer::onFlow(
bool on )
110void GSmtp::ServerPeer::protocolSecure()
115void GSmtp::ServerPeer::onSecure(
const std::string & certificate ,
const std::string & protocol ,
116 const std::string & cipher )
118 m_protocol.secure( certificate , protocol , cipher ) ;
121void GSmtp::ServerPeer::protocolSend(
const std::string & line ,
bool )
123 G_ASSERT( !line.empty() ) ;
124 if( m_output_blocked )
126 m_output_buffer.append( line ) ;
128 else if( !send( line ) )
130 m_output_blocked = true ;
131 m_output_buffer.clear() ;
135void GSmtp::ServerPeer::onSendComplete()
137 G_ASSERT( m_output_blocked ) ;
138 if( send( m_output_buffer ) )
139 m_output_blocked = false ;
140 m_output_buffer.clear() ;
143void GSmtp::ServerPeer::protocolShutdown(
int how )
146 socket().shutdown( how ) ;
149void GSmtp::ServerPeer::protocolExpect( std::size_t n )
151 m_input_buffer.expect( n ) ;
154void GSmtp::ServerPeer::onDnsBlockResult(
bool allow )
162void GSmtp::ServerPeer::onCheckTimeout()
166 std::string head = m_input_buffer.head() ;
167 if( head.size() > 6U && head.at(0U) ==
'\x16' && head.at(1U) ==
'\x03' &&
168 ( head.at(2U) ==
'\x03' || head.at(2U) ==
'\x02' || head.at(2U) ==
'\01' ) )
169 G_WARNING(
"GSmtp::ServerPeer::doCheck: received unexpected tls handshake packet from remote client: "
170 "try enabling implicit tls (smtps)" ) ;
178 const std::string & forward_to ,
int forward_to_family ,
180 GNet::MultiServer(es,server_config.interfaces,server_config.port,
"smtp",
181 server_config.net_server_peer_config,
182 server_config.net_server_config) ,
186 m_server_config(server_config) ,
187 m_client_config(client_config) ,
188 m_server_secrets(server_secrets) ,
189 m_forward_to(forward_to) ,
190 m_forward_to_family(forward_to_family) ,
191 m_client_secrets(client_secrets) ,
192 m_dnsbl_suspend_time(
G::TimerTime::zero())
204 return m_server_config ;
210 return m_event_signal ;
215 serverReport( group ) ;
223 std::unique_ptr<ServerPeer> ptr ;
227 if( ! m_server_config.allow_remote && !peer_info.m_address.isLocal(reason) )
229 G_WARNING(
"GSmtp::Server: "
230 << format(
txt(
"configured to reject non-local smtp connection: %1%")) % reason ) ;
235 ptr = std::make_unique<ServerPeer>( esu , std::move(peer_info) , *
this ,
236 m_enabled , m_vf , m_server_secrets , serverConfig() ,
237 newProtocolText(m_server_config.anonymous_smtp,m_server_config.anonymous_content,peer_address,m_server_config.domain) ) ;
240 catch( std::exception & e )
242 G_WARNING(
"GSmtp::Server: new connection error: " << e.what() ) ;
249 if( !m_dnsbl_suspend_time.isZero() &&
G::TimerTime::now() < m_dnsbl_suspend_time )
250 return Config(m_server_config).set_dnsbl_config({}) ;
251 return m_server_config ;
256 G_LOG(
"GSmtp::Server::nodnsbl: dnsbl " << (s?
"disabled":
"enabled") << (s?(
" for "+
G::Str::fromUInt(s).append(1U,
's')):
"") ) ;
265std::unique_ptr<GSmtp::ServerProtocol::Text> GSmtp::Server::newProtocolText(
bool anonymous_smtp ,
266 bool anonymous_content ,
const GNet::Address & peer_address ,
const std::string & domain )
const
268 const bool with_received_line = !anonymous_content ;
269 return std::make_unique<ServerText>( m_server_config.ident , anonymous_smtp , with_received_line ,
270 domain , peer_address ) ;
273std::unique_ptr<GSmtp::Filter> GSmtp::Server::newFilter(
GNet::EventState es )
const
275 return m_ff.newFilter( es , Filter::Type::server , m_server_config.filter_config ,
276 m_server_config.filter_spec ) ;
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::EventState 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 , m_forward_to_family ) ;
294 const bool do_forward = ! m_forward_to.empty() ;
296 newProtocolMessageForward( es , newProtocolMessageStore(newFilter(es)) ) :
297 newProtocolMessageStore( newFilter(es) ) ;
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.
void start(const Address &)
Starts an asychronous check on the given address.
An exception class that is caught separately by GNet::EventEmitter and GNet::TimerList so that onExce...
The EventStateUnbound class is used as a device to force factory methods to plumb-in an ExceptionSour...
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
A move-only structure used in GNet::Server::newPeer() and containing the new socket.
Address peerAddress() const override
Returns the peer address.
void onData(const char *, std::size_t) override
Override from GNet::SocketProtocolSink.
A factory interface for making GSmtp::Filter message processors.
G::Slot::Signal< bool > & flowSignal() noexcept
Returns a signal that should be connected to a function that controls network flow control,...
Handles a connection from a remote SMTP client.
~ServerPeer() override
Destructor.
ServerPeer(GNet::EventStateUnbound, GNet::ServerPeerInfo &&peer_info, Server &server, bool enabled, VerifierFactoryBase &vf, const GAuth::SaslServerSecrets &server_secrets, const Server::Config &server_config, std::unique_ptr< ServerProtocol::Text > ptext)
Constructor.
void init()
Starts the protocol.
void enable(bool)
Disables or re-enables new SMTP sessions.
void report(const std::string &group={}) const
Generates helpful diagnostics after construction.
Config & config()
Exposes the configuration sub-object.
Server(GNet::EventState es, GStore::MessageStore &, FilterFactoryBase &, VerifierFactoryBase &, const GAuth::SaslClientSecrets &, const GAuth::SaslServerSecrets &, const Config &server_config, const std::string &forward_to, int forward_to_family, const GSmtp::Client::Config &client_config)
Constructor.
std::unique_ptr< ProtocolMessage > newProtocolMessage(GNet::EventState)
Called by GSmtp::ServerPeer to construct a ProtocolMessage.
void nodnsbl(unsigned int seconds)
Clears the DNSBL configuration string for a period of time.
~Server() override
Destructor.
G::Slot::Signal< const std::string &, const std::string & > & eventSignal() noexcept
Returns a signal that indicates that something has happened.
A factory interface for addresss verifiers.
A class which allows SMTP messages to be stored and retrieved.
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
An interval between two G::SystemTime values or two G::TimerTime values.
static TimerTime now()
Factory function for the current steady-clock time.
bool enabled() noexcept
Returns true if pop code is built in.
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
const char * txt(const char *p) noexcept
A briefer alternative to G::gettext().
A structure used in GNet::MultiServer::newPeer().
A configuration structure for GNet::ServerPeer.
A structure containing GSmtp::Client configuration parameters.
A configuration structure for GSmtp::Server.