E-MailRelay
gsmtpserver.h
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 gsmtpserver.h
19///
20
21#ifndef G_SMTP_SERVER_H
22#define G_SMTP_SERVER_H
23
24#include "gdef.h"
25#include "gmultiserver.h"
26#include "gsmtpclient.h"
27#include "gdnsbl.h"
28#include "glinebuffer.h"
29#include "gverifier.h"
30#include "gmessagestore.h"
31#include "gfilterfactorybase.h"
33#include "gsmtpserverprotocol.h"
34#include "gsmtpserversender.h"
35#include "gsmtpserverbufferin.h"
36#include "gprotocolmessage.h"
37#include "glimits.h"
38#include "gexception.h"
39#include <algorithm>
40#include <string>
41#include <sstream>
42#include <memory>
43#include <list>
44
45namespace GSmtp
46{
47 class Server ;
48 class ServerPeer ;
49}
50
51//| \class GSmtp::Server
52/// An SMTP server class.
53///
55{
56public:
57 using AddressList = std::vector<GNet::Address> ;
58
59 struct Config /// A configuration structure for GSmtp::Server.
60 {
61 bool allow_remote {false} ;
62 G::StringArray interfaces ;
63 unsigned int port {0U} ;
64 std::string ident ;
65 bool anonymous_smtp {false} ;
66 bool anonymous_content {false} ;
67 Filter::Config filter_config ;
68 FilterFactoryBase::Spec filter_spec ;
69 Verifier::Config verifier_config ;
70 VerifierFactoryBase::Spec verifier_spec ;
71 GNet::ServerPeer::Config net_server_peer_config ;
72 GNet::Server::Config net_server_config ;
73 ServerProtocol::Config protocol_config ;
74 std::string dnsbl_config ;
75 ServerBufferIn::Config buffer_config ;
76 std::string domain ;
77
78 Config & set_allow_remote( bool = true ) noexcept ;
79 Config & set_interfaces( const G::StringArray & ) ;
80 Config & set_port( unsigned int ) noexcept ;
81 Config & set_ident( const std::string & ) ;
82 Config & set_anonymous( bool = true ) noexcept ;
83 Config & set_anonymous_smtp( bool = true ) noexcept ;
84 Config & set_anonymous_content( bool = true ) noexcept ;
85 Config & set_filter_config( const Filter::Config & ) ;
86 Config & set_filter_spec( const FilterFactoryBase::Spec & ) ;
87 Config & set_verifier_config( const Verifier::Config & ) ;
88 Config & set_verifier_spec( const VerifierFactoryBase::Spec & ) ;
89 Config & set_net_server_peer_config( const GNet::ServerPeer::Config & ) ;
90 Config & set_net_server_config( const GNet::Server::Config & ) ;
91 Config & set_protocol_config( const ServerProtocol::Config & ) ;
92 Config & set_dnsbl_config( const std::string & ) ;
93 Config & set_buffer_config( const ServerBufferIn::Config & ) ;
94 Config & set_domain( const std::string & ) ;
95 } ;
96
99 const GAuth::SaslServerSecrets & , const Config & server_config ,
100 const std::string & forward_to , int forward_to_family ,
101 const GSmtp::Client::Config & client_config ) ;
102 ///< Constructor. Listens on the given port number using INET_ANY
103 ///< if 'server_config.interfaces' is empty, or on specific
104 ///< interfaces otherwise.
105 ///<
106 ///< If the forward-to address is given then all messages are
107 ///< forwarded as soon as they are received using the
108 ///< GSmtp::ProtocolMessageForward class and the given client
109 ///< configuration.
110 ///<
111 ///< The forward-to-family is used if the forward-to address
112 ///< is a DNS name that needs to be resolved.
113
114 ~Server() override ;
115 ///< Destructor.
116
117 void report( const std::string & group = {} ) const ;
118 ///< Generates helpful diagnostics after construction.
119
121 ///< Returns a signal that indicates that something has happened.
122
123 std::unique_ptr<ProtocolMessage> newProtocolMessage( GNet::EventState ) ;
124 ///< Called by GSmtp::ServerPeer to construct a ProtocolMessage.
125
126 Config & config() ;
127 ///< Exposes the configuration sub-object.
128
129 void nodnsbl( unsigned int seconds ) ;
130 ///< Clears the DNSBL configuration string for a period of time.
131
132 void enable( bool ) ;
133 ///< Disables or re-enables new SMTP sessions. When disabled new
134 ///< network connections are allowed but the SMTP protocol is
135 ///< disabled in some way.
136
137private: // overrides
138 std::unique_ptr<GNet::ServerPeer> newPeer( GNet::EventStateUnbound ,
139 GNet::ServerPeerInfo && , GNet::MultiServer::ServerInfo ) override ; // Override from GNet::MultiServer.
140
141public:
142 Server( const Server & ) = delete ;
143 Server( Server && ) = delete ;
144 Server & operator=( const Server & ) = delete ;
145 Server & operator=( Server && ) = delete ;
146
147private:
148 std::unique_ptr<Filter> newFilter( GNet::EventState ) const ;
149 std::unique_ptr<ProtocolMessage> newProtocolMessageStore( std::unique_ptr<Filter> ) ;
150 std::unique_ptr<ProtocolMessage> newProtocolMessageForward( GNet::EventState , std::unique_ptr<ProtocolMessage> ) ;
151 std::unique_ptr<ServerProtocol::Text> newProtocolText( bool , bool , const GNet::Address & , const std::string & domain ) const ;
152 Config serverConfig() const ;
153
154private:
155 GStore::MessageStore & m_store ;
156 FilterFactoryBase & m_ff ;
157 VerifierFactoryBase & m_vf ;
158 Config m_server_config ;
159 Client::Config m_client_config ;
160 const GAuth::SaslServerSecrets & m_server_secrets ;
161 std::string m_sasl_server_config ;
162 std::string m_forward_to ;
163 int m_forward_to_family ;
164 const GAuth::SaslClientSecrets & m_client_secrets ;
165 std::string m_sasl_client_config ;
166 G::Slot::Signal<const std::string&,const std::string&> m_event_signal ;
167 G::TimerTime m_dnsbl_suspend_time ;
168 bool m_enabled {true} ;
169} ;
170
171//| \class GSmtp::ServerPeer
172/// Handles a connection from a remote SMTP client.
173/// \see GSmtp::Server
174///
176{
177public:
178 G_EXCEPTION( Error , tx("smtp server error") )
179 G_EXCEPTION( SendError , tx("failed to send smtp response") )
180
182 bool enabled , VerifierFactoryBase & vf , const GAuth::SaslServerSecrets & server_secrets ,
183 const Server::Config & server_config , std::unique_ptr<ServerProtocol::Text> ptext ) ;
184 ///< Constructor.
185
186 ~ServerPeer() override ;
187 ///< Destructor.
188
189private: // overrides
190 void onSendComplete() override ; // GNet::ServerPeer
191 void onDelete( const std::string & reason ) override ; // GNet::ServerPeer
192 bool onReceive( const char * , std::size_t , std::size_t , std::size_t , char ) override ; // GNet::ServerPeer
193 void onSecure( const std::string & , const std::string & , const std::string & ) override ; // GNet::SocketProtocolSink
194 void protocolSecure() override ; // GSmtp::ServerSender
195 void protocolSend( const std::string & line , bool ) override ; // GSmtp::ServerSender
196 void protocolShutdown( int how ) override ; // GSmtp::ServerSender
197 void protocolExpect( std::size_t ) override ; // GSmtp::ServerSender
198 void onData( const char * , std::size_t ) override ; // GNet::ServerPeer
199
200public:
201 ServerPeer( const ServerPeer & ) = delete ;
202 ServerPeer( ServerPeer && ) = delete ;
203 ServerPeer & operator=( const ServerPeer & ) = delete ;
204 ServerPeer & operator=( ServerPeer && ) = delete ;
205
206private:
207 void onDnsBlockResult( bool ) ; // GNet::Dnsbl callback
208 void onCheckTimeout() ;
209 void onFlow( bool ) ;
210
211private:
212 Server & m_server ;
213 Server::Config m_server_config ;
214 GNet::Dnsbl m_block ;
215 GNet::Timer<ServerPeer> m_check_timer ;
216 std::unique_ptr<Verifier> m_verifier ;
217 std::unique_ptr<ProtocolMessage> m_pmessage ;
218 std::unique_ptr<ServerProtocol::Text> m_ptext ;
219 ServerProtocol m_protocol ;
220 ServerBufferIn m_input_buffer ;
221 std::string m_output_buffer ;
222 bool m_output_blocked {false} ;
223} ;
224
225inline GSmtp::Server::Config & GSmtp::Server::Config::set_allow_remote( bool b ) noexcept { allow_remote = b ; return *this ; }
226inline GSmtp::Server::Config & GSmtp::Server::Config::set_interfaces( const G::StringArray & a ) { interfaces = a ; return *this ; }
227inline GSmtp::Server::Config & GSmtp::Server::Config::set_port( unsigned int n ) noexcept { port = n ; return *this ; }
228inline GSmtp::Server::Config & GSmtp::Server::Config::set_ident( const std::string & s ) { ident = s ; return *this ; }
229inline GSmtp::Server::Config & GSmtp::Server::Config::set_anonymous( bool b ) noexcept { anonymous_smtp = anonymous_content = b ; return *this ; }
230inline GSmtp::Server::Config & GSmtp::Server::Config::set_anonymous_smtp( bool b ) noexcept { anonymous_smtp = b ; return *this ; }
231inline GSmtp::Server::Config & GSmtp::Server::Config::set_anonymous_content( bool b ) noexcept { anonymous_content = b ; return *this ; }
232inline GSmtp::Server::Config & GSmtp::Server::Config::set_filter_config( const Filter::Config & c ) { filter_config = c ; return *this ; }
233inline GSmtp::Server::Config & GSmtp::Server::Config::set_filter_spec( const FilterFactoryBase::Spec & r ) { filter_spec = r ; return *this ; }
234inline GSmtp::Server::Config & GSmtp::Server::Config::set_verifier_config( const Verifier::Config & c ) { verifier_config = c ; return *this ; }
235inline GSmtp::Server::Config & GSmtp::Server::Config::set_verifier_spec( const VerifierFactoryBase::Spec & r ) { verifier_spec = r ; return *this ; }
236inline GSmtp::Server::Config & GSmtp::Server::Config::set_net_server_peer_config( const GNet::ServerPeer::Config & c ) { net_server_peer_config = c ; return *this ; }
237inline GSmtp::Server::Config & GSmtp::Server::Config::set_net_server_config( const GNet::Server::Config & c ) { net_server_config = c ; return *this ; }
238inline GSmtp::Server::Config & GSmtp::Server::Config::set_protocol_config( const ServerProtocol::Config & c ) { protocol_config = c ; return *this ; }
239inline GSmtp::Server::Config & GSmtp::Server::Config::set_dnsbl_config( const std::string & s ) { dnsbl_config = s ; return *this ; }
240inline GSmtp::Server::Config & GSmtp::Server::Config::set_buffer_config( const ServerBufferIn::Config & c ) { buffer_config = c ; return *this ; }
241inline GSmtp::Server::Config & GSmtp::Server::Config::set_domain( const std::string & s ) { domain = s ; return *this ; }
242
243#endif
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
An interface used by GAuth::SaslServer to obtain authentication secrets.
A minimal bridge to GNet::DnsBlock.
Definition: gdnsbl.h:41
The EventStateUnbound class is used as a device to force factory methods to plumb-in an ExceptionSour...
Definition: geventstate.h:231
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
A server that listens on more than one address using a facade pattern to multiple GNet::Server instan...
Definition: gmultiserver.h:48
MultiServer(EventState es_listener, const G::StringArray &listen_list, unsigned int port, const std::string &server_type, ServerPeer::Config server_peer_config, Server::Config server_config)
Constructor.
A move-only structure used in GNet::Server::newPeer() and containing the new socket.
Definition: gserver.h:142
An abstract base class for the GNet::Server's connection to a remote client.
Definition: gserverpeer.h:59
A timer class template in which the timeout is delivered to the specified method.
Definition: gtimer.h:141
A class which acts as an SMTP client, sending messages to a remote SMTP server.
Definition: gsmtpclient.h:64
A factory interface for making GSmtp::Filter message processors.
An interface for processing a message file through a filter.
Definition: gfilter.h:51
An interface used by the ServerProtocol class to assemble and process an incoming message.
A helper class for GSmtp::ServerProtocol that does buffering of data received from the remote peer an...
Handles a connection from a remote SMTP client.
Definition: gsmtpserver.h:176
~ServerPeer() override
Destructor.
Definition: gsmtpserver.cpp:66
ServerPeer(GNet::EventStateUnbound, GNet::ServerPeerInfo &&peer_info, Server &server, bool enabled, VerifierFactoryBase &vf, const GAuth::SaslServerSecrets &server_secrets, const Server::Config &server_config, std::unique_ptr< ServerProtocol::Text > ptext)
Constructor.
Definition: gsmtpserver.cpp:36
Implements the SMTP server-side protocol.
An interface used by ServerProtocol to send protocol responses.
An SMTP server class.
Definition: gsmtpserver.h:55
void enable(bool)
Disables or re-enables new SMTP sessions.
void report(const std::string &group={}) const
Generates helpful diagnostics after construction.
Config & config()
Exposes the configuration sub-object.
Server(GNet::EventState es, GStore::MessageStore &, FilterFactoryBase &, VerifierFactoryBase &, const GAuth::SaslClientSecrets &, const GAuth::SaslServerSecrets &, const Config &server_config, const std::string &forward_to, int forward_to_family, const GSmtp::Client::Config &client_config)
Constructor.
std::unique_ptr< ProtocolMessage > newProtocolMessage(GNet::EventState)
Called by GSmtp::ServerPeer to construct a ProtocolMessage.
void nodnsbl(unsigned int seconds)
Clears the DNSBL configuration string for a period of time.
~Server() override
Destructor.
G::Slot::Signal< const std::string &, const std::string & > & eventSignal() noexcept
Returns a signal that indicates that something has happened.
A factory interface for addresss verifiers.
A class which allows SMTP messages to be stored and retrieved.
Definition: gmessagestore.h:73
SASL authentication classes.
Definition: gcram.cpp:38
Network classes.
Definition: gdef.h:1243
bool enabled() noexcept
Returns true if pop code is built in.
SMTP classes.
Definition: gadminserver.h:42
Message store classes.
Definition: genvelope.cpp:30
Low-level classes.
Definition: garg.h:36
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
STL namespace.
A configuration structure for GNet::ServerPeer.
Definition: gserverpeer.h:64
A configuration structure for GNet::Server.
Definition: gserver.h:56
A structure containing GSmtp::Client configuration parameters.
Definition: gsmtpclient.h:67
Filter specification tuple for GSmtp::FilterFactoryBase::newFilter().
Configuration passed to filter constructors.
Definition: gfilter.h:66
A configuration structure for GSmtp::ServerBufferIn.
A configuration structure for GSmtp::ServerProtocol.
A configuration structure for GSmtp::Server.
Definition: gsmtpserver.h:60
Verifier specification tuple for GSmtp::VerifierFactoryBase::newVerifier().
Configuration passed to address verifier constructors.
Definition: gverifier.h:57