/* * Copyright (C) 2015 Christian Mollekopf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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 "inspection.h" #include #include #include #include #include #include #define ENTITY_TYPE_MAIL "mail" using namespace Sink; //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), mResourceInstanceIdentifier(resourceInstanceIdentifier) { } 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." << mail.identifier(); auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/"; Trace() << path; QDir dir; dir.mkpath(path); QFile f(path+ mail.identifier()); f.open(QIODevice::ReadWrite); f.write("foo"); f.close(); } 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(); } 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.getSent()) { toSend << mail; } return true; }); auto job = KAsync::null(); for (const auto &m : toSend) { job = job.then(send(m, mSettings)).then([this, m]() { auto modifiedMail = ApplicationDomain::Mail(mResourceInstanceIdentifier, m.identifier(), m.revision(), QSharedPointer::create()); modifiedMail.setSent(true); modify(modifiedMail); //TODO copy to a sent mail folder as well }); } 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 << new MailPropertyExtractor << new DefaultIndexUpdater); } 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) { if (domainType == ENTITY_TYPE_MAIL) { if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/" + entityId; if (QFileInfo::exists(path)) { return KAsync::null(); } return KAsync::error(1, "Couldn't find message: " + path); } } return KAsync::null(); } MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent) : Sink::ResourceFactory(parent) { } Sink::Resource *MailtransportResourceFactory::createResource(const QByteArray &instanceIdentifier) { return new MailtransportResource(instanceIdentifier); } void MailtransportResourceFactory::registerFacades(Sink::FacadeFactory &factory) { factory.registerFacade>>(PLUGIN_NAME); } void MailtransportResourceFactory::registerAdaptorFactories(Sink::AdaptorFactoryRegistry ®istry) { registry.registerFactory>(PLUGIN_NAME); }