33 #include <vmime/platforms/posix/posixHandler.hpp>
39 bool EMailSmtpService::_run(
false);
47 EMailSmtpService::EMailSmtpService()
48 : _config(daemon::Configuration::getInstance().getEMail()),
49 _storage(dtn::core::
BundleCore::getInstance().getStorage()),
50 _certificateVerifier(vmime::create<vmime::security::cert::defaultCertificateVerifier>())
57 vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();
67 vmime::ref<vmime::net::session> session =
68 vmime::create<vmime::net::session>();
71 _transport = session->getTransport(vmime::utility::url(url));
74 _transport->setProperty(
"options.need-authentication",
78 _transport->setProperty(
"server.port", _config.
getSmtpPort());
83 _transport->setProperty(
"connection.tls",
true);
84 _transport->setProperty(
"connection.tls.required",
true);
88 _transport->setTimeoutHandlerFactory(vmime::create<TimeoutHandlerFactory>());
93 _transport->setCertificateVerifier(_certificateVerifier);
95 }
catch (vmime::exception &e) {
100 _threadMutex.
enter();
107 EMailSmtpService::~EMailSmtpService()
114 while(!_queue.
empty()) {
115 Task *t = _queue.
front();
127 _threadMutex.
enter();
149 }
catch(std::exception &e) {
152 if(dynamic_cast<vmime::exceptions::authentication_error*>(&e) != NULL)
157 else if(dynamic_cast<vmime::exceptions::connection_error*>(&e) != NULL)
171 _threadMutex.
leave();
186 _threadMutex.
leave();
189 void EMailSmtpService::connect()
192 _transport->connect();
195 bool EMailSmtpService::isConnected()
197 return _transport->isConnected();
200 void EMailSmtpService::disconnect()
203 _transport->disconnect();
206 void EMailSmtpService::loadCerificates()
208 std::vector<std::string> certPath;
210 std::vector<vmime::ref <vmime::security::cert::X509Certificate> > ca;
212 if(!certPath.empty()) {
213 for(std::vector<std::string>::iterator it = certPath.begin() ; it != certPath.end(); ++it)
216 ca.push_back(loadCertificateFromFile((*it)));
217 }
catch(InvalidCertificate &e) {
221 _certificateVerifier->setX509RootCAs(ca);
225 std::vector<vmime::ref <vmime::security::cert::X509Certificate> > user;
227 if(!certPath.empty()) {
228 for(std::vector<std::string>::iterator it = certPath.begin() ; it != certPath.end(); ++it)
231 user.push_back(loadCertificateFromFile((*it)));
232 }
catch(InvalidCertificate &e) {
236 _certificateVerifier->setX509TrustedCerts(user);
240 vmime::ref<vmime::security::cert::X509Certificate> EMailSmtpService::loadCertificateFromFile(
const std::string &path)
242 std::ifstream certFile;
243 certFile.open(path.c_str(), std::ios::in | std::ios::binary);
246 throw(InvalidCertificate(
"Unable to find certificate at \"" + path +
"\""));
250 vmime::utility::inputStreamAdapter is(certFile);
251 vmime::ref<vmime::security::cert::X509Certificate> cert;
252 cert = vmime::security::cert::X509Certificate::import(is);
257 throw(InvalidCertificate(
"The certificate at \"" + path +
"\" does not seem to be PEM or DER encoded"));
270 _threadMutex.
leave();
275 _threadMutex.
leave();
278 void EMailSmtpService::submit(Task *t)
288 vmime::ref<vmime::message> msg = vmime::create <vmime::message>();
289 vmime::ref<vmime::header> header = msg->getHeader();
290 vmime::ref<vmime::body> body = msg->getBody();
293 vmime::headerFieldFactory* hfFactory =
294 vmime::headerFieldFactory::getInstance();
297 header->appendField(hfFactory->create(vmime::fields::FROM,
300 header->appendField(hfFactory->create(vmime::fields::TO,
303 header->appendField(hfFactory->create(vmime::fields::SUBJECT,
304 "Bundle for " + t->getNode().getEID().getString()));
307 header->appendField(hfFactory->create(
"Bundle-EMailCL-Version",
"1"));
308 header->appendField(hfFactory->create(
"Bundle-Flags",
310 header->appendField(hfFactory->create(
"Bundle-Destination",
312 header->appendField(hfFactory->create(
"Bundle-Source",
314 header->appendField(hfFactory->create(
"Bundle-Report-To",
316 header->appendField(hfFactory->create(
"Bundle-Custodian",
318 header->appendField(hfFactory->create(
"Bundle-Creation-Time",
320 header->appendField(hfFactory->create(
"Bundle-Sequence-Number",
322 header->appendField(hfFactory->create(
"Bundle-Lifetime",
326 header->appendField(hfFactory->create(
"Bundle-Fragment-Offset",
328 header->appendField(hfFactory->create(
"Bundle-Total-Application-Data-Unit-Length",
333 unsigned int additionalBlocks = 0;
336 if(bundle.
size() > 0)
337 header->appendField(hfFactory->create(
"MIME-Version",
"1.0"));
345 header->appendField(hfFactory->create(
"Bundle-Payload-Flags",
346 toString(getProcFlags(payload))));
347 header->appendField(hfFactory->create(
"Bundle-Payload-Block-Length",
349 header->appendField(hfFactory->create(
"Bundle-Payload-Data-Name",
354 std::stringstream ss;
357 vmime::ref<vmime::utility::inputStream> dataStream =
358 vmime::create<vmime::utility::inputStreamStringAdapter>(ss.str());
360 vmime::ref<vmime::attachment> payloadAttachement =
361 vmime::create<vmime::fileAttachment>(
363 vmime::word(
"payload.data"),
364 vmime::mediaType(
"application/octet-stream")
366 vmime::attachmentHelper::addAttachment(msg, payloadAttachement);
368 }
catch(
const std::bad_cast&) {};
375 std::stringstream attachment;
379 vmime::ref<vmime::utility::inputStream> dataStream =
380 vmime::create<vmime::utility::inputStreamStringAdapter>(attachment.str());
382 vmime::ref<vmime::attachment> extensionAttachement =
383 vmime::create<vmime::fileAttachment>(
385 vmime::word(
"block-" + toString(additionalBlocks) +
".data"),
386 vmime::mediaType(
"application/octet-stream")
389 vmime::attachmentHelper::addAttachment(msg, extensionAttachement);
392 vmime::ref<vmime::header> extensionHeader = msg->getBody()->getPartAt(msg->getBody()->getPartCount()-1)->getHeader();
393 std::stringstream ss;
396 extensionHeader->appendField(hfFactory->create(
"Block-Type", ss.str()));
398 extensionHeader->appendField(hfFactory->create(
"Block-Processing-Flags",
399 toString(getProcFlags(block))));
405 for(Block::eid_list::const_iterator eidIt = eids.begin(); eidIt != eids.end(); eidIt++)
407 extensionHeader->appendField(hfFactory->create(
"Block-EID-Reference",
408 (*eidIt).getString()));
413 header->appendField(hfFactory->create(
"Bundle-Additional-Block",
414 "block-" + toString(additionalBlocks++) +
".data"));
416 }
catch(
const std::bad_cast&) {};
419 _transport->send(msg);
422 IBRCOMMON_LOGGER(
info) <<
"EMail Convergence Layer: Bundle " << t->getJob().getBundle().toString() <<
" for node " << t->getNode().getEID().getString() <<
" submitted via smtp" <<
IBRCOMMON_LOGGER_ENDL;
427 unsigned int out = 0;
447 std::string EMailSmtpService::toString(
int i)
449 std::stringstream ss;
455 : _node(node), _job(job), _recipient(recipient), _timesChecked(0) {}
479 bool EMailSmtpService::TimeoutHandler::isTimeOut()
484 return (getTime() >= last +
488 void EMailSmtpService::TimeoutHandler::resetTimeOut()
493 bool EMailSmtpService::TimeoutHandler::handleTimeOut()