33 Filter::Type filter_type ,
const Filter::Config & filter_config ,
const std::string & spec ) :
36 m_filter_type(filter_type) ,
37 m_filter_config(filter_config) ,
40 m_result(Result::fail) ,
42 m_timer(*this,&
MxFilter::onTimeout,es)
51 m_lookup->doneSignal().disconnect() ;
56 G::Path envelope_path = m_store.envelopePath( message_id , storestate() ) ;
58 unsigned int port = parseForwardToPort( envelope.forward_to ) ;
59 std::string domain = parseForwardToDomain( envelope.forward_to ) ;
62 m_timer.startTimer( 0U ) ;
63 m_result = Result::ok ;
67 G_LOG(
"GFilters::MxFilter::start: " << prefix() <<
" looking up [" << domain <<
"]" ) ;
69 if( m_lookup ) m_lookup->doneSignal().disconnect() ;
70 m_lookup = std::make_unique<MxLookup>( m_es , mxconfig(m_spec) , mxnameservers(m_spec) ) ;
71 m_lookup->doneSignal().connect(
G::Slot::slot(*
this,&MxFilter::lookupDone) ) ;
73 m_lookup->start( message_id , domain , port ) ;
74 if( m_filter_config.timeout )
75 m_timer.startTimer( m_filter_config.timeout ) ;
77 m_timer.cancelTimer() ;
81std::string GFilters::MxFilter::id()
const
86bool GFilters::MxFilter::quiet()
const
91bool GFilters::MxFilter::special()
const
96GSmtp::Filter::Result GFilters::MxFilter::result()
const
101std::string GFilters::MxFilter::response()
const
103 return std::string( m_result == Result::fail ?
"failed" :
"" ) ;
106int GFilters::MxFilter::responseCode()
const
111std::string GFilters::MxFilter::reason()
const
118 return m_done_signal ;
121void GFilters::MxFilter::cancel()
127void GFilters::MxFilter::onTimeout()
129 G_DEBUG(
"GFilters::MxFilter::onTimeout: response=[" << response() <<
"] special=" << m_special ) ;
130 m_done_signal.emit(
static_cast<int>(m_result) ) ;
133void GFilters::MxFilter::lookupDone(
GStore::MessageId message_id , std::string address , std::string error )
135 G_ASSERT( address.empty() == !error.empty() ) ;
141 G_LOG(
"GFilters::MxFilter::start: " << prefix() <<
": [" << message_id.
str() <<
"]: "
142 <<
"setting forward-to-address [" << address <<
"]"
143 << (error.empty()?
"":
" (") << error << (error.empty()?
"":
")") ) ;
148 msg.editEnvelope( [address](
GStore::Envelope &env_){env_.forward_to_address=address;} ) ;
150 m_result = error.empty() ? Result::ok : Result::fail ;
151 m_timer.startTimer( 0U ) ;
154GStore::FileStore::State GFilters::MxFilter::storestate()
const
156 return m_filter_type == GSmtp::Filter::Type::server ?
157 GStore::FileStore::State::New :
158 GStore::FileStore::State::Locked ;
163 MxLookup::Config config ;
167 if( t().find(
"nst=") == 0U && t().size() > 4U )
169 else if( t().find(
"rt=") == 0U && t().size() > 3U )
175std::vector<GNet::Address> GFilters::MxFilter::mxnameservers(
const std::string & spec )
177 std::vector<GNet::Address> result ;
184 return result.empty() ? GNet::nameservers(53U) : result ;
187std::string GFilters::MxFilter::parseForwardToDomain(
const std::string & forward_to )
189 return parseForwardTo(forward_to).first ;
192unsigned int GFilters::MxFilter::parseForwardToPort(
const std::string & forward_to )
194 return parseForwardTo(forward_to).second ;
197std::pair<std::string,unsigned int> GFilters::MxFilter::parseForwardTo(
const std::string & forward_to )
205 std::size_t pos = no_user.rfind(
':' ) ;
209 auto first = with_port ? head : no_user ;
211 return { G::sv_to_string(first) , second } ;
214std::string GFilters::MxFilter::prefix()
const
216 return G::sv_to_string(strtype(m_filter_type)).append(
" [").append(
id()).append(1U,
']') ;
A concrete GSmtp::Filter class for message routing: if the message's 'forward-to' field is set then t...
~MxFilter() override
Destructor.
MxFilter(GNet::ExceptionSink es, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &spec)
Constructor.
static bool enabled()
Returns true if implemented.
static Address parse(const std::string &display_string)
Factory function for any address family.
static bool validString(const std::string &display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A structure containing the contents of an envelope file, with support for file reading,...
A concrete implementation of the MessageStore interface dealing in paired flat files.
static Envelope readEnvelope(const G::Path &, std::ifstream *=nullptr)
Used by FileStore sibling classes to read an envelope file.
A somewhat opaque identifer for a GStore::MessageStore message id.
std::string str() const
Returns the id string.
A concete class implementing the GStore::StoredMessage interface for separate envelope and content fi...
A general-purpose exception class derived from std::exception and containing an error message.
A Path object represents a file system path.
static string_view headView(string_view in, std::size_t pos, string_view default_={}) noexcept
Like head() but returning a view into the input string.
static string_view tailView(string_view in, std::size_t pos, string_view default_={}) noexcept
Like tail() but returning a view into the input string.
static unsigned int toUInt(string_view s)
Converts string 's' to an unsigned int.
static bool isNumeric(string_view s, bool allow_minus_sign=false) noexcept
Returns true if every character is a decimal digit.
static bool headMatch(const std::string &in, string_view head) noexcept
Returns true if the string has the given start (or head is empty).
A zero-copy string token iterator where the token separators are runs of whitespace characters,...
An interval between two G::SystemTime values or two G::TimerTime values.
A class like c++17's std::string_view.
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
A configuration structure for GFilters::MxLookup.