21#ifndef G_SMTP_CLIENT_PROTOCOL_H
22#define G_SMTP_CLIENT_PROTOCOL_H
43 class ClientProtocol ;
52 G_EXCEPTION( NotReady ,
tx(
"not ready") )
53 G_EXCEPTION( TlsError ,
tx(
"tls/ssl error") )
54 G_EXCEPTION( BadSelector ,
tx(
"no client authentication account") )
55 G_EXCEPTION_CLASS( SmtpError ,
tx(
"smtp error") )
60 virtual bool protocolSend( std::string_view , std::size_t offset ,
bool go_secure ) = 0 ;
80 unsigned int response_timeout {0U} ;
81 unsigned int ready_timeout {0U} ;
82 bool use_starttls_if_possible {
false} ;
83 bool must_use_tls {
false} ;
84 bool authentication_fallthrough {
false} ;
85 bool anonymous{
false} ;
86 bool must_accept_all_recipients {
false} ;
87 bool eightbit_strict {
false} ;
88 bool binarymime_strict {
false} ;
89 bool smtputf8_strict {
false} ;
90 bool pipelining {
false} ;
92 std::size_t bdat_chunk_size {1000000} ;
93 bool crlf_only {
false} ;
94 bool try_reauthentication {
false} ;
96 Config & set_ehlo(
const std::string & ) ;
97 Config & set_response_timeout(
unsigned int ) noexcept ;
98 Config & set_ready_timeout(
unsigned int ) noexcept ;
99 Config & set_use_starttls_if_possible(
bool =
true ) noexcept ;
100 Config & set_must_use_tls(
bool =
true ) noexcept ;
101 Config & set_authentication_fallthrough(
bool =
true ) noexcept ;
102 Config & set_anonymous(
bool =
true ) noexcept ;
103 Config & set_must_accept_all_recipients(
bool =
true ) noexcept ;
104 Config & set_eightbit_strict(
bool =
true ) noexcept ;
105 Config & set_binarymime_strict(
bool =
true ) noexcept ;
106 Config & set_smtputf8_strict(
bool =
true ) noexcept ;
107 Config & set_pipelining(
bool =
true ) noexcept ;
108 Config & set_reply_size_limit( std::size_t ) noexcept ;
109 Config & set_crlf_only(
bool =
true ) noexcept ;
110 Config & set_try_reauthentication(
bool =
true ) noexcept ;
116 std::string response ;
123 const Config & config ,
bool in_secure_tunnel ) ;
169 bool apply( const
std::
string & rx ) ;
182 void onTimeout() override ;
209 bool has_starttls {
false} ;
210 bool has_auth {
false} ;
212 bool has_8bitmime {
false} ;
213 bool has_binarymime {
false} ;
214 bool has_chunking {
false} ;
215 bool has_pipelining {
false} ;
216 bool has_smtputf8 {
false} ;
221 std::weak_ptr<GStore::StoredMessage> ptr ;
223 std::string selector ;
224 std::size_t content_size {0U} ;
225 std::size_t to_index {0U} ;
226 std::size_t to_accepted {0U} ;
228 std::size_t chunk_data_size {0U} ;
229 std::string chunk_data_size_str ;
235 bool authenticated {
false} ;
236 std::string client_ehlo ;
237 std::string auth_selector ;
238 std::string auth_mechanism ;
239 bool ok(
const std::string & s )
const
241 return !authenticated || auth_selector == s ;
246 State state {State::Init} ;
248 std::size_t replySize()
const ;
252 using BodyType = GStore::MessageStore::BodyType ;
254 std::string_view checkSendable() ;
255 bool endOfContent() ;
256 bool applyEvent(
const ClientReply & event ) ;
257 void raiseDoneSignal(
int ,
const std::string & ,
const std::string & = {} ) ;
258 void startFiltering() ;
262 void sendCommandLines(
const std::string & ) ;
264 void send( std::string_view ) ;
265 void send( std::string_view , std::string_view , std::string_view = {} , std::string_view = {} ,
bool = false ) ;
266 std::size_t sendContentLines() ;
267 bool sendNextContentLine( std::string & ) ;
270 bool sendMailFrom() ;
272 bool sendBdatAndChunk( std::size_t ,
const std::string & ,
bool ) ;
274 bool sendContentLineImp(
const std::string & , std::size_t ) ;
275 void sendChunkImp(
const char * , std::size_t ) ;
276 bool sendImp( std::string_view , std::size_t sensitive_from = std::string::npos ) ;
280 std::unique_ptr<GAuth::SaslClient> m_sasl ;
282 const bool m_in_secure_tunnel ;
283 bool m_eightbit_warned {
false} ;
284 bool m_binarymime_warned {
false} ;
285 bool m_utf8_warned {
false} ;
288 Protocol m_protocol ;
289 MessageState m_message_state ;
291 std::vector<char> m_message_buffer ;
292 std::string m_message_line ;
293 SessionState m_session ;
297inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_response_timeout(
unsigned int t )
noexcept { response_timeout =
t ;
return *this ; }
298inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_ready_timeout(
unsigned int t )
noexcept { ready_timeout =
t ;
return *this ; }
299inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_use_starttls_if_possible(
bool b )
noexcept { use_starttls_if_possible = b ;
return *this ; }
300inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_must_use_tls(
bool b )
noexcept { must_use_tls = b ;
return *this ; }
301inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_authentication_fallthrough(
bool b )
noexcept { authentication_fallthrough = b ;
return *this ; }
303inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_must_accept_all_recipients(
bool b )
noexcept { must_accept_all_recipients = b ;
return *this ; }
304inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_eightbit_strict(
bool b )
noexcept { eightbit_strict = b ;
return *this ; }
305inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_binarymime_strict(
bool b )
noexcept { binarymime_strict = b ;
return *this ; }
306inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_smtputf8_strict(
bool b )
noexcept { smtputf8_strict = b ;
return *this ; }
308inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_reply_size_limit( std::size_t n )
noexcept { reply_size_limit = n ;
return *this ; }
310inline GSmtp::ClientProtocol::Config & GSmtp::ClientProtocol::Config::set_try_reauthentication(
bool b )
noexcept { try_reauthentication = b ;
return *this ; }
An interface used by GAuth::SaslClient to obtain a client id and its authentication secret.
A class that implements the client-side SASL challenge/response concept.
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
An interface used by GNet::TimerList to keep track of pending timeouts and to deliver timeout events.
G::TimerTime t() const
Used by TimerList to get the expiry epoch time.
An interface used by ClientProtocol to send protocol messages.
virtual ~Sender()=default
Destructor.
virtual bool protocolSend(std::string_view, std::size_t offset, bool go_secure)=0
Called by the Protocol class to send network data to the peer.
Implements the client-side SMTP protocol.
ClientProtocol(GNet::EventState, Sender &sender, const GAuth::SaslClientSecrets &secrets, const std::string &sasl_client_config, const Config &config, bool in_secure_tunnel)
Constructor.
void start(std::weak_ptr< GStore::StoredMessage >)
Starts transmission of the given message.
void reconfigure(const std::string &ehlo)
Updates a configuration parameter after construction.
void secure()
To be called when the secure socket protocol has been successfully established.
void finish()
Called after the last message has been sent.
void filterDone(Filter::Result result, const std::string &response, const std::string &reason)
To be called when the Filter interface has done its thing.
G::Slot::Signal< const DoneInfo & > & doneSignal() noexcept
Returns a signal that is raised once the protocol has finished with a given message.
G::Slot::Signal & filterSignal() noexcept
Returns a signal that is raised when the protocol needs to do message filtering.
void sendComplete()
To be called when a blocked connection becomes unblocked.
bool apply(const std::string &rx)
Called on receipt of a line of text from the remote server.
An interface for processing a message file through a filter.
An abstract interface for messages which have come from the store.
std::vector< std::string > StringArray
A std::vector of std::strings.
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Result structure returned from GAuth::SaslClient::response.
A structure containing GSmtp::ClientProtocol configuration parameters.
Parameters for GSmtp::ClientProtocol::doneSignal()
A set of compile-time buffer sizes.
A slot holder, with connect() and emit() methods.