E-MailRelay
gspamfilter.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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{
39 m_client_ptr.eventSignal().connect( G::Slot::slot(*this,&GFilters::SpamFilter::clientEvent) ) ;
40 m_client_ptr.deletedSignal().connect( G::Slot::slot(*this,&GFilters::SpamFilter::clientDeleted) ) ;
41}
42
44{
45 m_client_ptr.eventSignal().disconnect() ;
46 m_client_ptr.deletedSignal().disconnect() ;
47}
48
49std::string GFilters::SpamFilter::id() const
50{
51 return m_location.displayString() ;
52}
53
54bool GFilters::SpamFilter::quiet() const
55{
56 return false ;
57}
58
59void GFilters::SpamFilter::start( const GStore::MessageId & message_id )
60{
61 // the spam client can do more than one request, but it is simpler to start fresh
62 m_client_ptr.reset( std::make_unique<GSmtp::SpamClient>( m_es.eh(m_client_ptr) ,
63 m_location , m_read_only , m_connection_timeout , m_response_timeout ) ) ;
64
65 m_done_signal.emitted( false ) ;
66 m_text.erase() ;
67 m_client_ptr->request( m_file_store.contentPath(message_id).str() ) ; // (no need to wait for connection)
68}
69
70void GFilters::SpamFilter::clientDeleted( const std::string & reason )
71{
72 if( !reason.empty() && !m_done_signal.emitted() )
73 {
74 G_WARNING( "GFilters::SpamFilter::clientDeleted: spamd interaction failed: " << reason ) ;
75 }
76 m_text = reason ;
77 done() ;
78}
79
80void GFilters::SpamFilter::clientEvent( const std::string & s1 , const std::string & s2 , const std::string & )
81{
82 G_DEBUG( "GFilters::SpamFilter::clientEvent: [" << s1 << "] [" << s2 << "]" ) ;
83 if( s1 == "spam" )
84 {
85 m_text = ( s2.empty() || m_always_pass ) ? std::string() : std::string("spam: ").append(G::Str::printable(s2)) ;
86 done() ;
87 }
88 else if( s1 == "failed" )
89 {
90 m_text = G::Str::printable( s2 ) ;
91 done() ;
92 }
93}
94
95bool GFilters::SpamFilter::special() const
96{
97 return false ;
98}
99
100void GFilters::SpamFilter::done()
101{
102 m_done_timer.startTimer( 0U ) ;
103}
104
105void GFilters::SpamFilter::onDoneTimeout()
106{
107 m_result = m_text.empty() ? Result::ok : Result::fail ;
108 m_done_signal.emit( static_cast<int>(m_result) ) ;
109}
110
111GSmtp::Filter::Result GFilters::SpamFilter::result() const
112{
113 return m_result ;
114}
115
116std::string GFilters::SpamFilter::response() const
117{
118 return m_text.empty() ? std::string() : std::string("rejected") ;
119}
120
121int GFilters::SpamFilter::responseCode() const
122{
123 return 0 ;
124}
125
126std::string GFilters::SpamFilter::reason() const
127{
128 return m_text ;
129}
130
131G::Slot::Signal<int> & GFilters::SpamFilter::doneSignal() noexcept
132{
133 return m_done_signal ;
134}
135
136void GFilters::SpamFilter::cancel()
137{
138 G_DEBUG( "GFilters::SpamFilter::cancel: cancelled" ) ;
139 m_done_timer.cancelTimer() ;
140 m_text.erase() ;
141 if( m_client_ptr.get() != nullptr && m_client_ptr->busy() )
142 m_client_ptr.reset() ;
143}
144
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(GNet::EventState, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &server_location, bool read_only, bool always_pass)
Constructor.
Definition: gspamfilter.cpp:26
~SpamFilter() override
Destructor.
Definition: gspamfilter.cpp:43
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 lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
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:913
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
Definition: gslot.h:240
STL namespace.