gprotocolmessageforward.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 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"
24 #include "gprotocolmessagestore.h"
25 #include "gnullprocessor.h"
26 #include "gexecutableprocessor.h"
27 #include "gmessagestore.h"
28 #include "gmemory.h"
29 #include "gstr.h"
30 #include "gassert.h"
31 #include "glog.h"
32 
34  std::auto_ptr<ProtocolMessage> pm ,
35  const GSmtp::Client::Config & client_config ,
36  const GAuth::Secrets & client_secrets , const std::string & server ,
37  unsigned int connection_timeout ) :
38  m_store(store) ,
39  m_client_resolver_info(server) ,
40  m_client_config(client_config) ,
41  m_client_secrets(client_secrets) ,
42  m_pm(pm) ,
43  m_client(NULL,true) ,
44  m_id(0) ,
45  m_connection_timeout(connection_timeout) ,
46  m_done_signal(true) // one-shot, but reset()able
47 {
48  // signal plumbing to receive 'done' events
49  m_pm->doneSignal().connect( G::slot(*this,&ProtocolMessageForward::processDone) ) ;
50  m_client.doneSignal().connect( G::slot(*this,&ProtocolMessageForward::clientDone) ) ;
51 }
52 
54 {
55  m_pm->doneSignal().disconnect() ;
56  m_client.doneSignal().disconnect() ;
57  if( m_client.get() != NULL )
58  m_client->messageDoneSignal().disconnect() ;
59 }
60 
62 {
63  return m_pm->doneSignal() ;
64 }
65 
67 {
68  return m_done_signal ;
69 }
70 
72 {
73  m_pm->reset() ;
74  m_client.reset() ;
75 }
76 
78 {
79  m_pm->clear() ;
80 }
81 
82 bool GSmtp::ProtocolMessageForward::setFrom( const std::string & from )
83 {
84  return m_pm->setFrom( from ) ;
85 }
86 
87 bool GSmtp::ProtocolMessageForward::addTo( const std::string & to , VerifierStatus to_status )
88 {
89  return m_pm->addTo( to , to_status ) ;
90 }
91 
92 void GSmtp::ProtocolMessageForward::addReceived( const std::string & line )
93 {
94  m_pm->addReceived( line ) ;
95 }
96 
97 bool GSmtp::ProtocolMessageForward::addText( const std::string & line )
98 {
99  return m_pm->addText( line ) ;
100 }
101 
103 {
104  return m_pm->from() ;
105 }
106 
107 void GSmtp::ProtocolMessageForward::process( const std::string & auth_id , const std::string & peer_socket_address ,
108  const std::string & peer_socket_name , const std::string & peer_certificate )
109 {
110  m_done_signal.reset() ; // one-shot reset
111  m_pm->process( auth_id , peer_socket_address , peer_socket_name , peer_certificate ) ;
112 }
113 
114 void GSmtp::ProtocolMessageForward::processDone( bool success , unsigned long id , std::string reason )
115 {
116  G_DEBUG( "ProtocolMessageForward::processDone: " << (success?1:0) << ", " << id << ", \"" << reason << "\"" ) ;
117  if( success && id != 0UL )
118  {
119  m_id = id ;
120 
121  // the message is now stored -- start the forwarding using the Client object
122  bool nothing_to_do = false ;
123  success = forward( id , nothing_to_do , &reason ) ;
124  if( !success || nothing_to_do )
125  {
126  // immediate failure or no recipients
127  m_done_signal.emit( success , id , reason ) ;
128  }
129  }
130  else
131  {
132  // message storage failed or cancelled
133  m_done_signal.emit( success , id , reason ) ;
134  }
135 }
136 
137 bool GSmtp::ProtocolMessageForward::forward( unsigned long id , bool & nothing_to_do , std::string * reason_p )
138 {
139  try
140  {
141  nothing_to_do = false ;
142  *reason_p = std::string() ;
143  G_DEBUG( "GSmtp::ProtocolMessageForward::forward: forwarding message " << id ) ;
144 
145  std::auto_ptr<StoredMessage> message = m_store.get( id ) ;
146 
147  if( message->remoteRecipientCount() == 0U )
148  {
149  // use our local delivery mechanism, not the downstream server's
150  nothing_to_do = true ;
151  message->destroy() ; // (already copied to "*.local")
152  }
153  else
154  {
155  if( m_client.get() == NULL )
156  {
157  m_client.reset( new Client(m_client_resolver_info,m_client_secrets,m_client_config) ) ;
158  m_client->messageDoneSignal().connect( G::slot(*this,&GSmtp::ProtocolMessageForward::messageDone) ) ;
159  }
160  m_client->sendMessage( message ) ;
161  }
162  return true ;
163  }
164  catch( std::exception & e ) // send forwarding errors back to the remote client via the server protocol
165  {
166  if( reason_p != NULL )
167  {
168  G_DEBUG( "GSmtp::ProtocolMessageForward::forward: exception" ) ;
169  *reason_p = e.what() ;
170  }
171  return false ;
172  }
173 }
174 
175 void GSmtp::ProtocolMessageForward::messageDone( std::string reason )
176 {
177  G_DEBUG( "GSmtp::ProtocolMessageForward::clientDone: \"" << reason << "\"" ) ;
178  const bool ok = reason.empty() ;
179  m_done_signal.emit( ok , m_id , reason ) ; // one-shot
180 }
181 
182 void GSmtp::ProtocolMessageForward::clientDone( std::string reason , bool )
183 {
184  G_DEBUG( "GSmtp::ProtocolMessageForward::clientDone: \"" << reason << "\"" ) ;
185  const bool ok = reason.empty() ;
186  m_done_signal.emit( ok , m_id , reason ) ; // one-shot
187 }
188 
G::Signal3< bool, unsigned long, std::string > & storageDoneSignal()
Returns the signal which is used to signal that the storage is complete.
virtual bool addText(const std::string &)
Final override from GSmtp::ProtocolMessage.
void processDone(bool, unsigned long, std::string)
Called by derived classes that have intercepted the storageDoneSignal() when their own post-storage p...
virtual void clear()
Final override from GSmtp::ProtocolMessage.
virtual void addReceived(const std::string &)
Final override from GSmtp::ProtocolMessage.
Slot0 slot(T &object, void(T::*fn)())
Part of the slot/signal system.
Definition: gslot.h:156
virtual bool setFrom(const std::string &from_user)
Final override from GSmtp::ProtocolMessage.
A class which allows SMTP messages (envelope+content) to be stored and retrieved. ...
Definition: gmessagestore.h:45
A simple interface to a store of secrets as used in authentication.
Definition: gsecrets.h:44
G::Signal2< std::string, bool > & doneSignal()
Returns a signal which indicates that client processing is complete and the client instance has delet...
Definition: gclientptr.h:217
ProtocolMessageForward(MessageStore &store, std::auto_ptr< ProtocolMessage > pm, const GSmtp::Client::Config &client_config, const GAuth::Secrets &client_secrets, const std::string &server_address, unsigned int connection_timeout)
Constructor.
#define G_DEBUG(expr)
Definition: glog.h:95
A structure containing GSmtp::Client configuration parameters.
Definition: gsmtpclient.h:61
A structure returned by GSmtp::Verifier to describe the status of a rcpt-to recipient.
virtual G::Signal3< bool, unsigned long, std::string > & doneSignal()
Final override from GSmtp::ProtocolMessage.
virtual void process(const std::string &auth_id, const std::string &peer_socket_address, const std::string &peer_socket_name, const std::string &peer_certificate)
Final override from GSmtp::ProtocolMessage.
void connect(Slot2< P1, P2 > slot)
Definition: gslot.h:295
virtual std::string from() const
Final override from GSmtp::ProtocolMessage.
virtual bool addTo(const std::string &to_user, VerifierStatus to_status)
Final override from GSmtp::ProtocolMessage.
virtual void reset()
Final override from GSmtp::ProtocolMessage.
virtual ~ProtocolMessageForward()
Destructor.