E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gprotocolmessagestore.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 // gprotocolmessagestore.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsmtp.h"
23 #include "gprotocolmessagestore.h"
24 #include "gmessagestore.h"
25 #include "gstr.h"
26 #include "gassert.h"
27 #include "glog.h"
28
29 GSmtp::ProtocolMessageStore::ProtocolMessageStore( MessageStore & store , unique_ptr<Filter> filter ) :
30 m_store(store) ,
31 m_filter(filter.release())
32 {
33 m_filter->doneSignal().connect( G::Slot::slot(*this,&ProtocolMessageStore::filterDone) ) ;
34 }
35
36 GSmtp::ProtocolMessageStore::~ProtocolMessageStore()
37 {
38 m_filter->doneSignal().disconnect() ;
39 }
40
41 void GSmtp::ProtocolMessageStore::reset()
42 {
43 G_DEBUG( "GSmtp::ProtocolMessageStore::reset" ) ;
44 clear() ;
45 }
46
47 void GSmtp::ProtocolMessageStore::clear()
48 {
49 G_DEBUG( "GSmtp::ProtocolMessageStore::clear" ) ;
50 m_new_msg.reset() ;
51 m_from.erase() ;
52 m_filter->cancel() ;
53 }
54
55 bool GSmtp::ProtocolMessageStore::setFrom( const std::string & from , const std::string & from_auth )
56 {
57 G_DEBUG( "GSmtp::ProtocolMessageStore::setFrom: " << from ) ;
58
59 if( from.length() == 0U ) // => probably a failure notification message
60 G_WARNING( "GSmtp::ProtocolMessageStore: empty MAIL-FROM return path" ) ;
61
62 G_ASSERT( m_new_msg.get() == nullptr ) ;
63 clear() ; // just in case
64
65 m_new_msg.reset( m_store.newMessage(from,from_auth,"").release() ) ;
66
67 m_from = from ;
68 return true ; // accept any name
69 }
70
71 bool GSmtp::ProtocolMessageStore::addTo( const std::string & to , VerifierStatus to_status )
72 {
73 G_DEBUG( "GSmtp::ProtocolMessageStore::addTo: " << to ) ;
74
75 G_ASSERT( m_new_msg.get() != nullptr ) ;
76 if( to.length() > 0U && m_new_msg.get() != nullptr )
77 {
78 if( !to_status.is_valid )
79 {
80 G_WARNING( "GSmtp::ProtocolMessage: rejecting recipient \"" << to << "\": "
81 << to_status.response << (to_status.reason.empty()?"":": ") << to_status.reason ) ;
82 return false ;
83 }
84 else
85 {
86 m_new_msg->addTo( to_status.address , to_status.is_local ) ;
87 return true ;
88 }
89 }
90 else
91 {
92 return false ;
93 }
94 }
95
96 void GSmtp::ProtocolMessageStore::addReceived( const std::string & received_line )
97 {
98 G_DEBUG( "GSmtp::ProtocolMessageStore::addReceived" ) ;
99 if( m_new_msg.get() != nullptr )
100 m_new_msg->addTextLine( received_line ) ;
101 }
102
103 bool GSmtp::ProtocolMessageStore::addText( const char * line_data , size_t line_size )
104 {
105 G_ASSERT( m_new_msg.get() != nullptr ) ;
106 if( m_new_msg.get() == nullptr )
107 return true ;
108 return m_new_msg->addText( line_data , line_size ) ;
109 }
110
111 std::string GSmtp::ProtocolMessageStore::from() const
112 {
113 return m_new_msg.get() ? m_from : std::string() ;
114 }
115
116 void GSmtp::ProtocolMessageStore::process( const std::string & session_auth_id , const std::string & peer_socket_address ,
117 const std::string & peer_certificate )
118 {
119 try
120 {
121 G_DEBUG( "GSmtp::ProtocolMessageStore::process: \"" << session_auth_id << "\", \"" << peer_socket_address << "\"" ) ;
122 G_ASSERT( m_new_msg.get() != nullptr ) ;
123 if( m_new_msg.get() == nullptr )
124 throw G::Exception( "internal error" ) ; // never gets here
125
126 // write ".new" envelope
127 std::string message_location = m_new_msg->prepare( session_auth_id , peer_socket_address , peer_certificate ) ;
128
129 // start the filter
130 if( !m_filter->simple() )
131 G_LOG( "GSmtp::ProtocolMessageStore::process: filter start: [" << m_filter->id() << "] [" << message_location << "]" ) ;
132 m_filter->start( message_location ) ;
133 }
134 catch( std::exception & e ) // catch filtering errors
135 {
136 G_WARNING( "GSmtp::ProtocolMessageStore::process: message processing exception: " << e.what() ) ;
137 clear() ;
138 m_done_signal.emit( false , 0UL , "failed" , e.what() ) ;
139 }
140 }
141
142 void GSmtp::ProtocolMessageStore::filterDone( int filter_result )
143 {
144 try
145 {
146 G_DEBUG( "GSmtp::ProtocolMessageStore::filterDone: " << filter_result ) ;
147 G_ASSERT( m_new_msg.get() != nullptr ) ;
148 if( m_new_msg.get() == nullptr )
149 throw G::Exception( "internal error" ) ; // never gets here
150
151 const bool ok = filter_result == 0 ;
152 const bool abandon = filter_result == 1 ;
153 const bool rescan = m_filter->special() ;
154 G_ASSERT( m_filter->reason().empty() == (ok || abandon) ) ; // filter post-condition
155
156 if( !m_filter->simple() )
157 G_LOG( "GSmtp::ProtocolMessageStore::filterDone: filter done: " << m_filter->str(true) ) ;
158
159 unsigned long id = 0UL ;
160 if( ok )
161 {
162 // commit the message to the store
163 m_new_msg->commit( true ) ;
164 id = m_new_msg->id() ;
165 }
166 else if( abandon )
167 {
168 // make a token effort to commit the message
169 // but ignore errors and dont set the id
170 m_new_msg->commit( false ) ;
171 }
172 else
173 {
174 G_LOG_S( "GSmtp::ProtocolMessageStore::filterDone: rejected by filter: [" << m_filter->reason() << "]" ) ;
175 }
176
177 if( rescan )
178 {
179 // pick up any new messages create by the filter
180 m_store.rescan() ;
181 }
182
183 std::string filter_response = m_filter->response() ;
184 std::string filter_reason = m_filter->reason() ;
185 clear() ;
186 G_DEBUG( "GSmtp::ProtocolMessageStore::filterDone: emiting done signal" ) ;
187 m_done_signal.emit( ok || abandon , id , filter_response , filter_reason ) ;
188 }
189 catch( std::exception & e ) // catch filtering errors
190 {
191 G_WARNING( "GSmtp::ProtocolMessageStore::filterDone: filter exception: " << e.what() ) ;
192 clear() ;
193 m_done_signal.emit( false , 0UL , "rejected" , e.what() ) ;
194 }
195 }
196
197 G::Slot::Signal4<bool,unsigned long,std::string,std::string> & GSmtp::ProtocolMessageStore::doneSignal()
198 {
199 return m_done_signal ;
200 }
201
202 /// \file gprotocolmessagestore.cpp
gprotocolmessagestore.h
G::Slot::Signal4< bool, unsigned long, std::string, std::string >
glog.h
GSmtp::ProtocolMessageStore::reset
virtual void reset() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:41
GSmtp::ProtocolMessageStore::doneSignal
virtual G::Slot::Signal4< bool, unsigned long, std::string, std::string > & doneSignal() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:197
GSmtp::ProtocolMessageStore::addTo
virtual bool addTo(const std::string &to_user, VerifierStatus to_status) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:71
GSmtp::ProtocolMessageStore::from
virtual std::string from() const override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:111
gstr.h
gassert.h
GSmtp::MessageStore
A class which allows SMTP messages to be stored and retrieved.
Definition: gmessagestore.h:43
GSmtp::ProtocolMessageStore::setFrom
virtual bool setFrom(const std::string &from_user, const std::string &) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:55
G::Slot::slot
Slot0 slot(T &object, void(T::*fn)())
A slot factory function overloaded for a zero-parameter callback.
Definition: gslot.h:209
GSmtp::ProtocolMessageStore::ProtocolMessageStore
ProtocolMessageStore(MessageStore &store, unique_ptr< Filter >)
Constructor.
Definition: gprotocolmessagestore.cpp:29
GSmtp::ProtocolMessageStore::~ProtocolMessageStore
virtual ~ProtocolMessageStore()
Destructor.
Definition: gprotocolmessagestore.cpp:36
gmessagestore.h
GSmtp::ProtocolMessageStore::clear
virtual void clear() override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:47
GSmtp::ProtocolMessageStore::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: gprotocolmessagestore.cpp:116
GSmtp::ProtocolMessageStore::addReceived
virtual void addReceived(const std::string &) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:96
GSmtp::VerifierStatus
A structure returned by GSmtp::Verifier to describe the status of a 'rcpt-to' recipient.
Definition: gverifierstatus.h:51
G::Exception
A general-purpose exception class derived from std::exception and containing a std::string.
Definition: gexception.h:43
gsmtp.h
GSmtp::ProtocolMessageStore::addText
virtual bool addText(const char *, size_t) override
Override from GSmtp::ProtocolMessage.
Definition: gprotocolmessagestore.cpp:103