From 3f4011bcbf4ccf55edb8ea618fbf9b50f9e7bec9 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 17 Jun 2016 09:09:33 +0200 Subject: Initial version of the mailtransport resource --- .../mailtransportresource.cpp | 199 ++++++++++++++++++++- 1 file changed, 196 insertions(+), 3 deletions(-) (limited to 'examples/mailtransportresource/mailtransportresource.cpp') diff --git a/examples/mailtransportresource/mailtransportresource.cpp b/examples/mailtransportresource/mailtransportresource.cpp index 3b8dfd0..e8a15ee 100644 --- a/examples/mailtransportresource/mailtransportresource.cpp +++ b/examples/mailtransportresource/mailtransportresource.cpp @@ -20,6 +20,196 @@ #include "mailtransportresource.h" #include "facade.h" #include "facadefactory.h" +#include "resourceconfig.h" +#include "definitions.h" +#include "domainadaptor.h" +#include "sourcewriteback.h" +#include +#include +#include +#include +#include +#include + +#include "resultprovider.h" +#include "mailtransport.h" +#include "mail_generated.h" +#include +#include +#include +#include + +#define ENTITY_TYPE_MAIL "mail" + +using namespace Sink; + +class MimeMessageMover : public Sink::EntityPreprocessor +{ +public: + MimeMessageMover(const QByteArray &resourceInstanceIdentifier) : Sink::EntityPreprocessor(), mResourceInstanceIdentifier(resourceInstanceIdentifier) {} + + QString moveMessage(const QString &oldPath, const Sink::ApplicationDomain::Mail &mail) + { + const auto directory = Sink::resourceStorageLocation(mResourceInstanceIdentifier); + const auto filePath = directory + "/" + mail.identifier(); + if (oldPath != filePath) { + if (!QDir().mkpath(directory)) { + Warning() << "Failed to create the directory: " << directory; + } + QFile::remove(filePath); + QFile origFile(oldPath); + if (!origFile.open(QIODevice::ReadWrite)) { + Warning() << "Failed to open the original file with write rights: " << origFile.errorString(); + } + if (!origFile.rename(filePath)) { + Warning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString(); + } + origFile.close(); + return filePath; + } + return oldPath; + } + + void newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + if (!mail.getMimeMessagePath().isEmpty()) { + mail.setMimeMessagePath(moveMessage(mail.getMimeMessagePath(), mail)); + } + } + + void modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + if (!newMail.getMimeMessagePath().isEmpty()) { + newMail.setMimeMessagePath(moveMessage(newMail.getMimeMessagePath(), newMail)); + } + } + + void deletedEntity(const Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + QFile::remove(mail.getMimeMessagePath()); + } + QByteArray mResourceInstanceIdentifier; +}; + +static KAsync::Jobsend(const ApplicationDomain::Mail &mail, const MailtransportResource::Settings &settings) +{ + const auto data = mail.getMimeMessage(); + auto msg = KMime::Message::Ptr::create(); + msg->setHead(KMime::CRLFtoLF(data)); + msg->parse(); + if (settings.testMode) { + Log() << "I would totally send that mail, but I'm in test mode."; + } else { + if (MailTransport::sendMessage(msg, settings.server.toUtf8(), settings.username.toUtf8(), settings.password.toUtf8(), settings.cacert.toUtf8())) { + Log() << "Sent message successfully"; + } else { + Log() << "Failed to send message"; + return KAsync::error(1, "Failed to send the message."); + } + } + return KAsync::null(); +} + +//TODO fold into synchronizer +class MailtransportWriteback : public Sink::SourceWriteBack +{ +public: + MailtransportWriteback(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) : Sink::SourceWriteBack(resourceType, resourceInstanceIdentifier) + { + + } + + KAsync::Job replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId, const QList &changedProperties) Q_DECL_OVERRIDE + { + if (operation == Sink::Operation_Creation) { + Trace() << "Dispatching message."; + // return send(mail, mSettings); + } else if (operation == Sink::Operation_Removal) { + } else if (operation == Sink::Operation_Modification) { + } + return KAsync::null(); + } + +public: + MailtransportResource::Settings mSettings; +}; + +class MailtransportSynchronizer : public Sink::Synchronizer { +public: + MailtransportSynchronizer(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) + : Sink::Synchronizer(resourceType, resourceInstanceIdentifier) + { + + } + + KAsync::Job synchronizeWithSource() Q_DECL_OVERRIDE + { + Log() << " Synchronizing"; + return KAsync::start([this](KAsync::Future future) { + Sink::Query query; + QList toSend; + Log() << " Looking for mail"; + store().reader().query(query, [&](const ApplicationDomain::Mail &mail) -> bool { + Trace() << "Found mail: " << mail.identifier(); + // if (!mail.isSent()) { + toSend << mail; + // } + return true; + }); + auto job = KAsync::null(); + for (const auto &m : toSend) { + job = job.then(send(m, mSettings)).then([]() { + //on success, mark the mail as sent and move it to a separate place + //TODO + }); + } + job = job.then([&future]() { + future.setFinished(); + }, + [&future](int errorCode, const QString &errorString) { + future.setFinished(); + }); + job.exec(); + }); + } + +public: + QByteArray mResourceInstanceIdentifier; + MailtransportResource::Settings mSettings; +}; + +MailtransportResource::MailtransportResource(const QByteArray &instanceIdentifier, const QSharedPointer &pipeline) + : Sink::GenericResource(PLUGIN_NAME, instanceIdentifier, pipeline) +{ + auto config = ResourceConfig::getConfiguration(instanceIdentifier); + mSettings = {config.value("server").toString(), + config.value("username").toString(), + config.value("cacert").toString(), + config.value("password").toString(), + config.value("testmode").toBool() + }; + + auto synchronizer = QSharedPointer::create(PLUGIN_NAME, instanceIdentifier); + synchronizer->mSettings = mSettings; + setupSynchronizer(synchronizer); + + auto changereplay = QSharedPointer::create(PLUGIN_NAME, instanceIdentifier); + changereplay->mSettings = mSettings; + setupChangereplay(changereplay); + + setupPreprocessors(ENTITY_TYPE_MAIL, QVector() << new MimeMessageMover(mResourceInstanceIdentifier)); +} + +void MailtransportResource::removeFromDisk(const QByteArray &instanceIdentifier) +{ + GenericResource::removeFromDisk(instanceIdentifier); + Sink::Storage(Sink::storageLocation(), instanceIdentifier + ".synchronization", Sink::Storage::ReadWrite).removeFromDisk(); +} + +KAsync::Job MailtransportResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) +{ + return KAsync::null(); +} MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent) : Sink::ResourceFactory(parent) @@ -29,12 +219,15 @@ MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent) Sink::Resource *MailtransportResourceFactory::createResource(const QByteArray &instanceIdentifier) { - ErrorMsg() << "The mailtransport resource has no synchronizer process: " << instanceIdentifier; - return nullptr; + return new MailtransportResource(instanceIdentifier); } void MailtransportResourceFactory::registerFacades(Sink::FacadeFactory &factory) { - factory.registerFacade(PLUGIN_NAME); + factory.registerFacade>>(PLUGIN_NAME); } +void MailtransportResourceFactory::registerAdaptorFactories(Sink::AdaptorFactoryRegistry ®istry) +{ + registry.registerFactory>(PLUGIN_NAME); +} -- cgit v1.2.3