E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gprotocolmessageforward.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gprotocolmessageforward.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsmtp.h"
23 #include "gprotocolmessageforward.h"
24 #include "gprotocolmessagestore.h"
25 #include "gnullfilter.h"
26 #include "gexecutablefilter.h"
27 #include "gmessagestore.h"
28 #include "gstr.h"
29 #include "gassert.h"
30 #include "glog.h"
31
32 GSmtp::ProtocolMessageForward::ProtocolMessageForward( MessageStore & store ,
33 unique_ptr<ProtocolMessage> pm ,
34 const GSmtp::Client::Config & client_config ,
35 const GAuth::Secrets & client_secrets , const std::string & server ) :
36 m_store(store) ,
37 m_client_location(server) ,
38 m_client_config(client_config) ,
39 m_client_secrets(client_secrets) ,
40 m_pm(pm.release()) ,
41 m_id(0) ,
42 m_done_signal(true) // one-shot, but reset()able
43 {
44 // signal plumbing to receive 'done' events
45 m_pm->doneSignal().connect( G::Slot::slot(*this,&ProtocolMessageForward::processDone) ) ;
46 m_client.doneSignal().connect( G::Slot::slot(*this,&ProtocolMessageForward::clientDone) ) ;
47 }
48
49 GSmtp::ProtocolMessageForward::~ProtocolMessageForward()
50 {
51 m_pm->doneSignal().disconnect() ;
52 m_client.doneSignal().disconnect() ;
53 if( m_client.get() != nullptr )
54 m_client->messageDoneSignal().disconnect() ;
55 }
56
57 G::Slot::Signal4<bool,unsigned long,std::string,std::string> & GSmtp::ProtocolMessageForward::storageDoneSignal()
58 {
59 return m_pm->doneSignal() ;
60 }
61
62 G::Slot::Signal4<bool,unsigned long,std::string,std::string> & GSmtp::ProtocolMessageForward::doneSignal()
63 {
64 return m_done_signal ;
65 }
66
67 void GSmtp::ProtocolMessageForward::reset()
68 {
69 m_pm->reset() ;
70 m_client.reset() ;
71 }
72
73 void GSmtp::ProtocolMessageForward::clear()
74 {
75 m_pm->clear() ;
76 }
77
78 bool GSmtp::ProtocolMessageForward::setFrom( const std::string & from , const std::string & from_auth )
79 {
80 return m_pm->setFrom( from , from_auth ) ;
81 }
82
83 bool GSmtp::ProtocolMessageForward::addTo( const std::string & to , VerifierStatus to_status )
84 {
85 return m_pm->addTo( to , to_status ) ;
86 }
87
88 void GSmtp::ProtocolMessageForward::addReceived( const std::string & line )
89 {
90 m_pm->addReceived( line ) ;
91 }
92
93 bool GSmtp::ProtocolMessageForward::addText( const char * line_data , size_t line_size )
94 {
95 return m_pm->addText( line_data , line_size ) ;
96 }
97
98 std::string GSmtp::ProtocolMessageForward::from() const
99 {
100 return m_pm->from() ;
101 }
102
103 void GSmtp::ProtocolMessageForward::process( const std::string & auth_id , const std::string & peer_socket_address ,
104 const std::string & peer_certificate )
105 {
106 m_done_signal.reset() ; // one-shot reset
107 m_pm->process( auth_id , peer_socket_address , peer_certificate ) ;
108 }
109
110 void GSmtp::ProtocolMessageForward::processDone( bool success , unsigned long id , std::string response , std::string reason )
111 {
112 G_DEBUG( "ProtocolMessageForward::processDone: " << (success?1:0) << " " << id << " [" << response << "] [" << reason << "]" ) ;
113 if( success && id != 0UL )
114 {
115 m_id = id ;
116
117 // the message is now stored -- start the forwarding using the Client object
118 bool nothing_to_do = false ;
119 std::string error = forward( id , nothing_to_do ) ;
120 if( !error.empty() || nothing_to_do )
121 {
122 // immediate failure or no recipients
123 m_done_signal.emit( success , id , "forwarding failed" , error ) ;
124 }
125 }
126 else
127 {
128 // filter fail-or-abandon, or message storage failed
129 m_done_signal.emit( success , id , response , reason ) ;
130 }
131 }
132
133 std::string GSmtp::ProtocolMessageForward::forward( unsigned long id , bool & nothing_to_do )
134 {
135 try
136 {
137 nothing_to_do = false ;
138 G_DEBUG( "GSmtp::ProtocolMessageForward::forward: forwarding message " << id ) ;
139
140 unique_ptr<StoredMessage> message = m_store.get( id ) ;
141
142 if( message->remoteRecipientCount() == 0U )
143 {
144 // use our local delivery mechanism, not the downstream server's
145 nothing_to_do = true ;
146 message->destroy() ; // (already copied to "*.local")
147 }
148 else
149 {
150 if( m_client.get() == nullptr )
151 {
152 m_client.reset( new Client(m_client_location,m_client_secrets,m_client_config) ) ;
153 m_client->messageDoneSignal().connect( G::Slot::slot(*this,&GSmtp::ProtocolMessageForward::messageDone) ) ;
154 }
155 m_client->sendMessage( unique_ptr<StoredMessage>(message.release()) ) ;
156 }
157 return std::string() ;
158 }
159 catch( std::exception & e ) // send forwarding errors back to the remote client via the server protocol
160 {
161 G_WARNING( "GSmtp::ProtocolMessageForward::forward: forwarding exception: " << e.what() ) ;
162 std::string e_what = e.what() ; if( e_what.empty() ) e_what = "exception" ;
163 return e_what ;
164 }
165 }
166
167 void GSmtp::ProtocolMessageForward::messageDone( std::string reason )
168 {
169 G_DEBUG( "GSmtp::ProtocolMessageForward::messageDone: \"" << reason << "\"" ) ;
170 const bool ok = reason.empty() ;
171 m_done_signal.emit( ok , m_id , ok?"":"forwarding failed" , reason ) ; // one-shot
172 }
173
174 void GSmtp::ProtocolMessageForward::clientDone( std::string reason )
175 {
176 G_DEBUG( "GSmtp::ProtocolMessageForward::clientDone: \"" << reason << "\"" ) ;
177 const bool ok = reason.empty() ;
178 m_done_signal.emit( ok , m_id , ok?"":"forwarding failed" , reason ) ; // one-shot
179 }
180
181 /// \file gprotocolmessageforward.cpp
gprotocolmessagestore.h
GSmtp::ProtocolMessageForward::ProtocolMessageForward
ProtocolMessageForward(MessageStore &store, unique_ptr< ProtocolMessage > pm, const GSmtp::Client::Config &client_config, const GAuth::Secrets &client_secrets, const std::string &remote_server_address)
Constructor.
Definition: gprotocolmessageforward.cpp:32
G::Slot::Signal4< bool, unsigned long, std::string, std::string >
glog.h
GSmtp::ProtocolMessageForward::storageDoneSignal
G::Slot::Signal4< bool, unsigned long, std::string, std::string > & storageDoneSignal()
Returns the signal which is used to signal that the storage is complete.
Definition: gprotocolmessageforward.cpp:57
GSmtp::StoredMessage::destroy
virtual void destroy()=0
Deletes the message within the store.
gexecutablefilter.h
GSmtp::ProtocolMessageForward::processDone
void processDone(bool, unsigned long, std::string, std::string)
Called by derived classes that have intercepted the storageDoneSignal() when their own post-storage p...
Definition: gprotocolmessageforward.cpp:110
GSmtp::ProtocolMessageForward::addTo
virtual bool addTo(const std::string &to_user, VerifierStatus to_status) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:83
gstr.h
gassert.h
GSmtp::MessageStore
A class which allows SMTP messages to be stored and retrieved.
Definition: gmessagestore.h:43
GAuth::Secrets
A simple interface for a store of secrets used in authentication.
Definition: gsecrets.h:40
GSmtp::ProtocolMessageForward::from
virtual std::string from() const override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:98
GSmtp::ProtocolMessageForward::process
virtual void process(const std::string &auth_id, const std::string &peer_socket_address, const std::string &peer_certificate) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:103
G::Slot::slot
Slot0 slot(T &object, void(T::*fn)())
A slot factory function overloaded for a zero-parameter callback.
Definition: gslot.h:209
gmessagestore.h
GSmtp::ProtocolMessageForward::setFrom
virtual bool setFrom(const std::string &from_user, const std::string &) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:78
GSmtp::Client::Config
A structure containing GSmtp::Client configuration parameters.
Definition: gsmtpclient.h:55
GSmtp::VerifierStatus
A structure returned by GSmtp::Verifier to describe the status of a 'rcpt-to' recipient.
Definition: gverifierstatus.h:51
GSmtp::ProtocolMessageForward::reset
virtual void reset() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:67
gsmtp.h
GSmtp::StoredMessage::remoteRecipientCount
virtual size_t remoteRecipientCount() const =0
Returns the number of non-local recipients.
GSmtp::ProtocolMessageForward::addText
virtual bool addText(const char *, size_t) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:93
gprotocolmessageforward.h
GSmtp::ProtocolMessageForward::addReceived
virtual void addReceived(const std::string &) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:88
GSmtp::ProtocolMessageForward::doneSignal
virtual G::Slot::Signal4< bool, unsigned long, std::string, std::string > & doneSignal() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:62
GSmtp::ProtocolMessageForward::clear
virtual void clear() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessageforward.cpp:73
gnullfilter.h
GSmtp::ProtocolMessageForward::~ProtocolMessageForward
virtual ~ProtocolMessageForward()
Destructor.
Definition: gprotocolmessageforward.cpp:49