E-MailRelay
gspamfilter.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gspamfilter.cpp
19///
20
21#include "gdef.h"
22#include "gspamfilter.h"
23#include "gstr.h"
24#include "glog.h"
25
27 Filter::Type , const Filter::Config & config , const std::string & server ,
28 bool read_only , bool always_pass ) :
29 m_es(es) ,
30 m_done_timer(*this,&SpamFilter::onDoneTimeout,m_es) ,
31 m_done_signal(true) ,
32 m_file_store(file_store) ,
33 m_location(server) ,
34 m_read_only(read_only) ,
35 m_always_pass(always_pass) ,
36 m_connection_timeout(config.timeout) ,
37 m_response_timeout(config.timeout) ,
38 m_result(Result::fail)
39{
40 m_client_ptr.eventSignal().connect( G::Slot::slot(*this,&GFilters::SpamFilter::clientEvent) ) ;
41 m_client_ptr.deletedSignal().connect( G::Slot::slot(*this,&GFilters::SpamFilter::clientDeleted) ) ;
42}
43
45{
46 m_client_ptr.eventSignal().disconnect() ;
47 m_client_ptr.deletedSignal().disconnect() ;
48}
49
50std::string GFilters::SpamFilter::id() const
51{
52 return m_location.displayString() ;
53}
54
55bool GFilters::SpamFilter::quiet() const
56{
57 return false ;
58}
59
60void GFilters::SpamFilter::start( const GStore::MessageId & message_id )
61{
62 // the spam client can do more than one request, but it is simpler to start fresh
63 m_client_ptr.reset( std::make_unique<GSmtp::SpamClient>( GNet::ExceptionSink(m_client_ptr,m_es.esrc()) ,
64 m_location , m_read_only , m_connection_timeout , m_response_timeout ) ) ;
65
66 m_done_signal.emitted( false ) ;
67 m_text.erase() ;
68 m_client_ptr->request( m_file_store.contentPath(message_id).str() ) ; // (no need to wait for connection)
69}
70
71void GFilters::SpamFilter::clientDeleted( const std::string & reason )
72{
73 if( !reason.empty() && !m_done_signal.emitted() )
74 {
75 G_WARNING( "GFilters::SpamFilter::clientDeleted: spamd interaction failed: " << reason ) ;
76 }
77 m_text = reason ;
78 done() ;
79}
80
81void GFilters::SpamFilter::clientEvent( const std::string & s1 , const std::string & s2 , const std::string & )
82{
83 G_DEBUG( "GFilters::SpamFilter::clientEvent: [" << s1 << "] [" << s2 << "]" ) ;
84 if( s1 == "spam" )
85 {
86 m_text = ( s2.empty() || m_always_pass ) ? std::string() : std::string("spam: ").append(G::Str::printable(s2)) ;
87 done() ;
88 }
89 else if( s1 == "failed" )
90 {
91 m_text = G::Str::printable( s2 ) ;
92 done() ;
93 }
94}
95
96bool GFilters::SpamFilter::special() const
97{
98 return false ;
99}
100
101void GFilters::SpamFilter::done()
102{
103 m_done_timer.startTimer( 0U ) ;
104}
105
106void GFilters::SpamFilter::onDoneTimeout()
107{
108 m_result = m_text.empty() ? Result::ok : Result::fail ;
109 m_done_signal.emit( static_cast<int>(m_result) ) ;
110}
111
112GSmtp::Filter::Result GFilters::SpamFilter::result() const
113{
114 return m_result ;
115}
116
117std::string GFilters::SpamFilter::response() const
118{
119 return m_text.empty() ? std::string() : std::string("rejected") ;
120}
121
122int GFilters::SpamFilter::responseCode() const
123{
124 return 0 ;
125}
126
127std::string GFilters::SpamFilter::reason() const
128{
129 return m_text ;
130}
131
132G::Slot::Signal<int> & GFilters::SpamFilter::doneSignal() noexcept
133{
134 return m_done_signal ;
135}
136
137void GFilters::SpamFilter::cancel()
138{
139 G_DEBUG( "GFilters::SpamFilter::cancel: cancelled" ) ;
140 m_done_timer.cancelTimer() ;
141 m_text.erase() ;
142 if( m_client_ptr.get() != nullptr && m_client_ptr->busy() )
143 m_client_ptr.reset() ;
144}
145
A Filter class that passes the body of a message file to a remote process over the network and option...
Definition: gspamfilter.h:42
~SpamFilter() override
Destructor.
Definition: gspamfilter.cpp:44
SpamFilter(GNet::ExceptionSink, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &server_location, bool read_only, bool always_pass)
Constructor.
Definition: gspamfilter.cpp:26
G::Slot::Signal< const std::string & > & deletedSignal() noexcept
A signal that is triggered after deleteSignal() once the client has been deleted and the ClientPtr is...
Definition: gclientptr.cpp:27
G::Slot::Signal< const std::string &, const std::string &, const std::string & > & eventSignal() noexcept
A signal that is linked to the contained client's eventSignal().
Definition: gclientptr.cpp:32
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A concrete implementation of the MessageStore interface dealing in paired flat files.
Definition: gfilestore.h:56
A somewhat opaque identifer for a GStore::MessageStore message id.
Definition: gmessagestore.h:43
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 ...
Definition: gstr.cpp:916
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
Definition: gslot.h:240
STL namespace.