29std::string GSmtp::SpamClient::m_username ;
32 unsigned int connection_timeout ,
unsigned int response_timeout ) :
35 .set_line_buffer_config(
GNet::LineBuffer::
Config::newline())
36 .set_connection_timeout(connection_timeout)
37 .set_response_timeout(response_timeout)) ,
43 G_LOG(
"GSmtp::SpamClient::ctor: spam connection to [" << location <<
"]" ) ;
44 G_DEBUG(
"GSmtp::SpamClient::ctor: spam read/only=" << read_only ) ;
45 G_DEBUG(
"GSmtp::SpamClient::ctor: spam connection timeout " << connection_timeout ) ;
46 G_DEBUG(
"GSmtp::SpamClient::ctor: spam response timeout " << response_timeout ) ;
52 m_username = username ;
63 G_DEBUG(
"GSmtp::SpamClient::request: path=" << path ) ;
65 throw Error(
"protocol error" ) ;
68 m_timer.startTimer( 0U ) ;
71void GSmtp::SpamClient::onTimeout()
73 G_DEBUG(
"GSmtp::SpamClient::onTimeout: connected=" << connected() ) ;
78void GSmtp::SpamClient::onDelete(
const std::string & )
82void GSmtp::SpamClient::onSecure(
const std::string & ,
const std::string & ,
const std::string & )
86void GSmtp::SpamClient::onConnect()
92void GSmtp::SpamClient::start()
94 m_request.send( m_path , m_username ) ;
97void GSmtp::SpamClient::onSendComplete()
99 while( m_request.sendMore() )
105bool GSmtp::SpamClient::onReceive(
const char * line_data , std::size_t line_size , std::size_t , std::size_t ,
char )
107 m_response.add( m_path , std::string(line_data,line_size) ) ;
108 if( m_response.complete() )
109 eventSignal().emit(
"spam" , m_response.result() , std::string() ) ;
115GSmtp::SpamClient::Request::Request( Client & client ) :
121void GSmtp::SpamClient::Request::send(
const std::string & path ,
const std::string & username )
123 G_LOG(
"GSmtp::SpamClient::Request::send: spam request for [" << path <<
"]" ) ;
125 if( !m_stream.good() )
126 throw SpamClient::Error(
"cannot read content file" , path ) ;
129 G_DEBUG(
"GSmtp::SpamClient::Request::send: spam request file size: " << file_size ) ;
131 std::ostringstream ss ;
132 std::string eol =
"\r\n" ;
133 ss <<
"PROCESS SPAMC/1.4" << eol ;
134 if( !username.empty() )
135 ss <<
"User: " << username << eol ;
136 ss <<
"Content-length: " << file_size << eol ;
139 bool sent = m_client->send( ss.str() ) ;
144 G_DEBUG(
"GSmtp::SpamClient::Request::send: spam sent" ) ;
147bool GSmtp::SpamClient::Request::sendMore()
149 m_stream.read( &m_buffer[0] , m_buffer.size() ) ;
150 std::streamsize n = m_stream.gcount() ;
153 G_LOG(
"GSmtp::SpamClient::Request::sendMore: spam request done" ) ;
158 G_DEBUG(
"GSmtp::SpamClient::Request::sendMore: spam request sending " << n <<
" bytes" ) ;
159 return m_client->send(
G::string_view(&m_buffer[0],
static_cast<std::size_t
>(n)) ) ;
165GSmtp::SpamClient::Response::Response(
bool read_only ) :
166 m_read_only(read_only) ,
168 m_content_length(0U) ,
173GSmtp::SpamClient::Response::~Response()
175 if( m_stream.is_open() )
182void GSmtp::SpamClient::Response::add(
const std::string & path ,
const std::string & line )
184 if( m_state == 0 && !ok(line) )
188 else if( m_state == 0 )
190 G_DEBUG(
"GSmtp::SpamClient::Request::sendMore: spam response" ) ;
191 m_path_final = path ;
192 m_path_tmp = path +
".spamd" ;
193 if( !m_read_only && !m_stream.is_open() )
196 if( !m_stream.good() )
197 throw SpamClient::Error(
"cannot write temporary content file" , m_path_tmp ) ;
199 m_content_length = m_size = 0U ;
204 G_LOG(
"GSmtp::SpamClient::Response::add: spam response line: ["
206 if( line.find(
"Spam:") == 0U )
210 else if( ( line.empty() || line ==
"\r" ) && m_content_length == 0U )
211 throw SpamClient::Error(
"invalid response headers" ) ;
212 else if( line.empty() || line ==
"\r" )
215 else if( m_state == 2 )
217 m_size += ( line.size() + 1U ) ;
219 if( m_stream.is_open() )
220 m_stream << line <<
"\n" ;
222 if( m_size >= m_content_length )
224 if( m_size != m_content_length )
225 G_WARNING(
"GSmtp::SpamClient::Response::add: incorrect content length in spam response" ) ;
226 G_LOG(
"GSmtp::SpamClient::add: spam response size: " << m_content_length ) ;
228 if( m_stream.is_open() )
231 if( m_stream.fail() )
232 throw SpamClient::Error(
"cannot write temporary content file" , m_path_tmp ) ;
243bool GSmtp::SpamClient::Response::complete()
const
245 return m_state == 3 ;
248bool GSmtp::SpamClient::Response::ok(
const std::string & line )
const
251 if( line.empty() )
return false ;
252 if( line.find(
"SPAMD/") != 0U )
return false ;
256 return t.valid() ? ( t() ==
"0"_sv ) :
false ;
259std::string GSmtp::SpamClient::Response::result()
const
262 return std::string() ;
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A class that represents the remote target for out-going client connections.
A class which acts as an SMTP client, sending messages to a remote SMTP server.
A client class that interacts with a remote process using a protocol somewhat similar to the spamassa...
static void username(const std::string &)
Sets the username used in the network protocol.
void request(const std::string &file_path)
Starts sending a request that comprises a few http-like header lines followed by the contents of the ...
bool busy() const
Returns true after request() and before the subsequent event signal.
SpamClient(GNet::ExceptionSink, const GNet::Location &host_and_service, bool read_only, unsigned int connection_timeout, unsigned int response_timeout)
Constructor.
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
static std::string sizeString(const Path &file)
Returns the file's size in string format.
static bool rename(const Path &from, const Path &to, std::nothrow_t) noexcept
Renames the file.
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
static unsigned int toUInt(string_view s)
Converts string 's' to an unsigned int.
static bool imatch(char, char) noexcept
Returns true if the two characters are the same, ignoring seven-bit case.
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 ...
static std::string trimmed(const std::string &s, string_view ws)
Returns a trim()med version of s.
static string_view ws() noexcept
Returns a string of standard whitespace characters.
A zero-copy string token iterator where the token separators are runs of whitespace characters,...
A class like c++17's std::string_view.
A structure containing GNet::Client configuration parameters.