38 m_filter(ff.newFilter(es,false,config.filter_address,config.filter_timeout)) ,
39 m_protocol(es,*this,client_secrets,config.sasl_client_config,config.client_protocol_config,config.secure_tunnel) ,
40 m_secure_tunnel(config.secure_tunnel) ,
45 m_filter->doneSignal().connect(
G::Slot::slot(*
this,&Client::filterDone) ) ;
50 m_protocol.doneSignal().disconnect() ;
51 m_protocol.filterSignal().disconnect() ;
52 m_filter->doneSignal().disconnect() ;
58 net_config.bind_local_address = smtp_config.bind_local_address ;
59 net_config.local_address = smtp_config.local_address ;
60 net_config.connection_timeout = smtp_config.connection_timeout ;
61 net_config.secure_connection_timeout = smtp_config.secure_connection_timeout ;
69 return m_message_done_signal ;
74 G_ASSERT( m_store ==
nullptr ) ;
75 G_ASSERT( !connected() ) ;
81 G_ASSERT( message && message->toCount() ) ;
82 if( message && message->toCount() )
84 m_message.reset( message.release() ) ;
90void GSmtp::Client::onConnect()
98void GSmtp::Client::onSecure(
const std::string & ,
const std::string & ,
const std::string & )
100 if( m_secure_tunnel )
103 m_protocol.secure() ;
106void GSmtp::Client::startSending()
108 G_LOG_S(
"GSmtp::Client::startSending: smtp connection to " << peerAddress().second.displayString() ) ;
109 if( m_store !=
nullptr )
112 m_iter = m_store->iterator(
true ) ;
115 bool started = sendNext() ;
118 G_DEBUG(
"GSmtp::Client::startSending: nothing to send" ) ;
129bool GSmtp::Client::sendNext()
135 std::unique_ptr<StoredMessage> message( ++m_iter ) ;
136 if( message ==
nullptr )
138 if( m_message_count != 0U )
139 G_LOG(
"GSmtp::Client: no more messages to send" ) ;
140 m_message_count = 0U ;
143 m_message.reset( message.release() ) ;
150void GSmtp::Client::start()
152 G_ASSERT( message()->toCount() != 0U ) ;
156 eventSignal().emit(
"sending" , message()->location() , std::string() ) ;
157 if( this_.deleted() ) return ;
159 m_protocol.start( std::weak_ptr<StoredMessage>(message()) ) ;
162std::shared_ptr<GSmtp::StoredMessage> GSmtp::Client::message()
164 G_ASSERT( m_message !=
nullptr ) ;
165 if( m_message ==
nullptr )
166 m_message = std::make_shared<StoredMessageStub>() ;
171bool GSmtp::Client::protocolSend(
const std::string & line , std::size_t offset ,
bool go_secure )
173 bool rc = send( line , offset ) ;
179void GSmtp::Client::filterStart()
181 if( !m_filter->simple() )
183 G_LOG(
"GSmtp::Client::filterStart: client filter: [" << m_filter->id() <<
"]" ) ;
186 m_filter->start( message()->
id() ) ;
189void GSmtp::Client::filterDone(
int filter_result )
191 const bool ok = filter_result == 0 ;
192 const bool abandon = filter_result == 1 ;
193 const bool stop_scanning = m_filter->special() ;
194 G_ASSERT( m_filter->reason().empty() == (ok || abandon) ) ;
198 G_DEBUG(
"GSmtp::Client::filterDone: making this the last message" ) ;
202 std::string reopen_error ;
203 if( !m_filter->simple() )
205 G_LOG(
"GSmtp::Client::filterDone: client filter done: " << m_filter->str(
false) ) ;
207 reopen_error = message()->reopen() ;
211 if( ok && reopen_error.empty() )
213 m_protocol.filterDone(
true , std::string() , std::string() ) ;
217 m_protocol.filterDone(
false , std::string() , std::string() ) ;
219 else if( !reopen_error.empty() )
221 m_protocol.filterDone(
false ,
"failed" , reopen_error ) ;
225 m_protocol.filterDone(
false , m_filter->response() , m_filter->reason() ) ;
229void GSmtp::Client::protocolDone(
int response_code ,
const std::string & response_in ,
230 const std::string & reason_in ,
const G::StringArray & rejectees )
232 G_DEBUG(
"GSmtp::Client::protocolDone: \"" << response_in <<
"\"" ) ;
234 std::string response = response_in.empty() ? std::string() : (
"smtp client failure: " + response_in ) ;
235 std::string reason = reason_in.empty() ? response : reason_in ;
236 std::string short_reason = ( response_in.empty() || reason_in.empty() ) ? response_in : reason_in ;
237 std::string message_location = message()->location() ;
239 if( response_code == -1 )
242 short_reason =
"abandoned" ;
244 else if( response_code == -2 )
246 messageFail( 550 , reason ) ;
247 short_reason =
"rejected" ;
249 else if( response.empty() )
254 else if( rejectees.empty() )
257 G_ASSERT( !reason.empty() ) ;
259 messageFail( response_code , reason ) ;
265 message()->edit( rejectees ) ;
266 messageFail( response_code , reason ) ;
270 eventSignal().emit(
"sent" , message_location , short_reason ) ;
271 if( this_.deleted() ) return ;
273 if( m_store !=
nullptr )
277 G_DEBUG(
"GSmtp::Client::protocolDone: all sent" ) ;
284 messageDoneSignal().emit( response ) ;
288void GSmtp::Client::quitAndFinish()
290 m_protocol.finish() ;
294void GSmtp::Client::messageDestroy()
296 message()->destroy() ;
300void GSmtp::Client::messageFail(
int response_code ,
const std::string & reason )
302 message()->fail( reason , response_code ) ;
306bool GSmtp::Client::onReceive(
const char * line_data , std::size_t line_size , std::size_t , std::size_t ,
char )
308 std::string line( line_data , line_size ) ;
312 bool done = m_protocol.apply( line ) ;
313 if( this_.deleted() )
return false ;
323void GSmtp::Client::onDelete(
const std::string & error )
325 G_DEBUG(
"GSmtp::Client::onDelete: error [" << error <<
"]" ) ;
326 if( ! error.empty() )
328 G_LOG(
"GSmtp::Client: smtp client error: " << error ) ;
330 messageFail( 0 , error ) ;
335void GSmtp::Client::onSendComplete()
337 m_protocol.sendComplete() ;
342GSmtp::Client::Config::Config() :
343 local_address(
GNet::Address::defaultAddress())
347GSmtp::Client::Config::Config(
const std::string & filter_address_ ,
unsigned int filter_timeout_ ,
348 bool bind_local_address_ ,
const GNet::Address & local_address_ ,
349 const ClientProtocol::Config & protocol_config_ ,
unsigned int connection_timeout_ ,
350 unsigned int secure_connection_timeout_ ,
bool secure_tunnel_ ,
351 const std::string & sasl_client_config_ ) :
352 filter_address(filter_address_) ,
353 filter_timeout(filter_timeout_) ,
354 bind_local_address(bind_local_address_) ,
355 local_address(local_address_) ,
356 client_protocol_config(protocol_config_) ,
357 connection_timeout(connection_timeout_) ,
358 secure_connection_timeout(secure_connection_timeout_) ,
359 secure_tunnel(secure_tunnel_) ,
360 sasl_client_config(sasl_client_config_)
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
The GNet::Address class encapsulates a TCP/UDP transport address.
An exception class that is detected by GNet::EventHandlerList and results in onException() being call...
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
static LineBufferConfig smtp()
Convenience factory function.
A class that represents the remote target for out-going client connections.
G::Slot::Signal & filterSignal()
Returns a signal that is raised when the protocol needs to do message filtering.
G::Slot::Signal< int, const std::string &, const std::string &, const G::StringArray & > & doneSignal()
Returns a signal that is raised once the protocol has finished with a given message.
A class which acts as an SMTP client, extracting messages from a message store and forwarding them to...
void sendMessage(std::unique_ptr< StoredMessage > message)
Starts sending the given message.
void sendMessagesFrom(MessageStore &store)
Sends all messages from the given message store once connected.
~Client() override
Destructor.
Client(GNet::ExceptionSink, FilterFactory &, const GNet::Location &remote, const GAuth::SaslClientSecrets &client_secrets, const Config &config)
Constructor.
G::Slot::Signal< const std::string & > & messageDoneSignal()
Returns a signal that indicates that sendMessage() has completed or failed.
A factory interface for GSmtp::Filter message processors.
A class which allows SMTP messages to be stored and retrieved.
An object to represent a nested execution context.
static std::string printable(const std::string &in, char escape='\\')
Returns a printable representation of the given input string, using chacter code ranges 0x20 to 0x7e ...
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
std::vector< std::string > StringArray
A std::vector of std::strings.
A structure containing GNet::Client configuration parameters.
A structure containing GSmtp::Client configuration parameters.