30std::string GSmtp::SpamClient::m_username ;
33 unsigned int connection_timeout ,
unsigned int response_timeout ) :
36 .set_line_buffer_config(
GNet::LineBuffer::
Config::newline())
37 .set_connection_timeout(connection_timeout)
38 .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.data() , 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( std::string_view(m_buffer.data(),
static_cast<std::size_t
>(n)) ) ;
165GSmtp::SpamClient::Response::Response(
bool read_only ) :
166 m_read_only(read_only)
170GSmtp::SpamClient::Response::~Response()
174 if( m_stream.is_open() )
185void GSmtp::SpamClient::Response::add(
const std::string & path ,
const std::string & line )
187 if( m_state == 0 && !ok(line) )
191 else if( m_state == 0 )
193 G_DEBUG(
"GSmtp::SpamClient::Request::sendMore: spam response" ) ;
194 m_path_final = path ;
195 m_path_tmp = path +
".spamd" ;
196 if( !m_read_only && !m_stream.is_open() )
199 if( !m_stream.good() )
200 throw SpamClient::Error(
"cannot write temporary content file" , m_path_tmp ) ;
202 m_content_length = m_size = 0U ;
207 G_LOG(
"GSmtp::SpamClient::Response::add: spam response line: ["
209 if( line.find(
"Spam:") == 0U )
213 else if( ( line.empty() || line ==
"\r" ) && m_content_length == 0U )
214 throw SpamClient::Error(
"invalid response headers" ) ;
215 else if( line.empty() || line ==
"\r" )
218 else if( m_state == 2 )
220 m_size += ( line.size() + 1U ) ;
222 if( m_stream.is_open() )
223 m_stream << line <<
"\n" ;
225 if( m_size >= m_content_length )
227 if( m_size != m_content_length )
228 G_WARNING(
"GSmtp::SpamClient::Response::add: incorrect content length in spam response" ) ;
229 G_LOG(
"GSmtp::SpamClient::add: spam response size: " << m_content_length ) ;
231 if( m_stream.is_open() )
234 if( m_stream.fail() )
235 throw SpamClient::Error(
"cannot write temporary content file" , m_path_tmp ) ;
246bool GSmtp::SpamClient::Response::complete()
const
248 return m_state == 3 ;
251bool GSmtp::SpamClient::Response::ok(
const std::string & line )
const
254 if( line.empty() )
return false ;
255 if( line.find(
"SPAMD/") != 0U )
return false ;
256 std::string_view line_sv( line ) ;
259 return t.valid() ? ( t() ==
"0"_sv ) :
false ;
262std::string GSmtp::SpamClient::Response::result()
const
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
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...
SpamClient(GNet::EventState, const GNet::Location &host_and_service, bool read_only, unsigned int connection_timeout, unsigned int response_timeout)
Constructor.
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.
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.
A Path object represents a file system path.
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 unsigned int toUInt(std::string_view s)
Converts string 's' to an unsigned int.
static std::string_view ws() noexcept
Returns a string of standard whitespace characters.
static std::string trimmed(const std::string &s, std::string_view ws)
Returns a trim()med version of s.
A zero-copy string token iterator where the token separators are runs of whitespace characters,...
A structure containing GNet::Client configuration parameters.