E-MailRelay
gsmtpclient.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 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 "gstringview.h"
40#include "gstringarray.h"
41#include "gexception.h"
42#include <memory>
43#include <iostream>
44
45namespace GSmtp
46{
47 class Client ;
48 class ClientProtocol ;
49}
50
51//| \class GSmtp::Client
52/// A class which acts as an SMTP client, sending messages to a remote
53/// SMTP server.
54///
55/// A GSmtp::Client is-a GNet::Client so when it is destroyed as the
56/// result of an exception the owner should call GNet::Client::doOnDelete()
57/// (like GNet::ClientPtr does). The onDelete() implementation in this
58/// class fails the current message if the GNet::Client was not
59/// finish()ed (see quitAndFinish()) and the exception was not GNet::Done.
60///
61/// \see GSmtp::Forward
62///
64{
65public:
66 struct Config /// A structure containing GSmtp::Client configuration parameters.
67 {
68 ClientProtocol::Config client_protocol_config ;
69 GNet::Client::Config net_client_config ;
70 Filter::Config filter_config ;
71 FilterFactoryBase::Spec filter_spec ;
72 bool secure_tunnel {false} ;
73 std::string sasl_client_config ;
74 bool fail_if_no_remote_recipients {true} ; // used by GSmtp::Forward
75 bool log_msgid {false} ;
76 Config & set_client_protocol_config( const ClientProtocol::Config & ) ;
77 Config & set_net_client_config( const GNet::Client::Config & ) ;
78 Config & set_filter_config( const Filter::Config & ) ;
79 Config & set_filter_spec( const FilterFactoryBase::Spec & ) ;
80 Config & set_secure_tunnel( bool = true ) noexcept ;
81 Config & set_sasl_client_config( const std::string & ) ;
82 Config & set_fail_if_no_remote_recipients( bool = true ) noexcept ;
83 Config & set_log_msgid( bool = true ) noexcept ;
84 } ;
85
86 struct MessageDoneInfo /// Signal parameters for GNet::Client::messageDoneSignal()
87 {
88 int response_code ; // smtp response code, or 0 for an internal non-smtp error
89 std::string response ; // response text, empty iff sent successfully
90 bool filter_special ;
91 } ;
92
94 FilterFactoryBase & , const GNet::Location & remote ,
95 const GAuth::SaslClientSecrets & , const Config & config ) ;
96 ///< Constructor. Expects sendMessage() immediately after
97 ///< construction.
98 ///<
99 ///< A messageDoneSignal() is emitted when the message
100 ///< has been sent, allowing the next sendMessage().
101 ///< Use quitAndFinish() at the end.
102
103 ~Client() override ;
104 ///< Destructor.
105
106 void sendMessage( std::unique_ptr<GStore::StoredMessage> message ) ;
107 ///< Starts sending the given message. Cannot be called
108 ///< if there is a message already in the pipeline.
109 ///<
110 ///< The messageDoneSignal() is used to indicate that the
111 ///< message filtering has finished or failed.
112 ///<
113 ///< The message is fail()ed if it cannot be sent. If this
114 ///< Client object is deleted before the message is sent
115 ///< the message is neither fail()ed or destroy()ed.
116 ///<
117 ///< Does nothing if there are no message recipients.
118
119 void quitAndFinish() ;
120 ///< Finishes a sendMessage() sequence. Sends a QUIT command and
121 ///< finish()es the GNet::Client.
122
124 ///< Returns a signal that indicates that sendMessage()
125 ///< has completed or failed.
126
127 static std::string eventLoggingString( const GStore::StoredMessage * , const Config & ) ;
128 ///< Returns an event logging string for the given message.
129
130private: // overrides
131 void onConnect() override ; // GNet::Client
132 bool onReceive( const char * , std::size_t , std::size_t , std::size_t , char ) override ; // GNet::Client
133 void onDelete( const std::string & ) override ; // GNet::Client
134 void onSendComplete() override ; // GNet::Client
135 void onSecure( const std::string & , const std::string & , const std::string & ) override ; // GNet::SocketProtocol
136 bool protocolSend( std::string_view , std::size_t , bool ) override ; // ClientProtocol::Sender
137 std::string_view eventLoggingString() const noexcept override ; // GNet::EventLogging
138
139public:
140 Client( const Client & ) = delete ;
141 Client( Client && ) = delete ;
142 Client & operator=( const Client & ) = delete ;
143 Client & operator=( Client && ) = delete ;
144
145private:
146 GNet::EventState m_es ;
147 std::shared_ptr<GStore::StoredMessage> message() ;
148 void protocolDone( const ClientProtocol::DoneInfo & ) ; // GSmtp::ClientProtocol::doneSignal()
149 void filterStart() ;
150 void filterDone( int ) ;
151 bool ready() const ;
152 void start() ;
153 void messageFail( int = 0 , const std::string & = {} ) ;
154 void messageDestroy() ;
155 void onNoFilterTimeout() ;
156 static GNet::Client::Config normalise( GNet::Client::Config ) ;
157
158private:
159 Config m_config ;
160 GNet::Timer<Client> m_nofilter_timer ;
161 std::shared_ptr<GStore::StoredMessage> m_message ;
162 std::unique_ptr<Filter> m_filter ;
163 ClientProtocol m_protocol ;
164 G::Slot::Signal<const MessageDoneInfo&> m_message_done_signal ;
165 bool m_secure {false} ;
166 bool m_filter_special {false} ;
167 G::CallStack m_stack ;
168 std::string m_event_logging_string ;
169} ;
170
171inline GSmtp::Client::Config & GSmtp::Client::Config::set_client_protocol_config( const ClientProtocol::Config & c ) { client_protocol_config = c ; return *this ; }
172inline GSmtp::Client::Config & GSmtp::Client::Config::set_net_client_config( const GNet::Client::Config & c ) { net_client_config = c ; return *this ; }
173inline GSmtp::Client::Config & GSmtp::Client::Config::set_filter_spec( const FilterFactoryBase::Spec & r ) { filter_spec = r ; return *this ; }
174inline GSmtp::Client::Config & GSmtp::Client::Config::set_filter_config( const Filter::Config & c ) { filter_config = c ; return *this ; }
175inline GSmtp::Client::Config & GSmtp::Client::Config::set_secure_tunnel( bool b ) noexcept { secure_tunnel = b ; return *this ; }
176inline GSmtp::Client::Config & GSmtp::Client::Config::set_sasl_client_config( const std::string & s ) { sasl_client_config = s ; return *this ; }
177inline GSmtp::Client::Config & GSmtp::Client::Config::set_fail_if_no_remote_recipients( bool b ) noexcept { fail_if_no_remote_recipients = b ; return *this ; }
178inline GSmtp::Client::Config & GSmtp::Client::Config::set_log_msgid( bool b ) noexcept { log_msgid = b ; return *this ; }
179
180#endif
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
A class for making an outgoing connection to a remote server, with support for socket-level protocols...
Definition: gclient.h:78
An interface for GNet classes that define a logging context string.
Definition: geventlogging.h:47
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
A class that represents the remote target for out-going client connections.
Definition: glocation.h:70
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:64
G::Slot::Signal< const MessageDoneInfo & > & messageDoneSignal() noexcept
Returns a signal that indicates that sendMessage() has completed or failed.
Definition: gsmtpclient.cpp:62
void quitAndFinish()
Finishes a sendMessage() sequence.
void sendMessage(std::unique_ptr< GStore::StoredMessage > message)
Starts sending the given message.
Definition: gsmtpclient.cpp:67
~Client() override
Destructor.
Definition: gsmtpclient.cpp:50
Client(GNet::EventState, FilterFactoryBase &, const GNet::Location &remote, const GAuth::SaslClientSecrets &, const Config &config)
Constructor.
Definition: gsmtpclient.cpp:34
A factory interface for making GSmtp::Filter message processors.
A linked list of CallFrame pointers.
Definition: gcall.h:59
Network classes.
Definition: gdef.h:1243
SMTP classes.
Definition: gadminserver.h:42
Message store classes.
Definition: genvelope.cpp:30
STL namespace.
A structure containing GNet::Client configuration parameters.
Definition: gclient.h:87
A structure containing GSmtp::ClientProtocol configuration parameters.
A structure containing GSmtp::Client configuration parameters.
Definition: gsmtpclient.h:67
Signal parameters for GNet::Client::messageDoneSignal()
Definition: gsmtpclient.h:87
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