E-MailRelay
gsmtpclient.h
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 gsmtpclient.h
19///
20
21#ifndef G_SMTP_CLIENT_H
22#define G_SMTP_CLIENT_H
23
24#include "gdef.h"
25#include "glocation.h"
26#include "gsaslclientsecrets.h"
27#include "glinebuffer.h"
28#include "gclient.h"
29#include "gclientptr.h"
30#include "gsmtpclientprotocol.h"
31#include "gmessagestore.h"
32#include "gstoredmessage.h"
33#include "gfilterfactorybase.h"
34#include "gfilter.h"
35#include "gcall.h"
36#include "gsocket.h"
37#include "gslot.h"
38#include "gtimer.h"
39#include "gstringarray.h"
40#include "gexception.h"
41#include <memory>
42#include <iostream>
43
44namespace GSmtp
45{
46 class Client ;
47 class ClientProtocol ;
48}
49
50//| \class GSmtp::Client
51/// A class which acts as an SMTP client, sending messages to a remote
52/// SMTP server.
53///
54/// A GSmtp::Client is-a GNet::Client so when it is destroyed as the
55/// result of an exception the owner should call GNet::Client::doOnDelete()
56/// (like GNet::ClientPtr does). The onDelete() implementation in this
57/// class fails the current message if the GNet::Client was not
58/// finish()ed (see quitAndFinish()) and the exception was not GNet::Done.
59///
60/// \see GSmtp::Forward
61///
63{
64public:
65 struct Config /// A structure containing GSmtp::Client configuration parameters.
66 {
67 GNet::StreamSocket::Config stream_socket_config ;
68 ClientProtocol::Config client_protocol_config ;
69 Filter::Config filter_config ;
70 FilterFactoryBase::Spec filter_spec ;
71 bool bind_local_address {false} ;
72 GNet::Address local_address ;
73 unsigned int connection_timeout {0U} ;
74 unsigned int secure_connection_timeout {0U} ;
75 bool secure_tunnel {false} ;
76 std::string sasl_client_config ;
77 std::string client_tls_profile ;
78 bool fail_if_no_remote_recipients {true} ; // used by GSmtp::Forward
79
80 Config() ;
81 Config & set_stream_socket_config( const GNet::StreamSocket::Config & ) ;
82 Config & set_client_protocol_config( const ClientProtocol::Config & ) ;
83 Config & set_filter_config( const Filter::Config & ) ;
84 Config & set_filter_spec( const FilterFactoryBase::Spec & ) ;
85 Config & set_bind_local_address( bool = true ) noexcept ;
86 Config & set_local_address( const GNet::Address & ) ;
87 Config & set_connection_timeout( unsigned int ) noexcept ;
88 Config & set_secure_connection_timeout( unsigned int ) noexcept ;
89 Config & set_secure_tunnel( bool = true ) noexcept ;
90 Config & set_sasl_client_config( const std::string & ) ;
91 Config & set_client_tls_profile( const std::string & ) ;
92 Config & set_fail_if_no_remote_recipients( bool = true ) noexcept ;
93 } ;
94
95 struct MessageDoneInfo /// Signal parameters for GNet::Client::messageDoneSignal()
96 {
97 int response_code ; // smtp response code, or 0 for an internal non-smtp error
98 std::string response ; // response text, empty iff sent successfully
99 bool filter_special ;
100 } ;
101
103 FilterFactoryBase & , const GNet::Location & remote ,
104 const GAuth::SaslClientSecrets & , const Config & config ) ;
105 ///< Constructor. Expects sendMessage() immediately after
106 ///< construction.
107 ///<
108 ///< A messageDoneSignal() is emitted when the message
109 ///< has been sent, allowing the next sendMessage().
110 ///< Use quitAndFinish() at the end.
111
112 ~Client() override ;
113 ///< Destructor.
114
115 void sendMessage( std::unique_ptr<GStore::StoredMessage> message ) ;
116 ///< Starts sending the given message. Cannot be called
117 ///< if there is a message already in the pipeline.
118 ///<
119 ///< The messageDoneSignal() is used to indicate that the
120 ///< message filtering has finished or failed.
121 ///<
122 ///< The message is fail()ed if it cannot be sent. If this
123 ///< Client object is deleted before the message is sent
124 ///< the message is neither fail()ed or destroy()ed.
125 ///<
126 ///< Does nothing if there are no message recipients.
127
128 void quitAndFinish() ;
129 ///< Finishes a sendMessage() sequence. Sends a QUIT command and
130 ///< finish()es the GNet::Client.
131
133 ///< Returns a signal that indicates that sendMessage()
134 ///< has completed or failed.
135
136private: // overrides
137 void onConnect() override ; // GNet::Client
138 bool onReceive( const char * , std::size_t , std::size_t , std::size_t , char ) override ; // GNet::Client
139 void onDelete( const std::string & ) override ; // GNet::Client
140 void onSendComplete() override ; // GNet::Client
141 void onSecure( const std::string & , const std::string & , const std::string & ) override ; // GNet::SocketProtocol
142 bool protocolSend( G::string_view , std::size_t , bool ) override ; // ClientProtocol::Sender
143
144public:
145 Client( const Client & ) = delete ;
146 Client( Client && ) = delete ;
147 Client & operator=( const Client & ) = delete ;
148 Client & operator=( Client && ) = delete ;
149
150private:
151 std::shared_ptr<GStore::StoredMessage> message() ;
152 void protocolDone( const ClientProtocol::DoneInfo & ) ; // GSmtp::ClientProtocol::doneSignal()
153 void filterStart() ;
154 void filterDone( int ) ;
155 bool ready() const ;
156 void start() ;
157 void messageFail( int = 0 , const std::string & = {} ) ;
158 void messageDestroy() ;
159 void onNoFilterTimeout() ;
160 static GNet::Client::Config netConfig( const Config & smtp_config ) ;
161
162private:
163 Config m_config ;
164 GNet::Timer<Client> m_nofilter_timer ;
165 std::shared_ptr<GStore::StoredMessage> m_message ;
166 std::unique_ptr<Filter> m_filter ;
167 ClientProtocol m_protocol ;
168 G::Slot::Signal<const MessageDoneInfo&> m_message_done_signal ;
169 bool m_secure ;
170 bool m_filter_special ;
171 G::CallStack m_stack ;
172} ;
173
174inline GSmtp::Client::Config & GSmtp::Client::Config::set_stream_socket_config( const GNet::StreamSocket::Config & c ) { stream_socket_config = c ; return *this ; }
175inline GSmtp::Client::Config & GSmtp::Client::Config::set_client_protocol_config( const ClientProtocol::Config & c ) { client_protocol_config = c ; return *this ; }
176inline GSmtp::Client::Config & GSmtp::Client::Config::set_filter_spec( const FilterFactoryBase::Spec & r ) { filter_spec = r ; return *this ; }
177inline GSmtp::Client::Config & GSmtp::Client::Config::set_filter_config( const Filter::Config & c ) { filter_config = c ; return *this ; }
178inline GSmtp::Client::Config & GSmtp::Client::Config::set_bind_local_address( bool b ) noexcept { bind_local_address = b ; return *this ; }
179inline GSmtp::Client::Config & GSmtp::Client::Config::set_local_address( const GNet::Address & a ) { local_address = a ; return *this ; }
180inline GSmtp::Client::Config & GSmtp::Client::Config::set_connection_timeout( unsigned int t ) noexcept { connection_timeout = t ; return *this ; }
181inline GSmtp::Client::Config & GSmtp::Client::Config::set_secure_connection_timeout( unsigned int t ) noexcept { secure_connection_timeout = t ; return *this ; }
182inline GSmtp::Client::Config & GSmtp::Client::Config::set_secure_tunnel( bool b ) noexcept { secure_tunnel = b ; return *this ; }
183inline GSmtp::Client::Config & GSmtp::Client::Config::set_sasl_client_config( const std::string & s ) { sasl_client_config = s ; return *this ; }
184inline GSmtp::Client::Config & GSmtp::Client::Config::set_client_tls_profile( const std::string & s ) { client_tls_profile = s ; return *this ; }
185inline GSmtp::Client::Config & GSmtp::Client::Config::set_fail_if_no_remote_recipients( bool b ) noexcept { fail_if_no_remote_recipients = b ; return *this ; }
186
187#endif
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
A class for making an outgoing connection to a remote server, with support for socket-level protocols...
Definition: gclient.h:76
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A class that represents the remote target for out-going client connections.
Definition: glocation.h:71
A timer class template in which the timeout is delivered to the specified method.
Definition: gtimer.h:141
An interface used by ClientProtocol to send protocol messages.
Implements the client-side SMTP protocol.
A class which acts as an SMTP client, sending messages to a remote SMTP server.
Definition: gsmtpclient.h:63
G::Slot::Signal< const MessageDoneInfo & > & messageDoneSignal() noexcept
Returns a signal that indicates that sendMessage() has completed or failed.
Definition: gsmtpclient.cpp:75
void quitAndFinish()
Finishes a sendMessage() sequence.
void sendMessage(std::unique_ptr< GStore::StoredMessage > message)
Starts sending the given message.
Definition: gsmtpclient.cpp:80
Client(GNet::ExceptionSink, FilterFactoryBase &, const GNet::Location &remote, const GAuth::SaslClientSecrets &, const Config &config)
Constructor.
Definition: gsmtpclient.cpp:35
~Client() override
Destructor.
Definition: gsmtpclient.cpp:51
A factory interface for making GSmtp::Filter message processors.
A linked list of CallFrame pointers.
Definition: gcall.h:59
SMTP classes.
Definition: gadminserver.h:42
Message store classes.
Definition: genvelope.cpp:30
Low-level classes.
Definition: garg.h:30
STL namespace.
A structure containing GNet::Client configuration parameters.
Definition: gclient.h:85
A configuration structure for GNet::StreamSocket.
Definition: gsocket.h:348
A structure containing GSmtp::ClientProtocol configuration parameters.
A structure containing GSmtp::Client configuration parameters.
Definition: gsmtpclient.h:66
Signal parameters for GNet::Client::messageDoneSignal()
Definition: gsmtpclient.h:96
Filter specification tuple for GSmtp::FilterFactoryBase::newFilter().
Configuration passed to filter constructors.
Definition: gfilter.h:66
A slot holder, with connect() and emit() methods.
Definition: gslot.h:184