From f5185c4799fe0e9c31a218dfc8310515ac921c2b Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 9 Mar 2016 15:20:31 +0100 Subject: Moved framework/mail to framework/domain --- framework/CMakeLists.txt | 5 +- framework/domain/CMakeLists.txt | 32 ++ framework/domain/actions/mailactions.cpp | 48 ++ framework/domain/actions/sinkactions.cpp | 106 ++++ framework/domain/composer.cpp | 199 ++++++++ framework/domain/composer.h | 93 ++++ framework/domain/csshelper.cpp | 64 +++ framework/domain/csshelper.h | 44 ++ framework/domain/data/mail.css | 298 +++++++++++ framework/domain/folderlistcontroller.cpp | 69 +++ framework/domain/folderlistcontroller.h | 56 +++ framework/domain/folderlistmodel.cpp | 65 +++ framework/domain/folderlistmodel.h | 50 ++ framework/domain/maillistcontroller.cpp | 101 ++++ framework/domain/maillistcontroller.h | 61 +++ framework/domain/maillistmodel.cpp | 149 ++++++ framework/domain/maillistmodel.h | 66 +++ framework/domain/mailplugin.cpp | 40 ++ framework/domain/mailplugin.h | 33 ++ framework/domain/mailtemplates.cpp | 804 ++++++++++++++++++++++++++++++ framework/domain/mailtemplates.h | 28 ++ framework/domain/mailtransport.cpp | 160 ++++++ framework/domain/mailtransport.h | 28 ++ framework/domain/messageparser.cpp | 76 +++ framework/domain/messageparser.h | 51 ++ framework/domain/objecttreesource.cpp | 144 ++++++ framework/domain/objecttreesource.h | 57 +++ framework/domain/qmldir | 3 + framework/domain/retriever.cpp | 55 ++ framework/domain/retriever.h | 55 ++ framework/domain/singlemailcontroller.cpp | 46 ++ framework/domain/singlemailcontroller.h | 49 ++ framework/domain/stringhtmlwriter.cpp | 145 ++++++ framework/domain/stringhtmlwriter.h | 70 +++ framework/mail/CMakeLists.txt | 32 -- framework/mail/actions/mailactions.cpp | 48 -- framework/mail/actions/sinkactions.cpp | 106 ---- framework/mail/composer.cpp | 199 -------- framework/mail/composer.h | 93 ---- framework/mail/csshelper.cpp | 64 --- framework/mail/csshelper.h | 44 -- framework/mail/data/mail.css | 298 ----------- framework/mail/folderlistcontroller.cpp | 69 --- framework/mail/folderlistcontroller.h | 56 --- framework/mail/folderlistmodel.cpp | 65 --- framework/mail/folderlistmodel.h | 50 -- framework/mail/maillistcontroller.cpp | 101 ---- framework/mail/maillistcontroller.h | 61 --- framework/mail/maillistmodel.cpp | 149 ------ framework/mail/maillistmodel.h | 66 --- framework/mail/mailplugin.cpp | 40 -- framework/mail/mailplugin.h | 33 -- framework/mail/mailtemplates.cpp | 804 ------------------------------ framework/mail/mailtemplates.h | 28 -- framework/mail/mailtransport.cpp | 160 ------ framework/mail/mailtransport.h | 28 -- framework/mail/messageparser.cpp | 76 --- framework/mail/messageparser.h | 51 -- framework/mail/objecttreesource.cpp | 144 ------ framework/mail/objecttreesource.h | 57 --- framework/mail/qmldir | 3 - framework/mail/retriever.cpp | 55 -- framework/mail/retriever.h | 55 -- framework/mail/singlemailcontroller.cpp | 46 -- framework/mail/singlemailcontroller.h | 49 -- framework/mail/stringhtmlwriter.cpp | 145 ------ framework/mail/stringhtmlwriter.h | 70 --- 67 files changed, 3349 insertions(+), 3346 deletions(-) create mode 100644 framework/domain/CMakeLists.txt create mode 100644 framework/domain/actions/mailactions.cpp create mode 100644 framework/domain/actions/sinkactions.cpp create mode 100644 framework/domain/composer.cpp create mode 100644 framework/domain/composer.h create mode 100644 framework/domain/csshelper.cpp create mode 100644 framework/domain/csshelper.h create mode 100644 framework/domain/data/mail.css create mode 100644 framework/domain/folderlistcontroller.cpp create mode 100644 framework/domain/folderlistcontroller.h create mode 100644 framework/domain/folderlistmodel.cpp create mode 100644 framework/domain/folderlistmodel.h create mode 100644 framework/domain/maillistcontroller.cpp create mode 100644 framework/domain/maillistcontroller.h create mode 100644 framework/domain/maillistmodel.cpp create mode 100644 framework/domain/maillistmodel.h create mode 100644 framework/domain/mailplugin.cpp create mode 100644 framework/domain/mailplugin.h create mode 100644 framework/domain/mailtemplates.cpp create mode 100644 framework/domain/mailtemplates.h create mode 100644 framework/domain/mailtransport.cpp create mode 100644 framework/domain/mailtransport.h create mode 100644 framework/domain/messageparser.cpp create mode 100644 framework/domain/messageparser.h create mode 100644 framework/domain/objecttreesource.cpp create mode 100644 framework/domain/objecttreesource.h create mode 100644 framework/domain/qmldir create mode 100644 framework/domain/retriever.cpp create mode 100644 framework/domain/retriever.h create mode 100644 framework/domain/singlemailcontroller.cpp create mode 100644 framework/domain/singlemailcontroller.h create mode 100644 framework/domain/stringhtmlwriter.cpp create mode 100644 framework/domain/stringhtmlwriter.h delete mode 100644 framework/mail/CMakeLists.txt delete mode 100644 framework/mail/actions/mailactions.cpp delete mode 100644 framework/mail/actions/sinkactions.cpp delete mode 100644 framework/mail/composer.cpp delete mode 100644 framework/mail/composer.h delete mode 100644 framework/mail/csshelper.cpp delete mode 100644 framework/mail/csshelper.h delete mode 100644 framework/mail/data/mail.css delete mode 100644 framework/mail/folderlistcontroller.cpp delete mode 100644 framework/mail/folderlistcontroller.h delete mode 100644 framework/mail/folderlistmodel.cpp delete mode 100644 framework/mail/folderlistmodel.h delete mode 100644 framework/mail/maillistcontroller.cpp delete mode 100644 framework/mail/maillistcontroller.h delete mode 100644 framework/mail/maillistmodel.cpp delete mode 100644 framework/mail/maillistmodel.h delete mode 100644 framework/mail/mailplugin.cpp delete mode 100644 framework/mail/mailplugin.h delete mode 100644 framework/mail/mailtemplates.cpp delete mode 100644 framework/mail/mailtemplates.h delete mode 100644 framework/mail/mailtransport.cpp delete mode 100644 framework/mail/mailtransport.h delete mode 100644 framework/mail/messageparser.cpp delete mode 100644 framework/mail/messageparser.h delete mode 100644 framework/mail/objecttreesource.cpp delete mode 100644 framework/mail/objecttreesource.h delete mode 100644 framework/mail/qmldir delete mode 100644 framework/mail/retriever.cpp delete mode 100644 framework/mail/retriever.h delete mode 100644 framework/mail/singlemailcontroller.cpp delete mode 100644 framework/mail/singlemailcontroller.h delete mode 100644 framework/mail/stringhtmlwriter.cpp delete mode 100644 framework/mail/stringhtmlwriter.h (limited to 'framework') diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 1955d709..be137441 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -34,8 +34,11 @@ enable_testing() set(SINK_RESOURCE_PLUGINS_PATH ${QT_PLUGIN_INSTALL_DIR}/sink/resources) -add_subdirectory(mail) +# The actions framework add_subdirectory(actions) +# The settings framework add_subdirectory(settings) +# Domain specific domain logic +add_subdirectory(domain) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt new file mode 100644 index 00000000..822b2981 --- /dev/null +++ b/framework/domain/CMakeLists.txt @@ -0,0 +1,32 @@ +set(mailplugin_SRCS + mailplugin.cpp + maillistcontroller.cpp + maillistmodel.cpp + singlemailcontroller.cpp + folderlistmodel.cpp + folderlistcontroller.cpp + actions/sinkactions.cpp + actions/mailactions.cpp + objecttreesource.cpp + stringhtmlwriter.cpp + csshelper.cpp + composer.cpp + messageparser.cpp + mailtransport.cpp + mailtemplates.cpp + retriever.cpp +) +add_definitions(-DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") + +find_package(CURL 7.20.0 REQUIRED) + +include_directories(${CURL_INCLUDE_DIRS}) + +add_library(mailplugin SHARED ${mailplugin_SRCS}) + +qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets) + +target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::Otp KF5::Codecs ${CURL_LIBRARIES}) + +install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail) +install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail) diff --git a/framework/domain/actions/mailactions.cpp b/framework/domain/actions/mailactions.cpp new file mode 100644 index 00000000..dab0533e --- /dev/null +++ b/framework/domain/actions/mailactions.cpp @@ -0,0 +1,48 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include +#include + +#include "../mailtransport.h" +#include +#include +#include +#include + +using namespace Kube; + +static ActionHandlerHelper sendMailHandler("org.kde.kube.actions.sendmail", + [](Context *context) -> bool { + auto username = context->property("username").value(); + auto password = context->property("password").value(); + auto server = context->property("server").value(); + auto message = context->property("message").value(); + return !username.isEmpty() && !password.isEmpty() && !server.isEmpty() && message; + }, + [](Context *context) { + auto username = context->property("username").value(); + auto password = context->property("password").value(); + auto server = context->property("server").value(); + //For ssl use "smtps://mainserver.example.net + QByteArray cacert; // = "/path/to/certificate.pem"; + auto message = context->property("message").value(); + qWarning() << "Sending a mail: "; + MailTransport::sendMessage(message, server, username, password, cacert); + } +); diff --git a/framework/domain/actions/sinkactions.cpp b/framework/domain/actions/sinkactions.cpp new file mode 100644 index 00000000..a19ab149 --- /dev/null +++ b/framework/domain/actions/sinkactions.cpp @@ -0,0 +1,106 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include +#include + +#include + +using namespace Kube; + +static ActionHandlerHelper markAsReadHandler("org.kde.kube.actions.mark-as-read", + [](Context *context) -> bool { + return context->property("mail").isValid(); + }, + [](Context *context) { + auto mail = context->property("mail").value(); + if (!mail) { + qWarning() << "Failed to get the mail mail: " << context->property("mail"); + return; + } + mail->setProperty("unread", false); + qDebug() << "Mark as read " << mail->identifier(); + Sink::Store::modify(*mail).exec(); + } +); + +static ActionHandlerHelper deleteHandler("org.kde.kube.actions.delete", + [](Context *context) -> bool { + return context->property("mail").isValid(); + }, + [](Context *context) { + auto mail = context->property("mail").value(); + if (!mail) { + qWarning() << "Failed to get the mail mail: " << context->property("mail"); + return; + } + mail->setProperty("unread", false); + qDebug() << "Remove " << mail->identifier(); + Sink::Store::remove(*mail).exec(); + } +); + +static ActionHandlerHelper synchronizeHandler("org.kde.kube.actions.synchronize", + [](Context *context) -> bool { + return context->property("folder").isValid(); + }, + [](Context *context) { + auto folder = context->property("folder").value(); + if (!folder) { + qWarning() << "Failed to get the folder: " << context->property("folder"); + return; + } + Sink::Store::synchronize(Sink::Query::ResourceFilter(folder->resourceInstanceIdentifier())).exec(); + } +); + +// static ActionHandlerHelper saveAsDraft("org.kde.kube.actions.save-as-draft", +// [](Context *context) -> bool { +// return context->property("mail").isValid(); +// }, +// [](Context *context) { +// Sink::Query query; +// query += Sink::Query::RequestedProperties(QByteArrayList() << "name") +// //FIXME do something like specialuse? +// query += Sink::Query::PropertyFilter("name", "Drafts"); +// // query += Sink::Query::PropertyContainsFilter("specialuser", "drafts"); +// query += Sink::Query::PropertyFilter("drafts", true); +// //TODO Use drafts folder of that specific account +// Sink::Store::fetchAll(query) +// .then>([](const QList folders) { +// if (folders.isEmpty()) { +// return KAsync::start([]() { +// //If message is already existing, modify, otherwise create +// }); +// } +// }); +// //TODO +// // * Find drafts folder +// // * Store KMime::Message on disk for use in blob property +// // * Check if message is already existing and either create or update +// // * +// // auto mail = context->property("mail").value(); +// // if (!mail) { +// // qWarning() << "Failed to get the mail mail: " << context->property("mail"); +// // return; +// // } +// // mail->setProperty("unread", false); +// // qDebug() << "Mark as read " << mail->identifier(); +// // Sink::Store::modify(*mail).exec(); +// } +// ); diff --git a/framework/domain/composer.cpp b/framework/domain/composer.cpp new file mode 100644 index 00000000..2f4fe2e9 --- /dev/null +++ b/framework/domain/composer.cpp @@ -0,0 +1,199 @@ +/* + Copyright (c) 2016 Michael Bohlender + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + + +#include "composer.h" +#include +#include +#include +#include +#include +#include +#include + +#include "mailtemplates.h" + +Composer::Composer(QObject *parent) : QObject(parent) +{ + m_identityModel << "Kuberich " << "Uni " << "Spam "; +} + +QString Composer::to() const +{ + return m_to; +} + +void Composer::setTo(const QString &to) +{ + if(m_to != to) { + m_to = to; + emit toChanged(); + } +} + +QString Composer::cc() const +{ + return m_cc; +} + +void Composer::setCc(const QString &cc) +{ + if(m_cc != cc) { + m_cc = cc; + emit ccChanged(); + } +} + +QString Composer::bcc() const +{ + return m_bcc; +} + +void Composer::setBcc(const QString &bcc) +{ + if(m_bcc != bcc) { + m_bcc = bcc; + emit bccChanged(); + } +} + +QString Composer::subject() const +{ + return m_subject; +} + +void Composer::setSubject(const QString &subject) +{ + if(m_subject != subject) { + m_subject = subject; + emit subjectChanged(); + } +} + +QString Composer::body() const +{ + return m_body; +} + +void Composer::setBody(const QString &body) +{ + if(m_body != body) { + m_body = body; + emit bodyChanged(); + } +} + +QStringList Composer::identityModel() const +{ + return m_identityModel; +} + +int Composer::fromIndex() const +{ + return m_fromIndex; +} + +void Composer::setFromIndex(int fromIndex) +{ + if(m_fromIndex != fromIndex) { + m_fromIndex = fromIndex; + emit fromIndexChanged(); + } +} + +QVariant Composer::originalMessage() const +{ + return m_originalMessage; +} + +void Composer::setOriginalMessage(const QVariant &originalMessage) +{ + const auto mailData = KMime::CRLFtoLF(originalMessage.toByteArray()); + if (!mailData.isEmpty()) { + KMime::Message::Ptr mail(new KMime::Message); + mail->setContent(mailData); + mail->parse(); + auto reply = MailTemplates::reply(mail); + //We assume reply + setTo(reply->to(true)->asUnicodeString()); + setCc(reply->cc(true)->asUnicodeString()); + setSubject(reply->subject(true)->asUnicodeString()); + setBody(reply->body()); + m_msg = QVariant::fromValue(reply); + } else { + m_msg = QVariant(); + } +} + +KMime::Message::Ptr Composer::assembleMessage() +{ + auto mail = m_msg.value(); + if (!mail) { + mail = KMime::Message::Ptr::create(); + } + for (const auto &to : KEmailAddress::splitAddressList(m_to)) { + QByteArray displayName; + QByteArray addrSpec; + QByteArray comment; + KEmailAddress::splitAddress(to.toUtf8(), displayName, addrSpec, comment); + mail->to(true)->addAddress(addrSpec, displayName); + } + mail->subject(true)->fromUnicodeString(m_subject, "utf-8"); + mail->setBody(m_body.toUtf8()); + mail->assemble(); + return mail; +} + +void Composer::send() +{ + auto mail = assembleMessage(); + Kube::ApplicationContext settings; + auto account = settings.currentAccount(); + auto identity = account.primaryIdentity(); + auto transport = identity.transport(); + + Kube::Context context; + context.setProperty("message", QVariant::fromValue(mail)); + + context.setProperty("username", transport.username()); + context.setProperty("password", transport.password()); + context.setProperty("server", transport.server()); + + Kube::Action("org.kde.kube.actions.sendmail", context).execute(); + clear(); +} + +void Composer::saveAsDraft() +{ + auto mail = assembleMessage(); + Kube::Context context; + context.setProperty("message", QVariant::fromValue(mail)); + Kube::Action("org.kde.kube.actions.saveasdraft", context).execute(); + clear(); +} + +void Composer::clear() +{ + setSubject(""); + setBody(""); + setTo(""); + setCc(""); + setBcc(""); + setFromIndex(-1); +} diff --git a/framework/domain/composer.h b/framework/domain/composer.h new file mode 100644 index 00000000..dd066b2e --- /dev/null +++ b/framework/domain/composer.h @@ -0,0 +1,93 @@ +/* + Copyright (c) 2016 Michael Bohlender + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include +#include +#include + +namespace KMime { +class Message; +} + +class Composer : public QObject +{ + Q_OBJECT + Q_PROPERTY (QVariant originalMessage READ originalMessage WRITE setOriginalMessage) + Q_PROPERTY (QString to READ to WRITE setTo NOTIFY toChanged) + Q_PROPERTY (QString cc READ cc WRITE setCc NOTIFY ccChanged) + Q_PROPERTY (QString bcc READ bcc WRITE setBcc NOTIFY bccChanged) + Q_PROPERTY (QString subject READ subject WRITE setSubject NOTIFY subjectChanged) + Q_PROPERTY (QString body READ body WRITE setBody NOTIFY bodyChanged) + Q_PROPERTY (QStringList identityModel READ identityModel) + Q_PROPERTY (int fromIndex READ fromIndex WRITE setFromIndex NOTIFY fromIndexChanged) + +public: + explicit Composer(QObject *parent = Q_NULLPTR); + + QString to() const; + void setTo(const QString &to); + + QString cc() const; + void setCc(const QString &cc); + + QString bcc() const; + void setBcc(const QString &bcc); + + QString subject() const; + void setSubject(const QString &subject); + + QString body() const; + void setBody(const QString &body); + + QStringList identityModel() const; + + int fromIndex() const; + void setFromIndex(int fromIndex); + + QVariant originalMessage() const; + void setOriginalMessage(const QVariant &originalMessage); + +signals: + void subjectChanged(); + void bodyChanged(); + void toChanged(); + void ccChanged(); + void bccChanged(); + void fromIndexChanged(); + +public slots: + void send(); + void saveAsDraft(); + void clear(); + +private: + QSharedPointer assembleMessage(); + QString m_to; + QString m_cc; + QString m_bcc; + QString m_subject; + QString m_body; + QStringList m_identityModel; + int m_fromIndex; + QVariant m_originalMessage; + QVariant m_msg; +}; diff --git a/framework/domain/csshelper.cpp b/framework/domain/csshelper.cpp new file mode 100644 index 00000000..a6355c57 --- /dev/null +++ b/framework/domain/csshelper.cpp @@ -0,0 +1,64 @@ +/* + csshelper.cpp + + This file is part of KMail, the KDE mail client. + Copyright (c) 2003 Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "csshelper.h" + +#include +#include +#include +#include +#include +#include + +CSSHelper::CSSHelper(const QPaintDevice *pd) : + MessageViewer::CSSHelperBase(pd) +{ + +} + +QString cssDefinitions() +{ + QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + "mail.css"); + if (file.open(QFile::ReadOnly)) { + return file.readAll(); + } + return QString(); +} + +QString CSSHelper::htmlHead(bool fixed) const +{ + return + QLatin1String("\n" + "\n" + "\n"); +} \ No newline at end of file diff --git a/framework/domain/csshelper.h b/framework/domain/csshelper.h new file mode 100644 index 00000000..775014e3 --- /dev/null +++ b/framework/domain/csshelper.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- + csshelper.h + + This file is part of KMail, the KDE mail client. + Copyright (c) 2003 Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#pragma once + +#include + +class CSSHelper : public MessageViewer::CSSHelperBase +{ +public: + explicit CSSHelper(const QPaintDevice *pd); + + /** @return HTML head including style sheet definitions and the + >body< tag */ + QString htmlHead(bool fixedFont = false) const Q_DECL_OVERRIDE; +}; \ No newline at end of file diff --git a/framework/domain/data/mail.css b/framework/domain/data/mail.css new file mode 100644 index 00000000..b77e36ee --- /dev/null +++ b/framework/domain/data/mail.css @@ -0,0 +1,298 @@ +div.header { + margin-bottom: 10pt ! important; +} + +table.textAtm { + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +tr.textAtmH, +tr.textAtmB, +tr.rfc822B { + font-weight: normal ! important; +} + +tr.signInProgressH, +tr.rfc822H, +tr.encrH, +tr.signOkKeyOkH, +tr.signOkKeyBadH, +tr.signWarnH, +tr.sign +ErrH { + font-weight: bold ! important; +} + +tr.textAtmH td, +tr.textAtmB td { + padding: 3px ! important; +} + +table.rfc822 { + width: 100% ! important; + border: solid 1px black ! important; + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +table.textAtm, +table.encr, +table.signWarn, +table.signErr, +table.signOkKeyBad, +table.signOkKeyOk, +table.signInProgress, +div.fancy.header table { + width: 100% ! important; + border-width: 0px ! important; + line-height: normal; +} + +div.htmlWarn { + margin: 0px 5% ! important; + padding: 10px ! important; + text-align: left ! important; + line-height: normal; +} + +div.fancy.header > div { + font-weight: bold ! important; + padding: 4px ! important; + line-height: normal; +} + +div.fancy.header table { + padding: 2px ! important; + text-align: left ! important; + border-collapse: separate ! important; +} + +div.fancy.header table th { + font-family: "Helvetica" ! important; + font-size: 12pt; + padding: 0px ! important; + white-space: nowrap ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + background-color: #efebe7 ! important; + color: #000000 ! important; + border: 1px ! important; +} + +div.fancy.header table td { + font-family: "Helvetica" ! important; + font-size: 12pt; + padding: 0px ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + width: 100% ! important; + background-color: #efebe7 ! important; + color: #000000 ! important; + border: 1px ! important; +} + +div.fancy.header table a:hover { + background-color: transparent ! important; +} + +span.pimsmileytext { + position: absolute; + top: 0px; + left: 0px; + visibility: hidden; +} + +img.pimsmileyimg { +} + +div.quotelevelmark { + position: absolute; + margin-left:-10px; +} + +body { + font-family: "Helvetica" ! important; + font-size: 12pt; + color: #000000 ! important; + background-color: #ffffff ! important; +} + +a { + color: #0000cc ! important; + text-decoration: none ! important; +} + +a.white { + color: white ! important; +} + +a.black { + color: black ! important; +} + +table.textAtm { background-color: #000000 ! important; } + +tr.textAtmH { + background-color: #ffffff ! important; + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +tr.textAtmB { + background-color: #ffffff ! important; +} + +table.signInProgress, +table.rfc822 { + background-color: #ffffff ! important +; +} + +tr.signInProgressH, +tr.rfc822H { + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +table.encr { + background-color: #0010cc ! important; +} + +tr.encrH { + background-color: #1010ee ! important; + color: #aaaaaa ! important; + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +tr.encrB { background-color: #ffe0e0 ! important; } + +table.signOkKeyOk { + background-color: #00cc00 ! important; +} + +tr.signOkKeyOkH { + background-color: #00ff00 ! important; + color: #000000 ! important; + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +tr.signOkKeyOkB { background-color: #e0ffe0 ! important; } + +table.signOkKeyBad { + background-color: #00cc00 ! important; +} + +tr.signOkKeyBadH { + background-color: #00ff00 ! important; + color: #000000 ! important; + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +tr.signOkKeyBadB { background-color: #e0ffe0 ! important; } + +table.signWarn { + background-color: #cc0 ! important; +} + +tr.signWarnH { + background-color: #fc0 ! important; + color: #000000 ! important; + font-family: "Helvetica" ! imp +ortant; + font-size: 12pt; +} + +tr.signWarnB { background-color: #e0e0ff ! important; } + +table.signErr { + background-color: #c00 ! important; +} + +tr.signErrH { + background-color: #0f00 ! important; + color: #0000 +00 ! important; + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +tr.signErrB { background-color: #d3d3f0 ! important; } + +div.htmlWarn { + border: 2px solid #00001a ! important; + line-height: normal; +} + +div.header { + font-family: "Helvetica" ! important; + font-size: 12pt; +} + +div.fancy.header > div { + background-color: #308cc6 ! important; + color: #ffffff ! important; + border: solid #000000 1px ! important; + line-height: normal; +} + +div.fancy.header > div a[href] { color: #ffffff ! important; } + +div.fancy.header > div a[href]:hover { text-decoration: underline ! important; } + +div.fancy.header > div.spamheader { + background-color: #cdcdcd ! important; + border-top: 0px ! important; + padding: 3px ! important; + color: black ! important; + font-weight: bold ! important; + font-size: 12pt; +} + +div.fancy.header > table.outer { + background-color: #efebe7 ! important; + color: #000000 ! important; + border-bottom: solid #000000 1px ! important; + border-left: solid #000000 1px ! important; + border-right: solid #000000 1px ! important; +} + +div.senderpic{ + padding: 0px ! important; + font-size:0.8em ! important; + border:1px solid #b8b5b2 ! important; + background-color:#efebe7 ! important; +} + +div.senderstatus{ + text-align:center ! important; +} + +div.quotelevel1 { + color: #100000 ! important; +} + +div.quotelevel2 { + color: #200000 ! important; +} + +div.quotelevel3 { + color: #300000 ! important; +} + +div.deepquotelevel1 { + color: #100000 ! important; +} + +div.deepquotelevel2 { + color: #200000 ! important; +} + +div.deepquotelevel3 { + color: #300000 ! important; +} diff --git a/framework/domain/folderlistcontroller.cpp b/framework/domain/folderlistcontroller.cpp new file mode 100644 index 00000000..46a6f648 --- /dev/null +++ b/framework/domain/folderlistcontroller.cpp @@ -0,0 +1,69 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "folderlistcontroller.h" + +#include "folderlistmodel.h" + +#include + +FolderListController::FolderListController(QObject *parent) : QObject(parent), m_model(new FolderListModel) +{ + +} + +QString FolderListController::accountId() const +{ + return m_accountId; +} + +void FolderListController::setAccountId(const QString &id) +{ + if(m_accountId != id) { + m_accountId = id; + + loadFolders(id); + + emit accountIdChanged(); + } +} + +FolderListModel* FolderListController::model() const +{ + return m_model.data(); +} + +void FolderListController::loadFolders(const QString &id) +{ + //load foldermodel from sink + +} + + +void FolderListController::addFolder(const QString &name) +{ + qDebug() << "User Action: add folder " << name; +} + +void FolderListController::deleteFolder(const QString &id) +{ + qDebug() << "User Action: delete folder " << id; +} + diff --git a/framework/domain/folderlistcontroller.h b/framework/domain/folderlistcontroller.h new file mode 100644 index 00000000..11057f21 --- /dev/null +++ b/framework/domain/folderlistcontroller.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include "folderlistmodel.h" + +#include +#include +#include + +class FolderListController : public QObject +{ + Q_OBJECT + Q_PROPERTY (QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged) + Q_PROPERTY (FolderListModel *model READ model CONSTANT) + +public: + explicit FolderListController(QObject *parent = Q_NULLPTR); + + QString accountId() const; + void setAccountId(const QString &id); + + FolderListModel *model() const; + + void loadFolders(const QString &id); + +signals: + void accountIdChanged(); + +public slots: + void deleteFolder(const QString &id); + void addFolder(const QString &name); + + +private: + QString m_accountId; + QScopedPointer m_model; +}; diff --git a/framework/domain/folderlistmodel.cpp b/framework/domain/folderlistmodel.cpp new file mode 100644 index 00000000..ce6fb4fd --- /dev/null +++ b/framework/domain/folderlistmodel.cpp @@ -0,0 +1,65 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "folderlistmodel.h" +#include + +FolderListModel::FolderListModel(QObject *parent) : QIdentityProxyModel() +{ + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "name" << "icon" << "parent"; + query.parentProperty = "parent"; + mModel = Sink::Store::loadModel(query); + setSourceModel(mModel.data()); +} + +FolderListModel::~FolderListModel() +{ + +} + +QHash< int, QByteArray > FolderListModel::roleNames() const +{ + QHash roles; + + roles[Name] = "name"; + roles[Icon] = "icon"; + roles[Id] = "id"; + roles[DomainObject] = "domainObject"; + + return roles; +} + +QVariant FolderListModel::data(const QModelIndex &idx, int role) const +{ + auto srcIdx = mapToSource(idx); + switch (role) { + case Name: + return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString(); + case Icon: + return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString(); + case Id: + return srcIdx.data(Sink::Store::DomainObjectBaseRole).value()->identifier(); + case DomainObject: + return srcIdx.data(Sink::Store::DomainObjectRole); + } + return QIdentityProxyModel::data(idx, role); +} diff --git a/framework/domain/folderlistmodel.h b/framework/domain/folderlistmodel.h new file mode 100644 index 00000000..7844e59a --- /dev/null +++ b/framework/domain/folderlistmodel.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include +#include +#include + +class FolderListModel : public QIdentityProxyModel +{ + Q_OBJECT + +public: + FolderListModel(QObject *parent = Q_NULLPTR); + ~FolderListModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + enum Roles { + Name = Qt::UserRole + 1, + Icon, + Id, + DomainObject + }; + Q_ENUMS(Roles) + + QHash roleNames() const; + +private: + QSharedPointer mModel; +}; diff --git a/framework/domain/maillistcontroller.cpp b/framework/domain/maillistcontroller.cpp new file mode 100644 index 00000000..a4bd6436 --- /dev/null +++ b/framework/domain/maillistcontroller.cpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "maillistcontroller.h" + +#include + +#include + +#include "maillistmodel.h" + +MailListController::MailListController(QObject *parent) : QObject(parent), m_model(new MailListModel) +{ +} + +MailListModel *MailListController::model() const +{ + return m_model.data(); + +} + +void MailListController::loadAllMail() +{ + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; + m_model->runQuery(query); +} + +void MailListController::loadMailFolder(const QString &folderId) +{ + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder"; + query.propertyFilter.insert("folder", folderId.toLatin1()); + m_model->runQuery(query); +} + +void MailListController::loadUnreadMail() +{ + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; + query.propertyFilter.insert("unread", true); + m_model->runQuery(query); +} + +void MailListController::loadImportantMail() +{ + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; + query.propertyFilter.insert("important", true); + m_model->runQuery(query); +} + +QString MailListController::selectedMail() const +{ + return m_selectedMail; +} + +void MailListController::setSelectedMail(const QString& id) +{ + if (m_selectedMail != id) { + m_selectedMail = id; + emit selectedMailChanged(); + } +} + +void MailListController::markMailImportant(bool important) +{ + qDebug() << "user action: mark mail important "; +} + +void MailListController::markMailUnread(bool unread) +{ + qDebug() << "user action: mark mail unread "; +} + +void MailListController::deleteMail() +{ + qDebug() << "user action: delete mail"; +} + diff --git a/framework/domain/maillistcontroller.h b/framework/domain/maillistcontroller.h new file mode 100644 index 00000000..959c63a3 --- /dev/null +++ b/framework/domain/maillistcontroller.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include "maillistmodel.h" + +#include +#include +#include +#include + +class MailListController : public QObject +{ + Q_OBJECT + Q_PROPERTY (MailListModel *model READ model CONSTANT) + Q_PROPERTY (QString selectedMail READ selectedMail WRITE setSelectedMail NOTIFY selectedMailChanged) + +public: + explicit MailListController(QObject *parent = Q_NULLPTR); + + MailListModel *model() const; + + QString selectedMail() const; + void setSelectedMail(const QString &id); + +signals: + void selectedMailChanged(); + +public slots: + void loadAllMail(); + void loadUnreadMail(); + void loadImportantMail(); + void loadMailFolder(const QString &folderId); + + void markMailImportant(bool important); + void markMailUnread(bool unread); + void deleteMail(); + +private: + QScopedPointer m_model; + + QString m_selectedMail; +}; diff --git a/framework/domain/maillistmodel.cpp b/framework/domain/maillistmodel.cpp new file mode 100644 index 00000000..b46fabf8 --- /dev/null +++ b/framework/domain/maillistmodel.cpp @@ -0,0 +1,149 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "maillistmodel.h" + +#include +#include + + +MailListModel::MailListModel(QObject *parent) + : QSortFilterProxyModel() +{ + setDynamicSortFilter(true); + sort(0, Qt::DescendingOrder); +} + +MailListModel::~MailListModel() +{ + +} + +QHash< int, QByteArray > MailListModel::roleNames() const +{ + QHash roles; + + roles[Subject] = "subject"; + roles[Sender] = "sender"; + roles[SenderName] = "senderName"; + roles[Date] = "date"; + roles[Unread] = "unread"; + roles[Important] = "important"; + roles[Id] = "id"; + roles[MimeMessage] = "mimeMessage"; + roles[DomainObject] = "domainObject"; + + return roles; +} + +QVariant MailListModel::data(const QModelIndex &idx, int role) const +{ + auto srcIdx = mapToSource(idx); + switch (role) { + case Subject: + return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString(); + case Sender: + return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString(); + case SenderName: + return srcIdx.sibling(srcIdx.row(), 2).data(Qt::DisplayRole).toString(); + case Date: + return srcIdx.sibling(srcIdx.row(), 3).data(Qt::DisplayRole).toString(); + case Unread: + return srcIdx.sibling(srcIdx.row(), 4).data(Qt::DisplayRole).toBool(); + case Important: + return srcIdx.sibling(srcIdx.row(), 5).data(Qt::DisplayRole).toBool(); + case Id: + return srcIdx.data(Sink::Store::DomainObjectBaseRole).value()->identifier(); + case DomainObject: + return srcIdx.data(Sink::Store::DomainObjectRole); + case MimeMessage: { + auto filename = srcIdx.sibling(srcIdx.row(), 6).data(Qt::DisplayRole).toString(); + QFile file(filename); + if (file.open(QFile::ReadOnly)) { + auto content = file.readAll(); + qWarning() << filename << content; + return content; + } else { + qWarning() << "Failed to open the file"; + } + return "Failed to read mail."; + } + } + return QSortFilterProxyModel::data(idx, role); +} + +bool MailListModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + const QVariant leftData = left.sibling(left.row(), 3).data(Qt::DisplayRole); + const QVariant rightData = right.sibling(right.row(), 3).data(Qt::DisplayRole); + return leftData.toDateTime() < rightData.toDateTime(); +} + +void MailListModel::runQuery(const Sink::Query &query) +{ + m_model = Sink::Store::loadModel(query); + setSourceModel(m_model.data()); +} + +void MailListModel::setParentFolder(const QVariant &parentFolder) +{ + auto folder = parentFolder.value(); + if (!folder) { + qWarning() << "No folder: " << parentFolder; + return; + } + Sink::Query query; + query.liveQuery = true; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder"; + query.propertyFilter.insert("folder", folder->identifier()); + query.resources << folder->resourceInstanceIdentifier(); + query.sortProperty = "date"; + query.limit = 100; + qWarning() << "Running folder query: " << folder->resourceInstanceIdentifier() << folder->identifier(); + runQuery(query); +} + +QVariant MailListModel::parentFolder() const +{ + return QVariant(); +} + +void MailListModel::setMail(const QVariant &variant) +{ + auto mail = variant.value(); + if (!mail) { + qWarning() << "No mail: " << mail; + return; + } + Sink::Query query; + query.liveQuery = false; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage"; + query.ids << mail->identifier(); + query.resources << mail->resourceInstanceIdentifier(); + qWarning() << "Running mail query: " << mail->resourceInstanceIdentifier() << mail->identifier(); + runQuery(query); +} + +QVariant MailListModel::mail() const +{ + return QVariant(); +} + + diff --git a/framework/domain/maillistmodel.h b/framework/domain/maillistmodel.h new file mode 100644 index 00000000..47a2a091 --- /dev/null +++ b/framework/domain/maillistmodel.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include + +#include +#include +#include + +class MailListModel : public QSortFilterProxyModel +{ + Q_OBJECT + Q_PROPERTY (QVariant parentFolder READ parentFolder WRITE setParentFolder) + Q_PROPERTY (QVariant mail READ mail WRITE setMail) + +public: + MailListModel(QObject *parent = Q_NULLPTR); + ~MailListModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + + bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; + + enum Roles { + Subject = Qt::UserRole + 1, + Sender, + SenderName, + Date, + Unread, + Important, + Id, + MimeMessage, + DomainObject + }; + + QHash roleNames() const; + + void runQuery(const Sink::Query &query); + + void setParentFolder(const QVariant &parentFolder); + QVariant parentFolder() const; + + void setMail(const QVariant &mail); + QVariant mail() const; +private: + QSharedPointer m_model; +}; diff --git a/framework/domain/mailplugin.cpp b/framework/domain/mailplugin.cpp new file mode 100644 index 00000000..2d19a437 --- /dev/null +++ b/framework/domain/mailplugin.cpp @@ -0,0 +1,40 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "mailplugin.h" + +#include "maillistmodel.h" +#include "folderlistmodel.h" +#include "composer.h" +#include "messageparser.h" +#include "retriever.h" + +#include + +void MailPlugin::registerTypes (const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.kube.mail")); + + qmlRegisterType(uri, 1, 0, "FolderListModel"); + qmlRegisterType(uri, 1, 0, "MailListModel"); + qmlRegisterType(uri, 1, 0, "Composer"); + qmlRegisterType(uri, 1, 0, "MessageParser"); + qmlRegisterType(uri, 1, 0, "Retriever"); +} diff --git a/framework/domain/mailplugin.h b/framework/domain/mailplugin.h new file mode 100644 index 00000000..ebd091ee --- /dev/null +++ b/framework/domain/mailplugin.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include + +class MailPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + virtual void registerTypes(const char *uri); +}; \ No newline at end of file diff --git a/framework/domain/mailtemplates.cpp b/framework/domain/mailtemplates.cpp new file mode 100644 index 00000000..e5ee8533 --- /dev/null +++ b/framework/domain/mailtemplates.cpp @@ -0,0 +1,804 @@ +/* + Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (c) 2010 Leo Franchi + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include "mailtemplates.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "stringhtmlwriter.h" +#include "objecttreesource.h" +#include "csshelper.h" + +#include + +namespace KMime { + namespace Types { +static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right) +{ + return (left.asString() == right.asString()); +} + +static bool operator==(const KMime::Types::Mailbox &left, const KMime::Types::Mailbox &right) +{ + return (left.addrSpec().asString() == right.addrSpec().asString()); +} + } +} + +static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me) +{ + KMime::Types::Mailbox::List addresses(list); + for (KMime::Types::Mailbox::List::Iterator it = addresses.begin(); it != addresses.end();) { + if (me.contains(it->addrSpec())) { + it = addresses.erase(it); + } else { + ++it; + } + } + + return addresses; +} + +void initHeader(const KMime::Message::Ptr &message) +{ + message->removeHeader(); + message->removeHeader(); + message->date()->setDateTime(QDateTime::currentDateTime()); + + const QStringList extraInfo = QStringList() << QSysInfo::prettyProductName(); + message->userAgent()->fromUnicodeString(QString("%1/%2(%3)").arg(QString::fromLocal8Bit("Kube")).arg("0.1").arg(extraInfo.join(",")), "utf-8"); + // This will allow to change Content-Type: + message->contentType()->setMimeType("text/plain"); +} + +QString replacePrefixes(const QString &str, const QStringList &prefixRegExps, + bool replace, const QString &newPrefix) +{ + bool recognized = false; + // construct a big regexp that + // 1. is anchored to the beginning of str (sans whitespace) + // 2. matches at least one of the part regexps in prefixRegExps + QString bigRegExp = QStringLiteral("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QStringLiteral(")|(?:"))); + QRegExp rx(bigRegExp, Qt::CaseInsensitive); + if (rx.isValid()) { + QString tmp = str; + if (rx.indexIn(tmp) == 0) { + recognized = true; + if (replace) { + return tmp.replace(0, rx.matchedLength(), newPrefix + QLatin1String(" ")); + } + } + } else { + qWarning() << "bigRegExp = \"" + << bigRegExp << "\"\n" + << "prefix regexp is invalid!"; + // try good ole Re/Fwd: + recognized = str.startsWith(newPrefix); + } + + if (!recognized) { + return newPrefix + QLatin1String(" ") + str; + } else { + return str; + } +} + +QString cleanSubject(const KMime::Message::Ptr &msg, const QStringList &prefixRegExps, bool replace, const QString &newPrefix) +{ + return replacePrefixes(msg->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix); +} + +QString forwardSubject(const KMime::Message::Ptr &msg) +{ + bool replaceForwardPrefix = true; + QStringList forwardPrefixes; + forwardPrefixes << "Fwd:"; + forwardPrefixes << "FW:"; + return cleanSubject(msg, forwardPrefixes, replaceForwardPrefix, QStringLiteral("Fwd:")); +} + +QString replySubject(const KMime::Message::Ptr &msg) +{ + bool replaceReplyPrefix = true; + QStringList replyPrefixes; + //We're escaping the regex escape sequences. awesome + replyPrefixes << "Re\\\\s*:"; + replyPrefixes << "Re[\\\\d+\\\\]:"; + replyPrefixes << "Re\\\\d+:"; + return cleanSubject(msg, replyPrefixes, replaceReplyPrefix, QStringLiteral("Re:")); +} + +QByteArray getRefStr(const KMime::Message::Ptr &msg) +{ + QByteArray firstRef, lastRef, refStr, retRefStr; + int i, j; + + if (auto hdr = msg->references(false)) { + refStr = hdr->as7BitString(false).trimmed(); + } + + if (refStr.isEmpty()) { + return msg->messageID()->as7BitString(false); + } + + i = refStr.indexOf('<'); + j = refStr.indexOf('>'); + firstRef = refStr.mid(i, j - i + 1); + if (!firstRef.isEmpty()) { + retRefStr = firstRef + ' '; + } + + i = refStr.lastIndexOf('<'); + j = refStr.lastIndexOf('>'); + + lastRef = refStr.mid(i, j - i + 1); + if (!lastRef.isEmpty() && lastRef != firstRef) { + retRefStr += lastRef + ' '; + } + + retRefStr += msg->messageID()->as7BitString(false); + return retRefStr; +} + +KMime::Content *createPlainPartContent(const KMime::Message::Ptr &msg, const QString &plainBody) +{ + KMime::Content *textPart = new KMime::Content(msg.data()); + textPart->contentType()->setMimeType("text/plain"); + //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text + // QTextCodec *charset = selectCharset(m_charsets, plainBody); + // textPart->contentType()->setCharset(charset->name()); + textPart->contentType()->setCharset("utf-8"); + textPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); + textPart->fromUnicodeString(plainBody); + return textPart; +} + +KMime::Content *createMultipartAlternativeContent(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody) +{ + KMime::Content *multipartAlternative = new KMime::Content(msg.data()); + multipartAlternative->contentType()->setMimeType("multipart/alternative"); + const QByteArray boundary = KMime::multiPartBoundary(); + multipartAlternative->contentType()->setBoundary(boundary); + + KMime::Content *textPart = createPlainPartContent(msg, plainBody); + multipartAlternative->addContent(textPart); + + KMime::Content *htmlPart = new KMime::Content(msg.data()); + htmlPart->contentType()->setMimeType("text/html"); + //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text + // QTextCodec *charset = selectCharset(m_charsets, htmlBody); + // htmlPart->contentType()->setCharset(charset->name()); + textPart->contentType()->setCharset("utf-8"); + htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); + htmlPart->fromUnicodeString(htmlBody); + multipartAlternative->addContent(htmlPart); + + return multipartAlternative; +} + +void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward) +{ + //FIXME + // MessageCore::ImageCollector ic; + // ic.collectImagesFrom(mOrigMsg.data()); + + // Now, delete the old content and set the new content, which + // is either only the new text or the new text with some attachments. + auto parts = msg->contents(); + foreach (KMime::Content *content, parts) { + msg->removeContent(content, true/*delete*/); + } + + msg->contentType()->clear(); // to get rid of old boundary + + const QByteArray boundary = KMime::multiPartBoundary(); + KMime::Content *const mainTextPart = + htmlBody.isEmpty() ? + createPlainPartContent(msg, plainBody) : + createMultipartAlternativeContent(msg, plainBody, htmlBody); + mainTextPart->assemble(); + + KMime::Content *textPart = mainTextPart; + // if (!ic.images().empty()) { + // textPart = createMultipartRelated(ic, mainTextPart); + // textPart->assemble(); + // } + + // If we have some attachments, create a multipart/mixed mail and + // add the normal body as well as the attachments + KMime::Content *mainPart = textPart; + //FIXME + // if (forward) { + // auto attachments = mOrigMsg->attachments(); + // attachments += mOtp->nodeHelper()->attachmentsOfExtraContents(); + // if (!attachments.isEmpty()) { + // mainPart = createMultipartMixed(attachments, textPart); + // mainPart->assemble(); + // } + // } + + msg->setBody(mainPart->encodedBody()); + msg->setHeader(mainPart->contentType()); + msg->setHeader(mainPart->contentTransferEncoding()); + msg->assemble(); + msg->parse(); +} + +QString plainToHtml(const QString &body) +{ + QString str = body; + str = str.toHtmlEscaped(); + str.replace(QStringLiteral("\n"), QStringLiteral("
\n")); + return str; +} + +//TODO implement this function using a DOM tree parser +void makeValidHtml(QString &body, const QString &headElement) +{ + QRegExp regEx; + regEx.setMinimal(true); + regEx.setPattern(QStringLiteral("")); + + if (!body.isEmpty() && !body.contains(regEx)) { + regEx.setPattern(QStringLiteral("")); + if (!body.contains(regEx)) { + body = QLatin1String("") + body + QLatin1String("
"); + } + regEx.setPattern(QStringLiteral("")); + if (!body.contains(regEx)) { + body = QLatin1String("") + headElement + QLatin1String("") + body; + } + body = QLatin1String("") + body + QLatin1String(""); + } +} + +QString stripSignature(const QString &msg) +{ + // Following RFC 3676, only > before -- + // I prefer to not delete a SB instead of delete good mail content. + const QRegExp sbDelimiterSearch = QRegExp(QLatin1String("(^|\n)[> ]*-- \n")); + // The regular expression to look for prefix change + const QRegExp commonReplySearch = QRegExp(QLatin1String("^[ ]*>")); + + QString res = msg; + int posDeletingStart = 1; // to start looking at 0 + + // While there are SB delimiters (start looking just before the deleted SB) + while ((posDeletingStart = res.indexOf(sbDelimiterSearch, posDeletingStart - 1)) >= 0) { + QString prefix; // the current prefix + QString line; // the line to check if is part of the SB + int posNewLine = -1; + + // Look for the SB beginning + int posSignatureBlock = res.indexOf(QLatin1Char('-'), posDeletingStart); + // The prefix before "-- "$ + if (res.at(posDeletingStart) == QLatin1Char('\n')) { + ++posDeletingStart; + } + + prefix = res.mid(posDeletingStart, posSignatureBlock - posDeletingStart); + posNewLine = res.indexOf(QLatin1Char('\n'), posSignatureBlock) + 1; + + // now go to the end of the SB + while (posNewLine < res.size() && posNewLine > 0) { + // handle the undefined case for mid ( x , -n ) where n>1 + int nextPosNewLine = res.indexOf(QLatin1Char('\n'), posNewLine); + + if (nextPosNewLine < 0) { + nextPosNewLine = posNewLine - 1; + } + + line = res.mid(posNewLine, nextPosNewLine - posNewLine); + + // check when the SB ends: + // * does not starts with prefix or + // * starts with prefix+(any substring of prefix) + if ((prefix.isEmpty() && line.indexOf(commonReplySearch) < 0) || + (!prefix.isEmpty() && line.startsWith(prefix) && + line.mid(prefix.size()).indexOf(commonReplySearch) < 0)) { + posNewLine = res.indexOf(QLatin1Char('\n'), posNewLine) + 1; + } else { + break; // end of the SB + } + } + + // remove the SB or truncate when is the last SB + if (posNewLine > 0) { + res.remove(posDeletingStart, posNewLine - posDeletingStart); + } else { + res.truncate(posDeletingStart); + } + } + + return res; +} + +QString plainMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature) +{ + QString result = otp.plainTextContent(); + if (result.isEmpty()) { //HTML-only mails + QWebPage doc; + doc.mainFrame()->setHtml(otp.htmlContent()); + result = doc.mainFrame()->toPlainText(); + } + + if (aStripSignature) { + result = stripSignature(result); + } + + return result; +} + +QString htmlMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature, QString &headElement) +{ + QString htmlElement = otp.htmlContent(); + + if (htmlElement.isEmpty()) { //plain mails only + QString htmlReplace = otp.plainTextContent().toHtmlEscaped(); + htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("
")); + htmlElement = QStringLiteral("%1\n").arg(htmlReplace); + } + + //QWebPage relies on this + Q_ASSERT(QApplication::style()); + QWebPage page; + page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); + page.settings()->setAttribute(QWebSettings::JavaEnabled, false); + page.settings()->setAttribute(QWebSettings::PluginsEnabled, false); + page.settings()->setAttribute(QWebSettings::AutoLoadImages, false); + + page.currentFrame()->setHtml(htmlElement); + + //TODO to be tested/verified if this is not an issue + page.settings()->setAttribute(QWebSettings::JavascriptEnabled, true); + const QString bodyElement = page.currentFrame()->evaluateJavaScript( + QStringLiteral("document.getElementsByTagName('body')[0].innerHTML")).toString(); + + headElement = page.currentFrame()->evaluateJavaScript( + QStringLiteral("document.getElementsByTagName('head')[0].innerHTML")).toString(); + + page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); + + if (!bodyElement.isEmpty()) { + if (aStripSignature) { + //FIXME strip signature works partially for HTML mails + return stripSignature(bodyElement); + } + return bodyElement; + } + + if (aStripSignature) { + //FIXME strip signature works partially for HTML mails + return stripSignature(htmlElement); + } + return htmlElement; +} + +QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) +{ + QString result; + + if (wildString.isEmpty()) { + return wildString; + } + + unsigned int strLength(wildString.length()); + for (uint i = 0; i < strLength;) { + QChar ch = wildString[i++]; + if (ch == QLatin1Char('%') && i < strLength) { + ch = wildString[i++]; + switch (ch.toLatin1()) { + case 'f': { // sender's initals + if (fromDisplayString.isEmpty()) { + break; + } + + uint j = 0; + const unsigned int strLength(fromDisplayString.length()); + for (; j < strLength && fromDisplayString[j] > QLatin1Char(' '); ++j) + ; + for (; j < strLength && fromDisplayString[j] <= QLatin1Char(' '); ++j) + ; + result += fromDisplayString[0]; + if (j < strLength && fromDisplayString[j] > QLatin1Char(' ')) { + result += fromDisplayString[j]; + } else if (strLength > 1) { + if (fromDisplayString[1] > QLatin1Char(' ')) { + result += fromDisplayString[1]; + } + } + } + break; + case '_': + result += QLatin1Char(' '); + break; + case '%': + result += QLatin1Char('%'); + break; + default: + result += QLatin1Char('%'); + result += ch; + break; + } + } else { + result += ch; + } + } + return result; +} + +QString quotedPlainText(const QString &selection, const QString &fromDisplayString) +{ + QString content = selection; + // Remove blank lines at the beginning: + const int firstNonWS = content.indexOf(QRegExp(QLatin1String("\\S"))); + const int lineStart = content.lastIndexOf(QLatin1Char('\n'), firstNonWS); + if (lineStart >= 0) { + content.remove(0, static_cast(lineStart)); + } + + const auto quoteString = QStringLiteral("> "); + const QString indentStr = formatQuotePrefix(quoteString, fromDisplayString); + //FIXME + // if (TemplateParserSettings::self()->smartQuote() && mWrap) { + // content = MessageCore::StringUtil::smartQuote(content, mColWrap - indentStr.length()); + // } + content.replace(QLatin1Char('\n'), QLatin1Char('\n') + indentStr); + content.prepend(indentStr); + content += QLatin1Char('\n'); + + return content; +} + +QString quotedHtmlText(const QString &selection) +{ + QString content = selection; + //TODO 1) look for all the variations of
and remove the blank lines + //2) implement vertical bar for quoted HTML mail. + //3) After vertical bar is implemented, If a user wants to edit quoted message, + // then the
tags below should open and close as when required. + + //Add blockquote tag, so that quoted message can be differentiated from normal message + content = QLatin1String("
") + content + QLatin1String("
"); + return content; +} + +void applyCharset(const KMime::Message::Ptr msg, const KMime::Message::Ptr &origMsg) +{ + // first convert the body from its current encoding to unicode representation + QTextCodec *bodyCodec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); + if (!bodyCodec) { + bodyCodec = KCharsets::charsets()->codecForName(QStringLiteral("UTF-8")); + } + + const QString body = bodyCodec->toUnicode(msg->body()); + + // then apply the encoding of the original message + msg->contentType()->setCharset(origMsg->contentType()->charset()); + + QTextCodec *codec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); + if (!codec) { + qCritical() << "Could not get text codec for charset" << msg->contentType()->charset(); + } else if (!codec->canEncode(body)) { // charset can't encode body, fall back to preferred + const QStringList charsets /*= preferredCharsets() */; + + QList chars; + chars.reserve(charsets.count()); + foreach (const QString &charset, charsets) { + chars << charset.toLatin1(); + } + + //FIXME + QByteArray fallbackCharset/* = selectCharset(chars, body)*/; + if (fallbackCharset.isEmpty()) { // UTF-8 as fall-through + fallbackCharset = "UTF-8"; + } + + codec = KCharsets::charsets()->codecForName(QString::fromLatin1(fallbackCharset)); + msg->setBody(codec->fromUnicode(body)); + } else { + msg->setBody(codec->fromUnicode(body)); + } +} + +enum ReplyStrategy { + ReplyList, + ReplySmart, + ReplyAll, + ReplyAuthor, + ReplyNone +}; + +KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) +{ + //FIXME + const bool alwaysPlain = true; + //FIXME + const ReplyStrategy replyStrategy = ReplySmart; + KMime::Message::Ptr msg(new KMime::Message); + //FIXME + //Personal email addresses + KMime::Types::AddrSpecList me; + KMime::Types::Mailbox::List toList; + KMime::Types::Mailbox::List replyToList; + KMime::Types::Mailbox::List mailingListAddresses; + + // const uint originalIdentity = identityUoid(origMsg); + initHeader(msg); + replyToList = origMsg->replyTo()->mailboxes(); + + msg->contentType()->setCharset("utf-8"); + + if (origMsg->headerByType("List-Post") && + origMsg->headerByType("List-Post")->asUnicodeString().contains(QStringLiteral("mailto:"), Qt::CaseInsensitive)) { + + const QString listPost = origMsg->headerByType("List-Post")->asUnicodeString(); + QRegExp rx(QStringLiteral("]+)@([^>]+)>"), Qt::CaseInsensitive); + if (rx.indexIn(listPost, 0) != -1) { // matched + KMime::Types::Mailbox mailbox; + mailbox.fromUnicodeString(rx.cap(1) + QLatin1Char('@') + rx.cap(2)); + mailingListAddresses << mailbox; + } + } + + switch (replyStrategy) { + case ReplySmart: { + if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { + toList << KMime::Types::Mailbox::listFrom7BitString(hdr->as7BitString(false)); + } else if (!replyToList.isEmpty()) { + toList = replyToList; + } else if (!mailingListAddresses.isEmpty()) { + toList = (KMime::Types::Mailbox::List() << mailingListAddresses.at(0)); + } else { + // doesn't seem to be a mailing list, reply to From: address + toList = origMsg->from()->mailboxes(); + + bool listContainsMe = false; + for (const auto &m : me) { + KMime::Types::Mailbox mailbox; + mailbox.setAddress(m); + if (toList.contains(mailbox)) { + listContainsMe = true; + } + } + if (listContainsMe) { + // sender seems to be one of our own identities, so we assume that this + // is a reply to a "sent" mail where the users wants to add additional + // information for the recipient. + toList = origMsg->to()->mailboxes(); + } + } + // strip all my addresses from the list of recipients + const KMime::Types::Mailbox::List recipients = toList; + + toList = stripMyAddressesFromAddressList(recipients, me); + + // ... unless the list contains only my addresses (reply to self) + if (toList.isEmpty() && !recipients.isEmpty()) { + toList << recipients.first(); + } + } + break; + case ReplyList: { + if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { + KMime::Types::Mailbox mailbox; + mailbox.from7BitString(hdr->as7BitString(false)); + toList << mailbox; + } else if (!mailingListAddresses.isEmpty()) { + toList << mailingListAddresses[ 0 ]; + } else if (!replyToList.isEmpty()) { + // assume a Reply-To header mangling mailing list + toList = replyToList; + } + + //FIXME + // strip all my addresses from the list of recipients + const KMime::Types::Mailbox::List recipients = toList; + toList = stripMyAddressesFromAddressList(recipients, me); + } + break; + case ReplyAll: { + KMime::Types::Mailbox::List recipients; + KMime::Types::Mailbox::List ccRecipients; + + // add addresses from the Reply-To header to the list of recipients + if (!replyToList.isEmpty()) { + recipients = replyToList; + + // strip all possible mailing list addresses from the list of Reply-To addresses + foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { + foreach (const KMime::Types::Mailbox &recipient, recipients) { + if (mailbox == recipient) { + recipients.removeAll(recipient); + } + } + } + } + + if (!mailingListAddresses.isEmpty()) { + // this is a mailing list message + if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { + // The sender didn't set a Reply-to address, so we add the From + // address to the list of CC recipients. + ccRecipients += origMsg->from()->mailboxes(); + qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of CC recipients"; + } + + // if it is a mailing list, add the posting address + recipients.prepend(mailingListAddresses[ 0 ]); + } else { + // this is a normal message + if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { + // in case of replying to a normal message only then add the From + // address to the list of recipients if there was no Reply-to address + recipients += origMsg->from()->mailboxes(); + qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of recipients"; + } + } + + // strip all my addresses from the list of recipients + toList = stripMyAddressesFromAddressList(recipients, me); + + // merge To header and CC header into a list of CC recipients + if (!origMsg->cc()->asUnicodeString().isEmpty() || !origMsg->to()->asUnicodeString().isEmpty()) { + KMime::Types::Mailbox::List list; + if (!origMsg->to()->asUnicodeString().isEmpty()) { + list += origMsg->to()->mailboxes(); + } + if (!origMsg->cc()->asUnicodeString().isEmpty()) { + list += origMsg->cc()->mailboxes(); + } + + foreach (const KMime::Types::Mailbox &mailbox, list) { + if (!recipients.contains(mailbox) && + !ccRecipients.contains(mailbox)) { + ccRecipients += mailbox; + qDebug() << "Added" << mailbox.prettyAddress() << "to the list of CC recipients"; + } + } + } + + if (!ccRecipients.isEmpty()) { + // strip all my addresses from the list of CC recipients + ccRecipients = stripMyAddressesFromAddressList(ccRecipients, me); + + // in case of a reply to self, toList might be empty. if that's the case + // then propagate a cc recipient to To: (if there is any). + if (toList.isEmpty() && !ccRecipients.isEmpty()) { + toList << ccRecipients.at(0); + ccRecipients.pop_front(); + } + + foreach (const KMime::Types::Mailbox &mailbox, ccRecipients) { + msg->cc()->addAddress(mailbox); + } + } + + if (toList.isEmpty() && !recipients.isEmpty()) { + // reply to self without other recipients + toList << recipients.at(0); + } + } + break; + case ReplyAuthor: { + if (!replyToList.isEmpty()) { + KMime::Types::Mailbox::List recipients = replyToList; + + // strip the mailing list post address from the list of Reply-To + // addresses since we want to reply in private + foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { + foreach (const KMime::Types::Mailbox &recipient, recipients) { + if (mailbox == recipient) { + recipients.removeAll(recipient); + } + } + } + + if (!recipients.isEmpty()) { + toList = recipients; + } else { + // there was only the mailing list post address in the Reply-To header, + // so use the From address instead + toList = origMsg->from()->mailboxes(); + } + } else if (!origMsg->from()->asUnicodeString().isEmpty()) { + toList = origMsg->from()->mailboxes(); + } + } + break; + case ReplyNone: + // the addressees will be set by the caller + break; + } + + foreach (const KMime::Types::Mailbox &mailbox, toList) { + msg->to()->addAddress(mailbox); + } + + const QByteArray refStr = getRefStr(origMsg); + if (!refStr.isEmpty()) { + msg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8"); + } + + //In-Reply-To = original msg-id + msg->inReplyTo()->from7BitString(origMsg->messageID()->as7BitString(false)); + + msg->subject()->fromUnicodeString(replySubject(origMsg), "utf-8"); + + auto definedLocale = QLocale::system(); + + //TODO set empty source instead + StringHtmlWriter htmlWriter; + QImage paintDevice; + CSSHelper cssHelper(&paintDevice); + MessageViewer::NodeHelper nodeHelper; + ObjectTreeSource source(&htmlWriter, &cssHelper); + MessageViewer::ObjectTreeParser otp(&source, &nodeHelper); + otp.setAllowAsync(false); + otp.parseObjectTree(origMsg.data()); + + //Add quoted body + QString plainBody; + QString htmlBody; + + //On $datetime you wrote: + const QDateTime date = origMsg->date()->dateTime(); + const auto dateTimeString = QString("%1 %2").arg(definedLocale.toString(date.date(), QLocale::LongFormat)).arg(definedLocale.toString(date.time(), QLocale::LongFormat)); + const auto onDateYouWroteLine = QString("On %1 you wrote:").arg(dateTimeString); + plainBody.append(onDateYouWroteLine); + htmlBody.append(plainToHtml(onDateYouWroteLine)); + + //Strip signature for replies + const bool stripSignature = true; + + //Quoted body + QString plainQuote = quotedPlainText(plainMessageText(otp, stripSignature), origMsg->from()->displayString()); + if (plainQuote.endsWith(QLatin1Char('\n'))) { + plainQuote.chop(1); + } + plainBody.append(plainQuote); + QString headElement; + htmlBody.append(quotedHtmlText(htmlMessageText(otp, stripSignature, headElement))); + + if (alwaysPlain) { + htmlBody.clear(); + } else { + makeValidHtml(htmlBody, headElement); + } + + addProcessedBodyToMessage(msg, plainBody, htmlBody, false); + + applyCharset(msg, origMsg); + + msg->assemble(); + + return msg; +} diff --git a/framework/domain/mailtemplates.h b/framework/domain/mailtemplates.h new file mode 100644 index 00000000..6519122a --- /dev/null +++ b/framework/domain/mailtemplates.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include + +namespace MailTemplates +{ + KMime::Message::Ptr reply(const KMime::Message::Ptr &message); +}; diff --git a/framework/domain/mailtransport.cpp b/framework/domain/mailtransport.cpp new file mode 100644 index 00000000..49d858e1 --- /dev/null +++ b/framework/domain/mailtransport.cpp @@ -0,0 +1,160 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include "mailtransport.h" + +#include +#include +#include + +extern "C" { + +#include +#include +#include + +struct upload_status { + int offset; + const char *data; +}; + +static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) +{ + struct upload_status *upload_ctx = (struct upload_status *)userp; + const char *data; + + if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + return 0; + } + + data = &upload_ctx->data[upload_ctx->offset]; + if(data) { + size_t len = strlen(data); + if (len > size * nmemb) { + len = size * nmemb; + } + fprintf(stderr, "read n bytes: %d\n",len); + memcpy(ptr, data, len); + upload_ctx->offset += len; + return len; + } + + return 0; +} + + +void sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, const char *msg, bool useTls, const char* from, const char *username, const char *password, const char *server, bool verifyPeer) +{ + //For ssl use "smtps://mainserver.example.net + const char* cacert = 0; // = "/path/to/certificate.pem"; + + CURL *curl; + CURLcode res = CURLE_OK; + struct curl_slist *recipients = NULL; + struct upload_status upload_ctx; + + upload_ctx.offset = 0; + upload_ctx.data = msg; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_USERNAME, username); + curl_easy_setopt(curl, CURLOPT_PASSWORD, password); + + curl_easy_setopt(curl, CURLOPT_URL, server); + + if (useTls) { + curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); + } + + if (!verifyPeer) { + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + } + if (cacert) { + curl_easy_setopt(curl, CURLOPT_CAINFO, cacert); + } + + if (from) { + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from); + } + + for (int i = 0; i < numTos; i++) { + recipients = curl_slist_append(recipients, to[i]); + } + for (int i = 0; i < numCcs; i++) { + recipients = curl_slist_append(recipients, cc[i]); + } + curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); + + /* We're using a callback function to specify the payload (the headers and + * body of the message). You could just use the CURLOPT_READDATA option to + * specify a FILE pointer to read from. */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + /* Since the traffic will be encrypted, it is very useful to turn on debug + * information within libcurl to see what is happening during the transfer. + */ + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + res = curl_easy_perform(curl); + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + } + curl_slist_free_all(recipients); + curl_easy_cleanup(curl); + } +} + +}; + +void MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert) +{ + QByteArray msg = message->encodedContent(); + qWarning() << "Sending message " << msg; + + QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address()); + QList toList; + for (const auto &mb : message->to(true)->mailboxes()) { + toList << mb.address(); + } + QList ccList; + for (const auto &mb : message->cc(true)->mailboxes()) { + ccList << mb.address(); + } + bool useTls = true; + bool verifyPeer = false; + + const int numTos = toList.size(); + const char* to[numTos]; + for (int i = 0; i < numTos; i++) { + to[i] = toList.at(i); + } + + const int numCcs = ccList.size(); + const char* cc[numCcs]; + for (int i = 0; i < numCcs; i++) { + cc[i] = ccList.at(i); + } + + sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, server, verifyPeer); + qWarning() << "Message sent"; +} diff --git a/framework/domain/mailtransport.h b/framework/domain/mailtransport.h new file mode 100644 index 00000000..2eb30a03 --- /dev/null +++ b/framework/domain/mailtransport.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include + +namespace MailTransport +{ + void sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert); +}; diff --git a/framework/domain/messageparser.cpp b/framework/domain/messageparser.cpp new file mode 100644 index 00000000..89f67f38 --- /dev/null +++ b/framework/domain/messageparser.cpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ +#include "messageparser.h" + +#include "stringhtmlwriter.h" +#include "objecttreesource.h" +#include "csshelper.h" + +#include +#include +#include +#include +#include + +MessageParser::MessageParser(QObject *parent) + : QObject(parent) +{ + +} + +QString MessageParser::html() const +{ + return mHtml; +} + +QVariant MessageParser::message() const +{ + return QVariant(); +} + +void MessageParser::setMessage(const QVariant &message) +{ + QTime time; + time.start(); + const auto mailData = KMime::CRLFtoLF(message.toByteArray()); + KMime::Message::Ptr msg(new KMime::Message); + msg->setContent(mailData); + msg->parse(); + qWarning() << "parsed: " << time.elapsed(); + + // render the mail + StringHtmlWriter htmlWriter; + QImage paintDevice; + CSSHelper cssHelper(&paintDevice); + //temporary files only have the lifetime of the nodehelper, so we keep it around until the mail changes. + mNodeHelper = std::make_shared(); + ObjectTreeSource source(&htmlWriter, &cssHelper); + MessageViewer::ObjectTreeParser otp(&source, mNodeHelper.get()); + + htmlWriter.begin(QString()); + htmlWriter.queue(cssHelper.htmlHead(false)); + + otp.parseObjectTree(msg.data()); + + htmlWriter.queue(QStringLiteral("")); + htmlWriter.end(); + + mHtml = htmlWriter.html(); + emit htmlChanged(); +} diff --git a/framework/domain/messageparser.h b/framework/domain/messageparser.h new file mode 100644 index 00000000..ba08a5ec --- /dev/null +++ b/framework/domain/messageparser.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include +#include +#include + +namespace MessageViewer { + class NodeHelper; +}; + +class MessageParser : public QObject +{ + Q_OBJECT + Q_PROPERTY (QVariant message READ message WRITE setMessage) + Q_PROPERTY (QString html READ html NOTIFY htmlChanged) + +public: + explicit MessageParser(QObject *parent = Q_NULLPTR); + + QString html() const; + + QVariant message() const; + void setMessage(const QVariant &to); + +signals: + void htmlChanged(); + +private: + QString mHtml; + std::shared_ptr mNodeHelper; +}; diff --git a/framework/domain/objecttreesource.cpp b/framework/domain/objecttreesource.cpp new file mode 100644 index 00000000..d14b7b9b --- /dev/null +++ b/framework/domain/objecttreesource.cpp @@ -0,0 +1,144 @@ +/* + Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net + Copyright (c) 2009 Andras Mantia + + 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 "objecttreesource.h" + +#include + +class ObjectSourcePrivate +{ +public: + ObjectSourcePrivate() + : mWriter(0) + , mCSSHelper(0) + , mAllowDecryption(true) + , mHtmlLoadExternal(true) + , mHtmlMail(true) + { + + } + MessageViewer::HtmlWriter *mWriter; + MessageViewer::CSSHelperBase *mCSSHelper; + bool mAllowDecryption; + bool mHtmlLoadExternal; + bool mHtmlMail; +}; + +ObjectTreeSource::ObjectTreeSource(MessageViewer::HtmlWriter *writer, + MessageViewer::CSSHelperBase *cssHelper) + : MessageViewer::ObjectTreeSourceIf() + , d(new ObjectSourcePrivate) + { + d->mWriter = writer; + d->mCSSHelper = cssHelper; + } + +ObjectTreeSource::~ObjectTreeSource() +{ + delete d; +} + +void ObjectTreeSource::setAllowDecryption(bool allowDecryption) +{ + d->mAllowDecryption = allowDecryption; +} + +MessageViewer::HtmlWriter *ObjectTreeSource::htmlWriter() +{ + return d->mWriter; +} +MessageViewer::CSSHelperBase *ObjectTreeSource::cssHelper() +{ + return d->mCSSHelper; +} + +bool ObjectTreeSource::htmlLoadExternal() const +{ + return d->mHtmlLoadExternal; +} + +void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal) +{ + d->mHtmlLoadExternal = loadExternal; +} + +bool ObjectTreeSource::htmlMail() const +{ + return d->mHtmlMail; +} + +void ObjectTreeSource::setHtmlMail(bool htmlMail) +{ + d->mHtmlMail = htmlMail; +} + +bool ObjectTreeSource::decryptMessage() const +{ + return d->mAllowDecryption; +} + +bool ObjectTreeSource::showSignatureDetails() const +{ + return true; +} + +int ObjectTreeSource::levelQuote() const +{ + return 1; +} + +const QTextCodec *ObjectTreeSource::overrideCodec() +{ + return Q_NULLPTR; +} + +QString ObjectTreeSource::createMessageHeader(KMime::Message *message) +{ + return QString(); +} + +const MessageViewer::AttachmentStrategy *ObjectTreeSource::attachmentStrategy() +{ + return MessageViewer::AttachmentStrategy::smart(); +} + +QObject *ObjectTreeSource::sourceObject() +{ + return Q_NULLPTR; +} + +void ObjectTreeSource::setHtmlMode(MessageViewer::Util::HtmlMode mode) +{ + Q_UNUSED(mode); +} + +bool ObjectTreeSource::autoImportKeys() const +{ + return false; +} + +bool ObjectTreeSource::showEmoticons() const +{ + return false; +} + +bool ObjectTreeSource::showExpandQuotesMark() const +{ + return false; +} diff --git a/framework/domain/objecttreesource.h b/framework/domain/objecttreesource.h new file mode 100644 index 00000000..db14e3ff --- /dev/null +++ b/framework/domain/objecttreesource.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net + Copyright (c) 2009 Andras Mantia + + 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. +*/ + +#ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H +#define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H + +#include + +class QString; + +class ObjectSourcePrivate; +class ObjectTreeSource : public MessageViewer::ObjectTreeSourceIf +{ +public: + ObjectTreeSource(MessageViewer::HtmlWriter *writer, + MessageViewer::CSSHelperBase *cssHelper); + virtual ~ObjectTreeSource(); + void setHtmlLoadExternal(bool loadExternal); + void setHtmlMail(bool htmlMail); + bool htmlMail() const Q_DECL_OVERRIDE; + bool decryptMessage() const Q_DECL_OVERRIDE; + bool htmlLoadExternal() const Q_DECL_OVERRIDE; + bool showSignatureDetails() const Q_DECL_OVERRIDE; + void setHtmlMode(MessageViewer::Util::HtmlMode mode) Q_DECL_OVERRIDE; + void setAllowDecryption(bool allowDecryption); + int levelQuote() const Q_DECL_OVERRIDE; + const QTextCodec *overrideCodec() Q_DECL_OVERRIDE; + QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE; + const MessageViewer::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE; + MessageViewer::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE; + MessageViewer::CSSHelperBase *cssHelper() Q_DECL_OVERRIDE; + QObject *sourceObject() Q_DECL_OVERRIDE; + bool autoImportKeys() const Q_DECL_OVERRIDE; + bool showEmoticons() const Q_DECL_OVERRIDE; + bool showExpandQuotesMark() const Q_DECL_OVERRIDE; +private: + ObjectSourcePrivate *const d; +}; + +#endif + diff --git a/framework/domain/qmldir b/framework/domain/qmldir new file mode 100644 index 00000000..fd54e5ee --- /dev/null +++ b/framework/domain/qmldir @@ -0,0 +1,3 @@ +module org.kde.kube.mail + +plugin mailplugin diff --git a/framework/domain/retriever.cpp b/framework/domain/retriever.cpp new file mode 100644 index 00000000..b8e29523 --- /dev/null +++ b/framework/domain/retriever.cpp @@ -0,0 +1,55 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + + +#include "retriever.h" + +Retriever::Retriever(QObject *parent) : QObject(parent) +{ +} + +QAbstractItemModel* Retriever::model() const +{ + return mModel; +} + +void Retriever::setModel(QAbstractItemModel* model) +{ + mValue = QVariant(); + mModel = model; + connect(model, &QAbstractItemModel::rowsInserted, this, &Retriever::onRowsInserted); + connect(model, &QAbstractItemModel::modelReset, this, &Retriever::onModelReset); + if (model->rowCount(QModelIndex())) { + mValue = model->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1())); + emit valueChanged(); + } +} + +void Retriever::onRowsInserted(const QModelIndex &parent, int first, int last) +{ + if (!mValue.isValid()) { + mValue = mModel->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1())); + emit valueChanged(); + } +} + +void Retriever::onModelReset() +{ + mValue = QVariant(); +} diff --git a/framework/domain/retriever.h b/framework/domain/retriever.h new file mode 100644 index 00000000..e454532d --- /dev/null +++ b/framework/domain/retriever.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include +#include +#include + +/** + * A wrapper for a QAbstractItemModel to retrieve a value from a single index via property binding + * + * Assign a model that retrieves the index, set the property your interested in, and propery-bind "value". + */ +class Retriever : public QObject +{ + Q_OBJECT + Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel) + Q_PROPERTY(QString propertyName MEMBER mPropertyName) + Q_PROPERTY(QVariant value MEMBER mValue NOTIFY valueChanged) + +public: + explicit Retriever(QObject *parent = Q_NULLPTR); + + QAbstractItemModel* model() const; + void setModel(QAbstractItemModel* model); + +signals: + void valueChanged(); + +private slots: + void onRowsInserted(const QModelIndex &parent, int first, int last); + void onModelReset(); + +private: + QString mPropertyName; + QVariant mValue; + QAbstractItemModel *mModel; +}; diff --git a/framework/domain/singlemailcontroller.cpp b/framework/domain/singlemailcontroller.cpp new file mode 100644 index 00000000..8ee4acbb --- /dev/null +++ b/framework/domain/singlemailcontroller.cpp @@ -0,0 +1,46 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "singlemailcontroller.h" + +SingleMailController::SingleMailController(QObject *parent) : QObject(parent), m_model(new MailListModel) +{ + +} + +SingleMailController::~SingleMailController() +{ + +} + +MailListModel* SingleMailController::model() const +{ + return m_model.data(); +} + + +void SingleMailController::loadMail(const QString &id) +{ + Sink::Query query; + query.liveQuery = false; + query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage"; + query.ids << id.toLatin1(); + m_model->runQuery(query); +} \ No newline at end of file diff --git a/framework/domain/singlemailcontroller.h b/framework/domain/singlemailcontroller.h new file mode 100644 index 00000000..283b03c4 --- /dev/null +++ b/framework/domain/singlemailcontroller.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2016 Michael Bohlender + Copyright (c) 2016 Christian Mollekopf + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#pragma once + +#include "maillistmodel.h" + +#include +#include +#include +#include + +class SingleMailController : public QObject +{ + Q_OBJECT + Q_PROPERTY (MailListModel *model READ model CONSTANT) + +public: + explicit SingleMailController(QObject *parent = Q_NULLPTR); + ~SingleMailController(); + + MailListModel *model() const; + +Q_SIGNALS: + void messageChanged(); + +public slots: + void loadMail(const QString &id); + +private: + QScopedPointer m_model; +}; diff --git a/framework/domain/stringhtmlwriter.cpp b/framework/domain/stringhtmlwriter.cpp new file mode 100644 index 00000000..df108946 --- /dev/null +++ b/framework/domain/stringhtmlwriter.cpp @@ -0,0 +1,145 @@ +/* -*- c++ -*- + filehtmlwriter.cpp + + This file is part of KMail, the KDE mail client. + Copyright (c) 2003 Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "stringhtmlwriter.h" + +#include +#include +#include + +StringHtmlWriter::StringHtmlWriter() + : MessageViewer::HtmlWriter() + , mState(Ended) +{ +} + +StringHtmlWriter::~StringHtmlWriter() +{ +} + +void StringHtmlWriter::begin(const QString &css) +{ + if (mState != Ended) { + qWarning() << "begin() called on non-ended session!"; + reset(); + } + + mState = Begun; + mExtraHead.clear(); + mHtml.clear(); + + if (!css.isEmpty()) { + write(QLatin1String("\n")); + } +} + +void StringHtmlWriter::end() +{ + if (mState != Begun) { + qWarning() << "Called on non-begun or queued session!"; + } + + if (!mExtraHead.isEmpty()) { + insertExtraHead(); + mExtraHead.clear(); + } + resolveCidUrls(); + mState = Ended; +} + +void StringHtmlWriter::reset() +{ + if (mState != Ended) { + mHtml.clear(); + mExtraHead.clear(); + mState = Begun; // don't run into end()'s warning + end(); + mState = Ended; + } +} + +void StringHtmlWriter::write(const QString &str) +{ + if (mState != Begun) { + qWarning() << "Called in Ended or Queued state!"; + } + mHtml.append(str); +} + +void StringHtmlWriter::queue(const QString &str) +{ + write(str); +} + +void StringHtmlWriter::flush() +{ + mState = Begun; // don't run into end()'s warning + end(); +} + +void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) +{ + write("\n"); + mEmbeddedPartMap.insert(contentId, url); +} + +void StringHtmlWriter::resolveCidUrls() +{ + for (const auto &cid : mEmbeddedPartMap.keys()) { + mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); + } +} + +void StringHtmlWriter::extraHead(const QString &extraHead) +{ + if (mState != Ended) { + qWarning() << "Called on non-started session!"; + } + mExtraHead.append(extraHead); +} + + +void StringHtmlWriter::insertExtraHead() +{ + const QString headTag(QStringLiteral("")); + const int index = mHtml.indexOf(headTag); + if (index != -1) { + mHtml.insert(index + headTag.length(), mExtraHead); + } +} + +QString StringHtmlWriter::html() const +{ + if (mState != Ended) { + qWarning() << "Called on non-ended session!"; + } + return mHtml; +} diff --git a/framework/domain/stringhtmlwriter.h b/framework/domain/stringhtmlwriter.h new file mode 100644 index 00000000..fa0a7aa5 --- /dev/null +++ b/framework/domain/stringhtmlwriter.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- + + Copyright (c) 2016 Sandro Knauß + + Kube is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + Kube 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 + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ +#define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ + +#include + +#include +#include + +class QString; + +class StringHtmlWriter : public MessageViewer::HtmlWriter +{ +public: + explicit StringHtmlWriter(); + virtual ~StringHtmlWriter(); + + void begin(const QString &cssDefs) Q_DECL_OVERRIDE; + void end() Q_DECL_OVERRIDE; + void reset() Q_DECL_OVERRIDE; + void write(const QString &str) Q_DECL_OVERRIDE; + void queue(const QString &str) Q_DECL_OVERRIDE; + void flush() Q_DECL_OVERRIDE; + void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; + void extraHead(const QString &str) Q_DECL_OVERRIDE; + + QString html() const; +private: + void insertExtraHead(); + void resolveCidUrls(); + + QString mHtml; + QString mExtraHead; + enum State { + Begun, + Queued, + Ended + } mState; + QMap mEmbeddedPartMap; +}; + +#endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__ diff --git a/framework/mail/CMakeLists.txt b/framework/mail/CMakeLists.txt deleted file mode 100644 index 822b2981..00000000 --- a/framework/mail/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -set(mailplugin_SRCS - mailplugin.cpp - maillistcontroller.cpp - maillistmodel.cpp - singlemailcontroller.cpp - folderlistmodel.cpp - folderlistcontroller.cpp - actions/sinkactions.cpp - actions/mailactions.cpp - objecttreesource.cpp - stringhtmlwriter.cpp - csshelper.cpp - composer.cpp - messageparser.cpp - mailtransport.cpp - mailtemplates.cpp - retriever.cpp -) -add_definitions(-DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") - -find_package(CURL 7.20.0 REQUIRED) - -include_directories(${CURL_INCLUDE_DIRS}) - -add_library(mailplugin SHARED ${mailplugin_SRCS}) - -qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets) - -target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::Otp KF5::Codecs ${CURL_LIBRARIES}) - -install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail) -install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail) diff --git a/framework/mail/actions/mailactions.cpp b/framework/mail/actions/mailactions.cpp deleted file mode 100644 index dab0533e..00000000 --- a/framework/mail/actions/mailactions.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ -#include -#include - -#include "../mailtransport.h" -#include -#include -#include -#include - -using namespace Kube; - -static ActionHandlerHelper sendMailHandler("org.kde.kube.actions.sendmail", - [](Context *context) -> bool { - auto username = context->property("username").value(); - auto password = context->property("password").value(); - auto server = context->property("server").value(); - auto message = context->property("message").value(); - return !username.isEmpty() && !password.isEmpty() && !server.isEmpty() && message; - }, - [](Context *context) { - auto username = context->property("username").value(); - auto password = context->property("password").value(); - auto server = context->property("server").value(); - //For ssl use "smtps://mainserver.example.net - QByteArray cacert; // = "/path/to/certificate.pem"; - auto message = context->property("message").value(); - qWarning() << "Sending a mail: "; - MailTransport::sendMessage(message, server, username, password, cacert); - } -); diff --git a/framework/mail/actions/sinkactions.cpp b/framework/mail/actions/sinkactions.cpp deleted file mode 100644 index a19ab149..00000000 --- a/framework/mail/actions/sinkactions.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ -#include -#include - -#include - -using namespace Kube; - -static ActionHandlerHelper markAsReadHandler("org.kde.kube.actions.mark-as-read", - [](Context *context) -> bool { - return context->property("mail").isValid(); - }, - [](Context *context) { - auto mail = context->property("mail").value(); - if (!mail) { - qWarning() << "Failed to get the mail mail: " << context->property("mail"); - return; - } - mail->setProperty("unread", false); - qDebug() << "Mark as read " << mail->identifier(); - Sink::Store::modify(*mail).exec(); - } -); - -static ActionHandlerHelper deleteHandler("org.kde.kube.actions.delete", - [](Context *context) -> bool { - return context->property("mail").isValid(); - }, - [](Context *context) { - auto mail = context->property("mail").value(); - if (!mail) { - qWarning() << "Failed to get the mail mail: " << context->property("mail"); - return; - } - mail->setProperty("unread", false); - qDebug() << "Remove " << mail->identifier(); - Sink::Store::remove(*mail).exec(); - } -); - -static ActionHandlerHelper synchronizeHandler("org.kde.kube.actions.synchronize", - [](Context *context) -> bool { - return context->property("folder").isValid(); - }, - [](Context *context) { - auto folder = context->property("folder").value(); - if (!folder) { - qWarning() << "Failed to get the folder: " << context->property("folder"); - return; - } - Sink::Store::synchronize(Sink::Query::ResourceFilter(folder->resourceInstanceIdentifier())).exec(); - } -); - -// static ActionHandlerHelper saveAsDraft("org.kde.kube.actions.save-as-draft", -// [](Context *context) -> bool { -// return context->property("mail").isValid(); -// }, -// [](Context *context) { -// Sink::Query query; -// query += Sink::Query::RequestedProperties(QByteArrayList() << "name") -// //FIXME do something like specialuse? -// query += Sink::Query::PropertyFilter("name", "Drafts"); -// // query += Sink::Query::PropertyContainsFilter("specialuser", "drafts"); -// query += Sink::Query::PropertyFilter("drafts", true); -// //TODO Use drafts folder of that specific account -// Sink::Store::fetchAll(query) -// .then>([](const QList folders) { -// if (folders.isEmpty()) { -// return KAsync::start([]() { -// //If message is already existing, modify, otherwise create -// }); -// } -// }); -// //TODO -// // * Find drafts folder -// // * Store KMime::Message on disk for use in blob property -// // * Check if message is already existing and either create or update -// // * -// // auto mail = context->property("mail").value(); -// // if (!mail) { -// // qWarning() << "Failed to get the mail mail: " << context->property("mail"); -// // return; -// // } -// // mail->setProperty("unread", false); -// // qDebug() << "Mark as read " << mail->identifier(); -// // Sink::Store::modify(*mail).exec(); -// } -// ); diff --git a/framework/mail/composer.cpp b/framework/mail/composer.cpp deleted file mode 100644 index 2f4fe2e9..00000000 --- a/framework/mail/composer.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - - -#include "composer.h" -#include -#include -#include -#include -#include -#include -#include - -#include "mailtemplates.h" - -Composer::Composer(QObject *parent) : QObject(parent) -{ - m_identityModel << "Kuberich " << "Uni " << "Spam "; -} - -QString Composer::to() const -{ - return m_to; -} - -void Composer::setTo(const QString &to) -{ - if(m_to != to) { - m_to = to; - emit toChanged(); - } -} - -QString Composer::cc() const -{ - return m_cc; -} - -void Composer::setCc(const QString &cc) -{ - if(m_cc != cc) { - m_cc = cc; - emit ccChanged(); - } -} - -QString Composer::bcc() const -{ - return m_bcc; -} - -void Composer::setBcc(const QString &bcc) -{ - if(m_bcc != bcc) { - m_bcc = bcc; - emit bccChanged(); - } -} - -QString Composer::subject() const -{ - return m_subject; -} - -void Composer::setSubject(const QString &subject) -{ - if(m_subject != subject) { - m_subject = subject; - emit subjectChanged(); - } -} - -QString Composer::body() const -{ - return m_body; -} - -void Composer::setBody(const QString &body) -{ - if(m_body != body) { - m_body = body; - emit bodyChanged(); - } -} - -QStringList Composer::identityModel() const -{ - return m_identityModel; -} - -int Composer::fromIndex() const -{ - return m_fromIndex; -} - -void Composer::setFromIndex(int fromIndex) -{ - if(m_fromIndex != fromIndex) { - m_fromIndex = fromIndex; - emit fromIndexChanged(); - } -} - -QVariant Composer::originalMessage() const -{ - return m_originalMessage; -} - -void Composer::setOriginalMessage(const QVariant &originalMessage) -{ - const auto mailData = KMime::CRLFtoLF(originalMessage.toByteArray()); - if (!mailData.isEmpty()) { - KMime::Message::Ptr mail(new KMime::Message); - mail->setContent(mailData); - mail->parse(); - auto reply = MailTemplates::reply(mail); - //We assume reply - setTo(reply->to(true)->asUnicodeString()); - setCc(reply->cc(true)->asUnicodeString()); - setSubject(reply->subject(true)->asUnicodeString()); - setBody(reply->body()); - m_msg = QVariant::fromValue(reply); - } else { - m_msg = QVariant(); - } -} - -KMime::Message::Ptr Composer::assembleMessage() -{ - auto mail = m_msg.value(); - if (!mail) { - mail = KMime::Message::Ptr::create(); - } - for (const auto &to : KEmailAddress::splitAddressList(m_to)) { - QByteArray displayName; - QByteArray addrSpec; - QByteArray comment; - KEmailAddress::splitAddress(to.toUtf8(), displayName, addrSpec, comment); - mail->to(true)->addAddress(addrSpec, displayName); - } - mail->subject(true)->fromUnicodeString(m_subject, "utf-8"); - mail->setBody(m_body.toUtf8()); - mail->assemble(); - return mail; -} - -void Composer::send() -{ - auto mail = assembleMessage(); - Kube::ApplicationContext settings; - auto account = settings.currentAccount(); - auto identity = account.primaryIdentity(); - auto transport = identity.transport(); - - Kube::Context context; - context.setProperty("message", QVariant::fromValue(mail)); - - context.setProperty("username", transport.username()); - context.setProperty("password", transport.password()); - context.setProperty("server", transport.server()); - - Kube::Action("org.kde.kube.actions.sendmail", context).execute(); - clear(); -} - -void Composer::saveAsDraft() -{ - auto mail = assembleMessage(); - Kube::Context context; - context.setProperty("message", QVariant::fromValue(mail)); - Kube::Action("org.kde.kube.actions.saveasdraft", context).execute(); - clear(); -} - -void Composer::clear() -{ - setSubject(""); - setBody(""); - setTo(""); - setCc(""); - setBcc(""); - setFromIndex(-1); -} diff --git a/framework/mail/composer.h b/framework/mail/composer.h deleted file mode 100644 index dd066b2e..00000000 --- a/framework/mail/composer.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include -#include - -namespace KMime { -class Message; -} - -class Composer : public QObject -{ - Q_OBJECT - Q_PROPERTY (QVariant originalMessage READ originalMessage WRITE setOriginalMessage) - Q_PROPERTY (QString to READ to WRITE setTo NOTIFY toChanged) - Q_PROPERTY (QString cc READ cc WRITE setCc NOTIFY ccChanged) - Q_PROPERTY (QString bcc READ bcc WRITE setBcc NOTIFY bccChanged) - Q_PROPERTY (QString subject READ subject WRITE setSubject NOTIFY subjectChanged) - Q_PROPERTY (QString body READ body WRITE setBody NOTIFY bodyChanged) - Q_PROPERTY (QStringList identityModel READ identityModel) - Q_PROPERTY (int fromIndex READ fromIndex WRITE setFromIndex NOTIFY fromIndexChanged) - -public: - explicit Composer(QObject *parent = Q_NULLPTR); - - QString to() const; - void setTo(const QString &to); - - QString cc() const; - void setCc(const QString &cc); - - QString bcc() const; - void setBcc(const QString &bcc); - - QString subject() const; - void setSubject(const QString &subject); - - QString body() const; - void setBody(const QString &body); - - QStringList identityModel() const; - - int fromIndex() const; - void setFromIndex(int fromIndex); - - QVariant originalMessage() const; - void setOriginalMessage(const QVariant &originalMessage); - -signals: - void subjectChanged(); - void bodyChanged(); - void toChanged(); - void ccChanged(); - void bccChanged(); - void fromIndexChanged(); - -public slots: - void send(); - void saveAsDraft(); - void clear(); - -private: - QSharedPointer assembleMessage(); - QString m_to; - QString m_cc; - QString m_bcc; - QString m_subject; - QString m_body; - QStringList m_identityModel; - int m_fromIndex; - QVariant m_originalMessage; - QVariant m_msg; -}; diff --git a/framework/mail/csshelper.cpp b/framework/mail/csshelper.cpp deleted file mode 100644 index a6355c57..00000000 --- a/framework/mail/csshelper.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - csshelper.cpp - - This file is part of KMail, the KDE mail client. - Copyright (c) 2003 Marc Mutz - - KMail is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - KMail 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 - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#include "csshelper.h" - -#include -#include -#include -#include -#include -#include - -CSSHelper::CSSHelper(const QPaintDevice *pd) : - MessageViewer::CSSHelperBase(pd) -{ - -} - -QString cssDefinitions() -{ - QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + "mail.css"); - if (file.open(QFile::ReadOnly)) { - return file.readAll(); - } - return QString(); -} - -QString CSSHelper::htmlHead(bool fixed) const -{ - return - QLatin1String("\n" - "\n" - "\n"); -} \ No newline at end of file diff --git a/framework/mail/csshelper.h b/framework/mail/csshelper.h deleted file mode 100644 index 775014e3..00000000 --- a/framework/mail/csshelper.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- c++ -*- - csshelper.h - - This file is part of KMail, the KDE mail client. - Copyright (c) 2003 Marc Mutz - - KMail is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - KMail 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 - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#pragma once - -#include - -class CSSHelper : public MessageViewer::CSSHelperBase -{ -public: - explicit CSSHelper(const QPaintDevice *pd); - - /** @return HTML head including style sheet definitions and the - >body< tag */ - QString htmlHead(bool fixedFont = false) const Q_DECL_OVERRIDE; -}; \ No newline at end of file diff --git a/framework/mail/data/mail.css b/framework/mail/data/mail.css deleted file mode 100644 index b77e36ee..00000000 --- a/framework/mail/data/mail.css +++ /dev/null @@ -1,298 +0,0 @@ -div.header { - margin-bottom: 10pt ! important; -} - -table.textAtm { - margin-top: 10pt ! important; - margin-bottom: 10pt ! important; -} - -tr.textAtmH, -tr.textAtmB, -tr.rfc822B { - font-weight: normal ! important; -} - -tr.signInProgressH, -tr.rfc822H, -tr.encrH, -tr.signOkKeyOkH, -tr.signOkKeyBadH, -tr.signWarnH, -tr.sign -ErrH { - font-weight: bold ! important; -} - -tr.textAtmH td, -tr.textAtmB td { - padding: 3px ! important; -} - -table.rfc822 { - width: 100% ! important; - border: solid 1px black ! important; - margin-top: 10pt ! important; - margin-bottom: 10pt ! important; -} - -table.textAtm, -table.encr, -table.signWarn, -table.signErr, -table.signOkKeyBad, -table.signOkKeyOk, -table.signInProgress, -div.fancy.header table { - width: 100% ! important; - border-width: 0px ! important; - line-height: normal; -} - -div.htmlWarn { - margin: 0px 5% ! important; - padding: 10px ! important; - text-align: left ! important; - line-height: normal; -} - -div.fancy.header > div { - font-weight: bold ! important; - padding: 4px ! important; - line-height: normal; -} - -div.fancy.header table { - padding: 2px ! important; - text-align: left ! important; - border-collapse: separate ! important; -} - -div.fancy.header table th { - font-family: "Helvetica" ! important; - font-size: 12pt; - padding: 0px ! important; - white-space: nowrap ! important; - border-spacing: 0px ! important; - text-align: left ! important; - vertical-align: top ! important; - background-color: #efebe7 ! important; - color: #000000 ! important; - border: 1px ! important; -} - -div.fancy.header table td { - font-family: "Helvetica" ! important; - font-size: 12pt; - padding: 0px ! important; - border-spacing: 0px ! important; - text-align: left ! important; - vertical-align: top ! important; - width: 100% ! important; - background-color: #efebe7 ! important; - color: #000000 ! important; - border: 1px ! important; -} - -div.fancy.header table a:hover { - background-color: transparent ! important; -} - -span.pimsmileytext { - position: absolute; - top: 0px; - left: 0px; - visibility: hidden; -} - -img.pimsmileyimg { -} - -div.quotelevelmark { - position: absolute; - margin-left:-10px; -} - -body { - font-family: "Helvetica" ! important; - font-size: 12pt; - color: #000000 ! important; - background-color: #ffffff ! important; -} - -a { - color: #0000cc ! important; - text-decoration: none ! important; -} - -a.white { - color: white ! important; -} - -a.black { - color: black ! important; -} - -table.textAtm { background-color: #000000 ! important; } - -tr.textAtmH { - background-color: #ffffff ! important; - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -tr.textAtmB { - background-color: #ffffff ! important; -} - -table.signInProgress, -table.rfc822 { - background-color: #ffffff ! important -; -} - -tr.signInProgressH, -tr.rfc822H { - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -table.encr { - background-color: #0010cc ! important; -} - -tr.encrH { - background-color: #1010ee ! important; - color: #aaaaaa ! important; - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -tr.encrB { background-color: #ffe0e0 ! important; } - -table.signOkKeyOk { - background-color: #00cc00 ! important; -} - -tr.signOkKeyOkH { - background-color: #00ff00 ! important; - color: #000000 ! important; - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -tr.signOkKeyOkB { background-color: #e0ffe0 ! important; } - -table.signOkKeyBad { - background-color: #00cc00 ! important; -} - -tr.signOkKeyBadH { - background-color: #00ff00 ! important; - color: #000000 ! important; - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -tr.signOkKeyBadB { background-color: #e0ffe0 ! important; } - -table.signWarn { - background-color: #cc0 ! important; -} - -tr.signWarnH { - background-color: #fc0 ! important; - color: #000000 ! important; - font-family: "Helvetica" ! imp -ortant; - font-size: 12pt; -} - -tr.signWarnB { background-color: #e0e0ff ! important; } - -table.signErr { - background-color: #c00 ! important; -} - -tr.signErrH { - background-color: #0f00 ! important; - color: #0000 -00 ! important; - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -tr.signErrB { background-color: #d3d3f0 ! important; } - -div.htmlWarn { - border: 2px solid #00001a ! important; - line-height: normal; -} - -div.header { - font-family: "Helvetica" ! important; - font-size: 12pt; -} - -div.fancy.header > div { - background-color: #308cc6 ! important; - color: #ffffff ! important; - border: solid #000000 1px ! important; - line-height: normal; -} - -div.fancy.header > div a[href] { color: #ffffff ! important; } - -div.fancy.header > div a[href]:hover { text-decoration: underline ! important; } - -div.fancy.header > div.spamheader { - background-color: #cdcdcd ! important; - border-top: 0px ! important; - padding: 3px ! important; - color: black ! important; - font-weight: bold ! important; - font-size: 12pt; -} - -div.fancy.header > table.outer { - background-color: #efebe7 ! important; - color: #000000 ! important; - border-bottom: solid #000000 1px ! important; - border-left: solid #000000 1px ! important; - border-right: solid #000000 1px ! important; -} - -div.senderpic{ - padding: 0px ! important; - font-size:0.8em ! important; - border:1px solid #b8b5b2 ! important; - background-color:#efebe7 ! important; -} - -div.senderstatus{ - text-align:center ! important; -} - -div.quotelevel1 { - color: #100000 ! important; -} - -div.quotelevel2 { - color: #200000 ! important; -} - -div.quotelevel3 { - color: #300000 ! important; -} - -div.deepquotelevel1 { - color: #100000 ! important; -} - -div.deepquotelevel2 { - color: #200000 ! important; -} - -div.deepquotelevel3 { - color: #300000 ! important; -} diff --git a/framework/mail/folderlistcontroller.cpp b/framework/mail/folderlistcontroller.cpp deleted file mode 100644 index 46a6f648..00000000 --- a/framework/mail/folderlistcontroller.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "folderlistcontroller.h" - -#include "folderlistmodel.h" - -#include - -FolderListController::FolderListController(QObject *parent) : QObject(parent), m_model(new FolderListModel) -{ - -} - -QString FolderListController::accountId() const -{ - return m_accountId; -} - -void FolderListController::setAccountId(const QString &id) -{ - if(m_accountId != id) { - m_accountId = id; - - loadFolders(id); - - emit accountIdChanged(); - } -} - -FolderListModel* FolderListController::model() const -{ - return m_model.data(); -} - -void FolderListController::loadFolders(const QString &id) -{ - //load foldermodel from sink - -} - - -void FolderListController::addFolder(const QString &name) -{ - qDebug() << "User Action: add folder " << name; -} - -void FolderListController::deleteFolder(const QString &id) -{ - qDebug() << "User Action: delete folder " << id; -} - diff --git a/framework/mail/folderlistcontroller.h b/framework/mail/folderlistcontroller.h deleted file mode 100644 index 11057f21..00000000 --- a/framework/mail/folderlistcontroller.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include "folderlistmodel.h" - -#include -#include -#include - -class FolderListController : public QObject -{ - Q_OBJECT - Q_PROPERTY (QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged) - Q_PROPERTY (FolderListModel *model READ model CONSTANT) - -public: - explicit FolderListController(QObject *parent = Q_NULLPTR); - - QString accountId() const; - void setAccountId(const QString &id); - - FolderListModel *model() const; - - void loadFolders(const QString &id); - -signals: - void accountIdChanged(); - -public slots: - void deleteFolder(const QString &id); - void addFolder(const QString &name); - - -private: - QString m_accountId; - QScopedPointer m_model; -}; diff --git a/framework/mail/folderlistmodel.cpp b/framework/mail/folderlistmodel.cpp deleted file mode 100644 index ce6fb4fd..00000000 --- a/framework/mail/folderlistmodel.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "folderlistmodel.h" -#include - -FolderListModel::FolderListModel(QObject *parent) : QIdentityProxyModel() -{ - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "name" << "icon" << "parent"; - query.parentProperty = "parent"; - mModel = Sink::Store::loadModel(query); - setSourceModel(mModel.data()); -} - -FolderListModel::~FolderListModel() -{ - -} - -QHash< int, QByteArray > FolderListModel::roleNames() const -{ - QHash roles; - - roles[Name] = "name"; - roles[Icon] = "icon"; - roles[Id] = "id"; - roles[DomainObject] = "domainObject"; - - return roles; -} - -QVariant FolderListModel::data(const QModelIndex &idx, int role) const -{ - auto srcIdx = mapToSource(idx); - switch (role) { - case Name: - return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString(); - case Icon: - return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString(); - case Id: - return srcIdx.data(Sink::Store::DomainObjectBaseRole).value()->identifier(); - case DomainObject: - return srcIdx.data(Sink::Store::DomainObjectRole); - } - return QIdentityProxyModel::data(idx, role); -} diff --git a/framework/mail/folderlistmodel.h b/framework/mail/folderlistmodel.h deleted file mode 100644 index 7844e59a..00000000 --- a/framework/mail/folderlistmodel.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include -#include - -class FolderListModel : public QIdentityProxyModel -{ - Q_OBJECT - -public: - FolderListModel(QObject *parent = Q_NULLPTR); - ~FolderListModel(); - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - - enum Roles { - Name = Qt::UserRole + 1, - Icon, - Id, - DomainObject - }; - Q_ENUMS(Roles) - - QHash roleNames() const; - -private: - QSharedPointer mModel; -}; diff --git a/framework/mail/maillistcontroller.cpp b/framework/mail/maillistcontroller.cpp deleted file mode 100644 index a4bd6436..00000000 --- a/framework/mail/maillistcontroller.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "maillistcontroller.h" - -#include - -#include - -#include "maillistmodel.h" - -MailListController::MailListController(QObject *parent) : QObject(parent), m_model(new MailListModel) -{ -} - -MailListModel *MailListController::model() const -{ - return m_model.data(); - -} - -void MailListController::loadAllMail() -{ - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; - m_model->runQuery(query); -} - -void MailListController::loadMailFolder(const QString &folderId) -{ - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder"; - query.propertyFilter.insert("folder", folderId.toLatin1()); - m_model->runQuery(query); -} - -void MailListController::loadUnreadMail() -{ - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; - query.propertyFilter.insert("unread", true); - m_model->runQuery(query); -} - -void MailListController::loadImportantMail() -{ - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important"; - query.propertyFilter.insert("important", true); - m_model->runQuery(query); -} - -QString MailListController::selectedMail() const -{ - return m_selectedMail; -} - -void MailListController::setSelectedMail(const QString& id) -{ - if (m_selectedMail != id) { - m_selectedMail = id; - emit selectedMailChanged(); - } -} - -void MailListController::markMailImportant(bool important) -{ - qDebug() << "user action: mark mail important "; -} - -void MailListController::markMailUnread(bool unread) -{ - qDebug() << "user action: mark mail unread "; -} - -void MailListController::deleteMail() -{ - qDebug() << "user action: delete mail"; -} - diff --git a/framework/mail/maillistcontroller.h b/framework/mail/maillistcontroller.h deleted file mode 100644 index 959c63a3..00000000 --- a/framework/mail/maillistcontroller.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include "maillistmodel.h" - -#include -#include -#include -#include - -class MailListController : public QObject -{ - Q_OBJECT - Q_PROPERTY (MailListModel *model READ model CONSTANT) - Q_PROPERTY (QString selectedMail READ selectedMail WRITE setSelectedMail NOTIFY selectedMailChanged) - -public: - explicit MailListController(QObject *parent = Q_NULLPTR); - - MailListModel *model() const; - - QString selectedMail() const; - void setSelectedMail(const QString &id); - -signals: - void selectedMailChanged(); - -public slots: - void loadAllMail(); - void loadUnreadMail(); - void loadImportantMail(); - void loadMailFolder(const QString &folderId); - - void markMailImportant(bool important); - void markMailUnread(bool unread); - void deleteMail(); - -private: - QScopedPointer m_model; - - QString m_selectedMail; -}; diff --git a/framework/mail/maillistmodel.cpp b/framework/mail/maillistmodel.cpp deleted file mode 100644 index b46fabf8..00000000 --- a/framework/mail/maillistmodel.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "maillistmodel.h" - -#include -#include - - -MailListModel::MailListModel(QObject *parent) - : QSortFilterProxyModel() -{ - setDynamicSortFilter(true); - sort(0, Qt::DescendingOrder); -} - -MailListModel::~MailListModel() -{ - -} - -QHash< int, QByteArray > MailListModel::roleNames() const -{ - QHash roles; - - roles[Subject] = "subject"; - roles[Sender] = "sender"; - roles[SenderName] = "senderName"; - roles[Date] = "date"; - roles[Unread] = "unread"; - roles[Important] = "important"; - roles[Id] = "id"; - roles[MimeMessage] = "mimeMessage"; - roles[DomainObject] = "domainObject"; - - return roles; -} - -QVariant MailListModel::data(const QModelIndex &idx, int role) const -{ - auto srcIdx = mapToSource(idx); - switch (role) { - case Subject: - return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString(); - case Sender: - return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString(); - case SenderName: - return srcIdx.sibling(srcIdx.row(), 2).data(Qt::DisplayRole).toString(); - case Date: - return srcIdx.sibling(srcIdx.row(), 3).data(Qt::DisplayRole).toString(); - case Unread: - return srcIdx.sibling(srcIdx.row(), 4).data(Qt::DisplayRole).toBool(); - case Important: - return srcIdx.sibling(srcIdx.row(), 5).data(Qt::DisplayRole).toBool(); - case Id: - return srcIdx.data(Sink::Store::DomainObjectBaseRole).value()->identifier(); - case DomainObject: - return srcIdx.data(Sink::Store::DomainObjectRole); - case MimeMessage: { - auto filename = srcIdx.sibling(srcIdx.row(), 6).data(Qt::DisplayRole).toString(); - QFile file(filename); - if (file.open(QFile::ReadOnly)) { - auto content = file.readAll(); - qWarning() << filename << content; - return content; - } else { - qWarning() << "Failed to open the file"; - } - return "Failed to read mail."; - } - } - return QSortFilterProxyModel::data(idx, role); -} - -bool MailListModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - const QVariant leftData = left.sibling(left.row(), 3).data(Qt::DisplayRole); - const QVariant rightData = right.sibling(right.row(), 3).data(Qt::DisplayRole); - return leftData.toDateTime() < rightData.toDateTime(); -} - -void MailListModel::runQuery(const Sink::Query &query) -{ - m_model = Sink::Store::loadModel(query); - setSourceModel(m_model.data()); -} - -void MailListModel::setParentFolder(const QVariant &parentFolder) -{ - auto folder = parentFolder.value(); - if (!folder) { - qWarning() << "No folder: " << parentFolder; - return; - } - Sink::Query query; - query.liveQuery = true; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder"; - query.propertyFilter.insert("folder", folder->identifier()); - query.resources << folder->resourceInstanceIdentifier(); - query.sortProperty = "date"; - query.limit = 100; - qWarning() << "Running folder query: " << folder->resourceInstanceIdentifier() << folder->identifier(); - runQuery(query); -} - -QVariant MailListModel::parentFolder() const -{ - return QVariant(); -} - -void MailListModel::setMail(const QVariant &variant) -{ - auto mail = variant.value(); - if (!mail) { - qWarning() << "No mail: " << mail; - return; - } - Sink::Query query; - query.liveQuery = false; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage"; - query.ids << mail->identifier(); - query.resources << mail->resourceInstanceIdentifier(); - qWarning() << "Running mail query: " << mail->resourceInstanceIdentifier() << mail->identifier(); - runQuery(query); -} - -QVariant MailListModel::mail() const -{ - return QVariant(); -} - - diff --git a/framework/mail/maillistmodel.h b/framework/mail/maillistmodel.h deleted file mode 100644 index 47a2a091..00000000 --- a/framework/mail/maillistmodel.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include - -#include -#include -#include - -class MailListModel : public QSortFilterProxyModel -{ - Q_OBJECT - Q_PROPERTY (QVariant parentFolder READ parentFolder WRITE setParentFolder) - Q_PROPERTY (QVariant mail READ mail WRITE setMail) - -public: - MailListModel(QObject *parent = Q_NULLPTR); - ~MailListModel(); - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - - bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; - - enum Roles { - Subject = Qt::UserRole + 1, - Sender, - SenderName, - Date, - Unread, - Important, - Id, - MimeMessage, - DomainObject - }; - - QHash roleNames() const; - - void runQuery(const Sink::Query &query); - - void setParentFolder(const QVariant &parentFolder); - QVariant parentFolder() const; - - void setMail(const QVariant &mail); - QVariant mail() const; -private: - QSharedPointer m_model; -}; diff --git a/framework/mail/mailplugin.cpp b/framework/mail/mailplugin.cpp deleted file mode 100644 index 2d19a437..00000000 --- a/framework/mail/mailplugin.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "mailplugin.h" - -#include "maillistmodel.h" -#include "folderlistmodel.h" -#include "composer.h" -#include "messageparser.h" -#include "retriever.h" - -#include - -void MailPlugin::registerTypes (const char *uri) -{ - Q_ASSERT(uri == QLatin1String("org.kde.kube.mail")); - - qmlRegisterType(uri, 1, 0, "FolderListModel"); - qmlRegisterType(uri, 1, 0, "MailListModel"); - qmlRegisterType(uri, 1, 0, "Composer"); - qmlRegisterType(uri, 1, 0, "MessageParser"); - qmlRegisterType(uri, 1, 0, "Retriever"); -} diff --git a/framework/mail/mailplugin.h b/framework/mail/mailplugin.h deleted file mode 100644 index ebd091ee..00000000 --- a/framework/mail/mailplugin.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include - -class MailPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") - -public: - virtual void registerTypes(const char *uri); -}; \ No newline at end of file diff --git a/framework/mail/mailtemplates.cpp b/framework/mail/mailtemplates.cpp deleted file mode 100644 index e5ee8533..00000000 --- a/framework/mail/mailtemplates.cpp +++ /dev/null @@ -1,804 +0,0 @@ -/* - Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com - Copyright (c) 2010 Leo Franchi - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ -#include "mailtemplates.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "stringhtmlwriter.h" -#include "objecttreesource.h" -#include "csshelper.h" - -#include - -namespace KMime { - namespace Types { -static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right) -{ - return (left.asString() == right.asString()); -} - -static bool operator==(const KMime::Types::Mailbox &left, const KMime::Types::Mailbox &right) -{ - return (left.addrSpec().asString() == right.addrSpec().asString()); -} - } -} - -static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me) -{ - KMime::Types::Mailbox::List addresses(list); - for (KMime::Types::Mailbox::List::Iterator it = addresses.begin(); it != addresses.end();) { - if (me.contains(it->addrSpec())) { - it = addresses.erase(it); - } else { - ++it; - } - } - - return addresses; -} - -void initHeader(const KMime::Message::Ptr &message) -{ - message->removeHeader(); - message->removeHeader(); - message->date()->setDateTime(QDateTime::currentDateTime()); - - const QStringList extraInfo = QStringList() << QSysInfo::prettyProductName(); - message->userAgent()->fromUnicodeString(QString("%1/%2(%3)").arg(QString::fromLocal8Bit("Kube")).arg("0.1").arg(extraInfo.join(",")), "utf-8"); - // This will allow to change Content-Type: - message->contentType()->setMimeType("text/plain"); -} - -QString replacePrefixes(const QString &str, const QStringList &prefixRegExps, - bool replace, const QString &newPrefix) -{ - bool recognized = false; - // construct a big regexp that - // 1. is anchored to the beginning of str (sans whitespace) - // 2. matches at least one of the part regexps in prefixRegExps - QString bigRegExp = QStringLiteral("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QStringLiteral(")|(?:"))); - QRegExp rx(bigRegExp, Qt::CaseInsensitive); - if (rx.isValid()) { - QString tmp = str; - if (rx.indexIn(tmp) == 0) { - recognized = true; - if (replace) { - return tmp.replace(0, rx.matchedLength(), newPrefix + QLatin1String(" ")); - } - } - } else { - qWarning() << "bigRegExp = \"" - << bigRegExp << "\"\n" - << "prefix regexp is invalid!"; - // try good ole Re/Fwd: - recognized = str.startsWith(newPrefix); - } - - if (!recognized) { - return newPrefix + QLatin1String(" ") + str; - } else { - return str; - } -} - -QString cleanSubject(const KMime::Message::Ptr &msg, const QStringList &prefixRegExps, bool replace, const QString &newPrefix) -{ - return replacePrefixes(msg->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix); -} - -QString forwardSubject(const KMime::Message::Ptr &msg) -{ - bool replaceForwardPrefix = true; - QStringList forwardPrefixes; - forwardPrefixes << "Fwd:"; - forwardPrefixes << "FW:"; - return cleanSubject(msg, forwardPrefixes, replaceForwardPrefix, QStringLiteral("Fwd:")); -} - -QString replySubject(const KMime::Message::Ptr &msg) -{ - bool replaceReplyPrefix = true; - QStringList replyPrefixes; - //We're escaping the regex escape sequences. awesome - replyPrefixes << "Re\\\\s*:"; - replyPrefixes << "Re[\\\\d+\\\\]:"; - replyPrefixes << "Re\\\\d+:"; - return cleanSubject(msg, replyPrefixes, replaceReplyPrefix, QStringLiteral("Re:")); -} - -QByteArray getRefStr(const KMime::Message::Ptr &msg) -{ - QByteArray firstRef, lastRef, refStr, retRefStr; - int i, j; - - if (auto hdr = msg->references(false)) { - refStr = hdr->as7BitString(false).trimmed(); - } - - if (refStr.isEmpty()) { - return msg->messageID()->as7BitString(false); - } - - i = refStr.indexOf('<'); - j = refStr.indexOf('>'); - firstRef = refStr.mid(i, j - i + 1); - if (!firstRef.isEmpty()) { - retRefStr = firstRef + ' '; - } - - i = refStr.lastIndexOf('<'); - j = refStr.lastIndexOf('>'); - - lastRef = refStr.mid(i, j - i + 1); - if (!lastRef.isEmpty() && lastRef != firstRef) { - retRefStr += lastRef + ' '; - } - - retRefStr += msg->messageID()->as7BitString(false); - return retRefStr; -} - -KMime::Content *createPlainPartContent(const KMime::Message::Ptr &msg, const QString &plainBody) -{ - KMime::Content *textPart = new KMime::Content(msg.data()); - textPart->contentType()->setMimeType("text/plain"); - //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text - // QTextCodec *charset = selectCharset(m_charsets, plainBody); - // textPart->contentType()->setCharset(charset->name()); - textPart->contentType()->setCharset("utf-8"); - textPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); - textPart->fromUnicodeString(plainBody); - return textPart; -} - -KMime::Content *createMultipartAlternativeContent(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody) -{ - KMime::Content *multipartAlternative = new KMime::Content(msg.data()); - multipartAlternative->contentType()->setMimeType("multipart/alternative"); - const QByteArray boundary = KMime::multiPartBoundary(); - multipartAlternative->contentType()->setBoundary(boundary); - - KMime::Content *textPart = createPlainPartContent(msg, plainBody); - multipartAlternative->addContent(textPart); - - KMime::Content *htmlPart = new KMime::Content(msg.data()); - htmlPart->contentType()->setMimeType("text/html"); - //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text - // QTextCodec *charset = selectCharset(m_charsets, htmlBody); - // htmlPart->contentType()->setCharset(charset->name()); - textPart->contentType()->setCharset("utf-8"); - htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit); - htmlPart->fromUnicodeString(htmlBody); - multipartAlternative->addContent(htmlPart); - - return multipartAlternative; -} - -void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward) -{ - //FIXME - // MessageCore::ImageCollector ic; - // ic.collectImagesFrom(mOrigMsg.data()); - - // Now, delete the old content and set the new content, which - // is either only the new text or the new text with some attachments. - auto parts = msg->contents(); - foreach (KMime::Content *content, parts) { - msg->removeContent(content, true/*delete*/); - } - - msg->contentType()->clear(); // to get rid of old boundary - - const QByteArray boundary = KMime::multiPartBoundary(); - KMime::Content *const mainTextPart = - htmlBody.isEmpty() ? - createPlainPartContent(msg, plainBody) : - createMultipartAlternativeContent(msg, plainBody, htmlBody); - mainTextPart->assemble(); - - KMime::Content *textPart = mainTextPart; - // if (!ic.images().empty()) { - // textPart = createMultipartRelated(ic, mainTextPart); - // textPart->assemble(); - // } - - // If we have some attachments, create a multipart/mixed mail and - // add the normal body as well as the attachments - KMime::Content *mainPart = textPart; - //FIXME - // if (forward) { - // auto attachments = mOrigMsg->attachments(); - // attachments += mOtp->nodeHelper()->attachmentsOfExtraContents(); - // if (!attachments.isEmpty()) { - // mainPart = createMultipartMixed(attachments, textPart); - // mainPart->assemble(); - // } - // } - - msg->setBody(mainPart->encodedBody()); - msg->setHeader(mainPart->contentType()); - msg->setHeader(mainPart->contentTransferEncoding()); - msg->assemble(); - msg->parse(); -} - -QString plainToHtml(const QString &body) -{ - QString str = body; - str = str.toHtmlEscaped(); - str.replace(QStringLiteral("\n"), QStringLiteral("
\n")); - return str; -} - -//TODO implement this function using a DOM tree parser -void makeValidHtml(QString &body, const QString &headElement) -{ - QRegExp regEx; - regEx.setMinimal(true); - regEx.setPattern(QStringLiteral("")); - - if (!body.isEmpty() && !body.contains(regEx)) { - regEx.setPattern(QStringLiteral("")); - if (!body.contains(regEx)) { - body = QLatin1String("") + body + QLatin1String("
"); - } - regEx.setPattern(QStringLiteral("")); - if (!body.contains(regEx)) { - body = QLatin1String("") + headElement + QLatin1String("") + body; - } - body = QLatin1String("") + body + QLatin1String(""); - } -} - -QString stripSignature(const QString &msg) -{ - // Following RFC 3676, only > before -- - // I prefer to not delete a SB instead of delete good mail content. - const QRegExp sbDelimiterSearch = QRegExp(QLatin1String("(^|\n)[> ]*-- \n")); - // The regular expression to look for prefix change - const QRegExp commonReplySearch = QRegExp(QLatin1String("^[ ]*>")); - - QString res = msg; - int posDeletingStart = 1; // to start looking at 0 - - // While there are SB delimiters (start looking just before the deleted SB) - while ((posDeletingStart = res.indexOf(sbDelimiterSearch, posDeletingStart - 1)) >= 0) { - QString prefix; // the current prefix - QString line; // the line to check if is part of the SB - int posNewLine = -1; - - // Look for the SB beginning - int posSignatureBlock = res.indexOf(QLatin1Char('-'), posDeletingStart); - // The prefix before "-- "$ - if (res.at(posDeletingStart) == QLatin1Char('\n')) { - ++posDeletingStart; - } - - prefix = res.mid(posDeletingStart, posSignatureBlock - posDeletingStart); - posNewLine = res.indexOf(QLatin1Char('\n'), posSignatureBlock) + 1; - - // now go to the end of the SB - while (posNewLine < res.size() && posNewLine > 0) { - // handle the undefined case for mid ( x , -n ) where n>1 - int nextPosNewLine = res.indexOf(QLatin1Char('\n'), posNewLine); - - if (nextPosNewLine < 0) { - nextPosNewLine = posNewLine - 1; - } - - line = res.mid(posNewLine, nextPosNewLine - posNewLine); - - // check when the SB ends: - // * does not starts with prefix or - // * starts with prefix+(any substring of prefix) - if ((prefix.isEmpty() && line.indexOf(commonReplySearch) < 0) || - (!prefix.isEmpty() && line.startsWith(prefix) && - line.mid(prefix.size()).indexOf(commonReplySearch) < 0)) { - posNewLine = res.indexOf(QLatin1Char('\n'), posNewLine) + 1; - } else { - break; // end of the SB - } - } - - // remove the SB or truncate when is the last SB - if (posNewLine > 0) { - res.remove(posDeletingStart, posNewLine - posDeletingStart); - } else { - res.truncate(posDeletingStart); - } - } - - return res; -} - -QString plainMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature) -{ - QString result = otp.plainTextContent(); - if (result.isEmpty()) { //HTML-only mails - QWebPage doc; - doc.mainFrame()->setHtml(otp.htmlContent()); - result = doc.mainFrame()->toPlainText(); - } - - if (aStripSignature) { - result = stripSignature(result); - } - - return result; -} - -QString htmlMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature, QString &headElement) -{ - QString htmlElement = otp.htmlContent(); - - if (htmlElement.isEmpty()) { //plain mails only - QString htmlReplace = otp.plainTextContent().toHtmlEscaped(); - htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("
")); - htmlElement = QStringLiteral("%1\n").arg(htmlReplace); - } - - //QWebPage relies on this - Q_ASSERT(QApplication::style()); - QWebPage page; - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); - page.settings()->setAttribute(QWebSettings::JavaEnabled, false); - page.settings()->setAttribute(QWebSettings::PluginsEnabled, false); - page.settings()->setAttribute(QWebSettings::AutoLoadImages, false); - - page.currentFrame()->setHtml(htmlElement); - - //TODO to be tested/verified if this is not an issue - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, true); - const QString bodyElement = page.currentFrame()->evaluateJavaScript( - QStringLiteral("document.getElementsByTagName('body')[0].innerHTML")).toString(); - - headElement = page.currentFrame()->evaluateJavaScript( - QStringLiteral("document.getElementsByTagName('head')[0].innerHTML")).toString(); - - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); - - if (!bodyElement.isEmpty()) { - if (aStripSignature) { - //FIXME strip signature works partially for HTML mails - return stripSignature(bodyElement); - } - return bodyElement; - } - - if (aStripSignature) { - //FIXME strip signature works partially for HTML mails - return stripSignature(htmlElement); - } - return htmlElement; -} - -QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString) -{ - QString result; - - if (wildString.isEmpty()) { - return wildString; - } - - unsigned int strLength(wildString.length()); - for (uint i = 0; i < strLength;) { - QChar ch = wildString[i++]; - if (ch == QLatin1Char('%') && i < strLength) { - ch = wildString[i++]; - switch (ch.toLatin1()) { - case 'f': { // sender's initals - if (fromDisplayString.isEmpty()) { - break; - } - - uint j = 0; - const unsigned int strLength(fromDisplayString.length()); - for (; j < strLength && fromDisplayString[j] > QLatin1Char(' '); ++j) - ; - for (; j < strLength && fromDisplayString[j] <= QLatin1Char(' '); ++j) - ; - result += fromDisplayString[0]; - if (j < strLength && fromDisplayString[j] > QLatin1Char(' ')) { - result += fromDisplayString[j]; - } else if (strLength > 1) { - if (fromDisplayString[1] > QLatin1Char(' ')) { - result += fromDisplayString[1]; - } - } - } - break; - case '_': - result += QLatin1Char(' '); - break; - case '%': - result += QLatin1Char('%'); - break; - default: - result += QLatin1Char('%'); - result += ch; - break; - } - } else { - result += ch; - } - } - return result; -} - -QString quotedPlainText(const QString &selection, const QString &fromDisplayString) -{ - QString content = selection; - // Remove blank lines at the beginning: - const int firstNonWS = content.indexOf(QRegExp(QLatin1String("\\S"))); - const int lineStart = content.lastIndexOf(QLatin1Char('\n'), firstNonWS); - if (lineStart >= 0) { - content.remove(0, static_cast(lineStart)); - } - - const auto quoteString = QStringLiteral("> "); - const QString indentStr = formatQuotePrefix(quoteString, fromDisplayString); - //FIXME - // if (TemplateParserSettings::self()->smartQuote() && mWrap) { - // content = MessageCore::StringUtil::smartQuote(content, mColWrap - indentStr.length()); - // } - content.replace(QLatin1Char('\n'), QLatin1Char('\n') + indentStr); - content.prepend(indentStr); - content += QLatin1Char('\n'); - - return content; -} - -QString quotedHtmlText(const QString &selection) -{ - QString content = selection; - //TODO 1) look for all the variations of
and remove the blank lines - //2) implement vertical bar for quoted HTML mail. - //3) After vertical bar is implemented, If a user wants to edit quoted message, - // then the
tags below should open and close as when required. - - //Add blockquote tag, so that quoted message can be differentiated from normal message - content = QLatin1String("
") + content + QLatin1String("
"); - return content; -} - -void applyCharset(const KMime::Message::Ptr msg, const KMime::Message::Ptr &origMsg) -{ - // first convert the body from its current encoding to unicode representation - QTextCodec *bodyCodec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); - if (!bodyCodec) { - bodyCodec = KCharsets::charsets()->codecForName(QStringLiteral("UTF-8")); - } - - const QString body = bodyCodec->toUnicode(msg->body()); - - // then apply the encoding of the original message - msg->contentType()->setCharset(origMsg->contentType()->charset()); - - QTextCodec *codec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset())); - if (!codec) { - qCritical() << "Could not get text codec for charset" << msg->contentType()->charset(); - } else if (!codec->canEncode(body)) { // charset can't encode body, fall back to preferred - const QStringList charsets /*= preferredCharsets() */; - - QList chars; - chars.reserve(charsets.count()); - foreach (const QString &charset, charsets) { - chars << charset.toLatin1(); - } - - //FIXME - QByteArray fallbackCharset/* = selectCharset(chars, body)*/; - if (fallbackCharset.isEmpty()) { // UTF-8 as fall-through - fallbackCharset = "UTF-8"; - } - - codec = KCharsets::charsets()->codecForName(QString::fromLatin1(fallbackCharset)); - msg->setBody(codec->fromUnicode(body)); - } else { - msg->setBody(codec->fromUnicode(body)); - } -} - -enum ReplyStrategy { - ReplyList, - ReplySmart, - ReplyAll, - ReplyAuthor, - ReplyNone -}; - -KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg) -{ - //FIXME - const bool alwaysPlain = true; - //FIXME - const ReplyStrategy replyStrategy = ReplySmart; - KMime::Message::Ptr msg(new KMime::Message); - //FIXME - //Personal email addresses - KMime::Types::AddrSpecList me; - KMime::Types::Mailbox::List toList; - KMime::Types::Mailbox::List replyToList; - KMime::Types::Mailbox::List mailingListAddresses; - - // const uint originalIdentity = identityUoid(origMsg); - initHeader(msg); - replyToList = origMsg->replyTo()->mailboxes(); - - msg->contentType()->setCharset("utf-8"); - - if (origMsg->headerByType("List-Post") && - origMsg->headerByType("List-Post")->asUnicodeString().contains(QStringLiteral("mailto:"), Qt::CaseInsensitive)) { - - const QString listPost = origMsg->headerByType("List-Post")->asUnicodeString(); - QRegExp rx(QStringLiteral("]+)@([^>]+)>"), Qt::CaseInsensitive); - if (rx.indexIn(listPost, 0) != -1) { // matched - KMime::Types::Mailbox mailbox; - mailbox.fromUnicodeString(rx.cap(1) + QLatin1Char('@') + rx.cap(2)); - mailingListAddresses << mailbox; - } - } - - switch (replyStrategy) { - case ReplySmart: { - if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { - toList << KMime::Types::Mailbox::listFrom7BitString(hdr->as7BitString(false)); - } else if (!replyToList.isEmpty()) { - toList = replyToList; - } else if (!mailingListAddresses.isEmpty()) { - toList = (KMime::Types::Mailbox::List() << mailingListAddresses.at(0)); - } else { - // doesn't seem to be a mailing list, reply to From: address - toList = origMsg->from()->mailboxes(); - - bool listContainsMe = false; - for (const auto &m : me) { - KMime::Types::Mailbox mailbox; - mailbox.setAddress(m); - if (toList.contains(mailbox)) { - listContainsMe = true; - } - } - if (listContainsMe) { - // sender seems to be one of our own identities, so we assume that this - // is a reply to a "sent" mail where the users wants to add additional - // information for the recipient. - toList = origMsg->to()->mailboxes(); - } - } - // strip all my addresses from the list of recipients - const KMime::Types::Mailbox::List recipients = toList; - - toList = stripMyAddressesFromAddressList(recipients, me); - - // ... unless the list contains only my addresses (reply to self) - if (toList.isEmpty() && !recipients.isEmpty()) { - toList << recipients.first(); - } - } - break; - case ReplyList: { - if (auto hdr = origMsg->headerByType("Mail-Followup-To")) { - KMime::Types::Mailbox mailbox; - mailbox.from7BitString(hdr->as7BitString(false)); - toList << mailbox; - } else if (!mailingListAddresses.isEmpty()) { - toList << mailingListAddresses[ 0 ]; - } else if (!replyToList.isEmpty()) { - // assume a Reply-To header mangling mailing list - toList = replyToList; - } - - //FIXME - // strip all my addresses from the list of recipients - const KMime::Types::Mailbox::List recipients = toList; - toList = stripMyAddressesFromAddressList(recipients, me); - } - break; - case ReplyAll: { - KMime::Types::Mailbox::List recipients; - KMime::Types::Mailbox::List ccRecipients; - - // add addresses from the Reply-To header to the list of recipients - if (!replyToList.isEmpty()) { - recipients = replyToList; - - // strip all possible mailing list addresses from the list of Reply-To addresses - foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { - foreach (const KMime::Types::Mailbox &recipient, recipients) { - if (mailbox == recipient) { - recipients.removeAll(recipient); - } - } - } - } - - if (!mailingListAddresses.isEmpty()) { - // this is a mailing list message - if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { - // The sender didn't set a Reply-to address, so we add the From - // address to the list of CC recipients. - ccRecipients += origMsg->from()->mailboxes(); - qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of CC recipients"; - } - - // if it is a mailing list, add the posting address - recipients.prepend(mailingListAddresses[ 0 ]); - } else { - // this is a normal message - if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) { - // in case of replying to a normal message only then add the From - // address to the list of recipients if there was no Reply-to address - recipients += origMsg->from()->mailboxes(); - qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of recipients"; - } - } - - // strip all my addresses from the list of recipients - toList = stripMyAddressesFromAddressList(recipients, me); - - // merge To header and CC header into a list of CC recipients - if (!origMsg->cc()->asUnicodeString().isEmpty() || !origMsg->to()->asUnicodeString().isEmpty()) { - KMime::Types::Mailbox::List list; - if (!origMsg->to()->asUnicodeString().isEmpty()) { - list += origMsg->to()->mailboxes(); - } - if (!origMsg->cc()->asUnicodeString().isEmpty()) { - list += origMsg->cc()->mailboxes(); - } - - foreach (const KMime::Types::Mailbox &mailbox, list) { - if (!recipients.contains(mailbox) && - !ccRecipients.contains(mailbox)) { - ccRecipients += mailbox; - qDebug() << "Added" << mailbox.prettyAddress() << "to the list of CC recipients"; - } - } - } - - if (!ccRecipients.isEmpty()) { - // strip all my addresses from the list of CC recipients - ccRecipients = stripMyAddressesFromAddressList(ccRecipients, me); - - // in case of a reply to self, toList might be empty. if that's the case - // then propagate a cc recipient to To: (if there is any). - if (toList.isEmpty() && !ccRecipients.isEmpty()) { - toList << ccRecipients.at(0); - ccRecipients.pop_front(); - } - - foreach (const KMime::Types::Mailbox &mailbox, ccRecipients) { - msg->cc()->addAddress(mailbox); - } - } - - if (toList.isEmpty() && !recipients.isEmpty()) { - // reply to self without other recipients - toList << recipients.at(0); - } - } - break; - case ReplyAuthor: { - if (!replyToList.isEmpty()) { - KMime::Types::Mailbox::List recipients = replyToList; - - // strip the mailing list post address from the list of Reply-To - // addresses since we want to reply in private - foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) { - foreach (const KMime::Types::Mailbox &recipient, recipients) { - if (mailbox == recipient) { - recipients.removeAll(recipient); - } - } - } - - if (!recipients.isEmpty()) { - toList = recipients; - } else { - // there was only the mailing list post address in the Reply-To header, - // so use the From address instead - toList = origMsg->from()->mailboxes(); - } - } else if (!origMsg->from()->asUnicodeString().isEmpty()) { - toList = origMsg->from()->mailboxes(); - } - } - break; - case ReplyNone: - // the addressees will be set by the caller - break; - } - - foreach (const KMime::Types::Mailbox &mailbox, toList) { - msg->to()->addAddress(mailbox); - } - - const QByteArray refStr = getRefStr(origMsg); - if (!refStr.isEmpty()) { - msg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8"); - } - - //In-Reply-To = original msg-id - msg->inReplyTo()->from7BitString(origMsg->messageID()->as7BitString(false)); - - msg->subject()->fromUnicodeString(replySubject(origMsg), "utf-8"); - - auto definedLocale = QLocale::system(); - - //TODO set empty source instead - StringHtmlWriter htmlWriter; - QImage paintDevice; - CSSHelper cssHelper(&paintDevice); - MessageViewer::NodeHelper nodeHelper; - ObjectTreeSource source(&htmlWriter, &cssHelper); - MessageViewer::ObjectTreeParser otp(&source, &nodeHelper); - otp.setAllowAsync(false); - otp.parseObjectTree(origMsg.data()); - - //Add quoted body - QString plainBody; - QString htmlBody; - - //On $datetime you wrote: - const QDateTime date = origMsg->date()->dateTime(); - const auto dateTimeString = QString("%1 %2").arg(definedLocale.toString(date.date(), QLocale::LongFormat)).arg(definedLocale.toString(date.time(), QLocale::LongFormat)); - const auto onDateYouWroteLine = QString("On %1 you wrote:").arg(dateTimeString); - plainBody.append(onDateYouWroteLine); - htmlBody.append(plainToHtml(onDateYouWroteLine)); - - //Strip signature for replies - const bool stripSignature = true; - - //Quoted body - QString plainQuote = quotedPlainText(plainMessageText(otp, stripSignature), origMsg->from()->displayString()); - if (plainQuote.endsWith(QLatin1Char('\n'))) { - plainQuote.chop(1); - } - plainBody.append(plainQuote); - QString headElement; - htmlBody.append(quotedHtmlText(htmlMessageText(otp, stripSignature, headElement))); - - if (alwaysPlain) { - htmlBody.clear(); - } else { - makeValidHtml(htmlBody, headElement); - } - - addProcessedBodyToMessage(msg, plainBody, htmlBody, false); - - applyCharset(msg, origMsg); - - msg->assemble(); - - return msg; -} diff --git a/framework/mail/mailtemplates.h b/framework/mail/mailtemplates.h deleted file mode 100644 index 6519122a..00000000 --- a/framework/mail/mailtemplates.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include - -namespace MailTemplates -{ - KMime::Message::Ptr reply(const KMime::Message::Ptr &message); -}; diff --git a/framework/mail/mailtransport.cpp b/framework/mail/mailtransport.cpp deleted file mode 100644 index 49d858e1..00000000 --- a/framework/mail/mailtransport.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ -#include "mailtransport.h" - -#include -#include -#include - -extern "C" { - -#include -#include -#include - -struct upload_status { - int offset; - const char *data; -}; - -static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) -{ - struct upload_status *upload_ctx = (struct upload_status *)userp; - const char *data; - - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { - return 0; - } - - data = &upload_ctx->data[upload_ctx->offset]; - if(data) { - size_t len = strlen(data); - if (len > size * nmemb) { - len = size * nmemb; - } - fprintf(stderr, "read n bytes: %d\n",len); - memcpy(ptr, data, len); - upload_ctx->offset += len; - return len; - } - - return 0; -} - - -void sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, const char *msg, bool useTls, const char* from, const char *username, const char *password, const char *server, bool verifyPeer) -{ - //For ssl use "smtps://mainserver.example.net - const char* cacert = 0; // = "/path/to/certificate.pem"; - - CURL *curl; - CURLcode res = CURLE_OK; - struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.offset = 0; - upload_ctx.data = msg; - - curl = curl_easy_init(); - if(curl) { - curl_easy_setopt(curl, CURLOPT_USERNAME, username); - curl_easy_setopt(curl, CURLOPT_PASSWORD, password); - - curl_easy_setopt(curl, CURLOPT_URL, server); - - if (useTls) { - curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); - } - - if (!verifyPeer) { - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - } - if (cacert) { - curl_easy_setopt(curl, CURLOPT_CAINFO, cacert); - } - - if (from) { - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from); - } - - for (int i = 0; i < numTos; i++) { - recipients = curl_slist_append(recipients, to[i]); - } - for (int i = 0; i < numCcs; i++) { - recipients = curl_slist_append(recipients, cc[i]); - } - curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); - - /* We're using a callback function to specify the payload (the headers and - * body of the message). You could just use the CURLOPT_READDATA option to - * specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); - curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - - /* Since the traffic will be encrypted, it is very useful to turn on debug - * information within libcurl to see what is happening during the transfer. - */ - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - - res = curl_easy_perform(curl); - if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - } - curl_slist_free_all(recipients); - curl_easy_cleanup(curl); - } -} - -}; - -void MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert) -{ - QByteArray msg = message->encodedContent(); - qWarning() << "Sending message " << msg; - - QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address()); - QList toList; - for (const auto &mb : message->to(true)->mailboxes()) { - toList << mb.address(); - } - QList ccList; - for (const auto &mb : message->cc(true)->mailboxes()) { - ccList << mb.address(); - } - bool useTls = true; - bool verifyPeer = false; - - const int numTos = toList.size(); - const char* to[numTos]; - for (int i = 0; i < numTos; i++) { - to[i] = toList.at(i); - } - - const int numCcs = ccList.size(); - const char* cc[numCcs]; - for (int i = 0; i < numCcs; i++) { - cc[i] = ccList.at(i); - } - - sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, server, verifyPeer); - qWarning() << "Message sent"; -} diff --git a/framework/mail/mailtransport.h b/framework/mail/mailtransport.h deleted file mode 100644 index 2eb30a03..00000000 --- a/framework/mail/mailtransport.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include - -namespace MailTransport -{ - void sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert); -}; diff --git a/framework/mail/messageparser.cpp b/framework/mail/messageparser.cpp deleted file mode 100644 index 89f67f38..00000000 --- a/framework/mail/messageparser.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ -#include "messageparser.h" - -#include "stringhtmlwriter.h" -#include "objecttreesource.h" -#include "csshelper.h" - -#include -#include -#include -#include -#include - -MessageParser::MessageParser(QObject *parent) - : QObject(parent) -{ - -} - -QString MessageParser::html() const -{ - return mHtml; -} - -QVariant MessageParser::message() const -{ - return QVariant(); -} - -void MessageParser::setMessage(const QVariant &message) -{ - QTime time; - time.start(); - const auto mailData = KMime::CRLFtoLF(message.toByteArray()); - KMime::Message::Ptr msg(new KMime::Message); - msg->setContent(mailData); - msg->parse(); - qWarning() << "parsed: " << time.elapsed(); - - // render the mail - StringHtmlWriter htmlWriter; - QImage paintDevice; - CSSHelper cssHelper(&paintDevice); - //temporary files only have the lifetime of the nodehelper, so we keep it around until the mail changes. - mNodeHelper = std::make_shared(); - ObjectTreeSource source(&htmlWriter, &cssHelper); - MessageViewer::ObjectTreeParser otp(&source, mNodeHelper.get()); - - htmlWriter.begin(QString()); - htmlWriter.queue(cssHelper.htmlHead(false)); - - otp.parseObjectTree(msg.data()); - - htmlWriter.queue(QStringLiteral("")); - htmlWriter.end(); - - mHtml = htmlWriter.html(); - emit htmlChanged(); -} diff --git a/framework/mail/messageparser.h b/framework/mail/messageparser.h deleted file mode 100644 index ba08a5ec..00000000 --- a/framework/mail/messageparser.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include -#include - -namespace MessageViewer { - class NodeHelper; -}; - -class MessageParser : public QObject -{ - Q_OBJECT - Q_PROPERTY (QVariant message READ message WRITE setMessage) - Q_PROPERTY (QString html READ html NOTIFY htmlChanged) - -public: - explicit MessageParser(QObject *parent = Q_NULLPTR); - - QString html() const; - - QVariant message() const; - void setMessage(const QVariant &to); - -signals: - void htmlChanged(); - -private: - QString mHtml; - std::shared_ptr mNodeHelper; -}; diff --git a/framework/mail/objecttreesource.cpp b/framework/mail/objecttreesource.cpp deleted file mode 100644 index d14b7b9b..00000000 --- a/framework/mail/objecttreesource.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net - Copyright (c) 2009 Andras Mantia - - 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 "objecttreesource.h" - -#include - -class ObjectSourcePrivate -{ -public: - ObjectSourcePrivate() - : mWriter(0) - , mCSSHelper(0) - , mAllowDecryption(true) - , mHtmlLoadExternal(true) - , mHtmlMail(true) - { - - } - MessageViewer::HtmlWriter *mWriter; - MessageViewer::CSSHelperBase *mCSSHelper; - bool mAllowDecryption; - bool mHtmlLoadExternal; - bool mHtmlMail; -}; - -ObjectTreeSource::ObjectTreeSource(MessageViewer::HtmlWriter *writer, - MessageViewer::CSSHelperBase *cssHelper) - : MessageViewer::ObjectTreeSourceIf() - , d(new ObjectSourcePrivate) - { - d->mWriter = writer; - d->mCSSHelper = cssHelper; - } - -ObjectTreeSource::~ObjectTreeSource() -{ - delete d; -} - -void ObjectTreeSource::setAllowDecryption(bool allowDecryption) -{ - d->mAllowDecryption = allowDecryption; -} - -MessageViewer::HtmlWriter *ObjectTreeSource::htmlWriter() -{ - return d->mWriter; -} -MessageViewer::CSSHelperBase *ObjectTreeSource::cssHelper() -{ - return d->mCSSHelper; -} - -bool ObjectTreeSource::htmlLoadExternal() const -{ - return d->mHtmlLoadExternal; -} - -void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal) -{ - d->mHtmlLoadExternal = loadExternal; -} - -bool ObjectTreeSource::htmlMail() const -{ - return d->mHtmlMail; -} - -void ObjectTreeSource::setHtmlMail(bool htmlMail) -{ - d->mHtmlMail = htmlMail; -} - -bool ObjectTreeSource::decryptMessage() const -{ - return d->mAllowDecryption; -} - -bool ObjectTreeSource::showSignatureDetails() const -{ - return true; -} - -int ObjectTreeSource::levelQuote() const -{ - return 1; -} - -const QTextCodec *ObjectTreeSource::overrideCodec() -{ - return Q_NULLPTR; -} - -QString ObjectTreeSource::createMessageHeader(KMime::Message *message) -{ - return QString(); -} - -const MessageViewer::AttachmentStrategy *ObjectTreeSource::attachmentStrategy() -{ - return MessageViewer::AttachmentStrategy::smart(); -} - -QObject *ObjectTreeSource::sourceObject() -{ - return Q_NULLPTR; -} - -void ObjectTreeSource::setHtmlMode(MessageViewer::Util::HtmlMode mode) -{ - Q_UNUSED(mode); -} - -bool ObjectTreeSource::autoImportKeys() const -{ - return false; -} - -bool ObjectTreeSource::showEmoticons() const -{ - return false; -} - -bool ObjectTreeSource::showExpandQuotesMark() const -{ - return false; -} diff --git a/framework/mail/objecttreesource.h b/framework/mail/objecttreesource.h deleted file mode 100644 index db14e3ff..00000000 --- a/framework/mail/objecttreesource.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net - Copyright (c) 2009 Andras Mantia - - 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. -*/ - -#ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H -#define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H - -#include - -class QString; - -class ObjectSourcePrivate; -class ObjectTreeSource : public MessageViewer::ObjectTreeSourceIf -{ -public: - ObjectTreeSource(MessageViewer::HtmlWriter *writer, - MessageViewer::CSSHelperBase *cssHelper); - virtual ~ObjectTreeSource(); - void setHtmlLoadExternal(bool loadExternal); - void setHtmlMail(bool htmlMail); - bool htmlMail() const Q_DECL_OVERRIDE; - bool decryptMessage() const Q_DECL_OVERRIDE; - bool htmlLoadExternal() const Q_DECL_OVERRIDE; - bool showSignatureDetails() const Q_DECL_OVERRIDE; - void setHtmlMode(MessageViewer::Util::HtmlMode mode) Q_DECL_OVERRIDE; - void setAllowDecryption(bool allowDecryption); - int levelQuote() const Q_DECL_OVERRIDE; - const QTextCodec *overrideCodec() Q_DECL_OVERRIDE; - QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE; - const MessageViewer::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE; - MessageViewer::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE; - MessageViewer::CSSHelperBase *cssHelper() Q_DECL_OVERRIDE; - QObject *sourceObject() Q_DECL_OVERRIDE; - bool autoImportKeys() const Q_DECL_OVERRIDE; - bool showEmoticons() const Q_DECL_OVERRIDE; - bool showExpandQuotesMark() const Q_DECL_OVERRIDE; -private: - ObjectSourcePrivate *const d; -}; - -#endif - diff --git a/framework/mail/qmldir b/framework/mail/qmldir deleted file mode 100644 index fd54e5ee..00000000 --- a/framework/mail/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module org.kde.kube.mail - -plugin mailplugin diff --git a/framework/mail/retriever.cpp b/framework/mail/retriever.cpp deleted file mode 100644 index b8e29523..00000000 --- a/framework/mail/retriever.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - - -#include "retriever.h" - -Retriever::Retriever(QObject *parent) : QObject(parent) -{ -} - -QAbstractItemModel* Retriever::model() const -{ - return mModel; -} - -void Retriever::setModel(QAbstractItemModel* model) -{ - mValue = QVariant(); - mModel = model; - connect(model, &QAbstractItemModel::rowsInserted, this, &Retriever::onRowsInserted); - connect(model, &QAbstractItemModel::modelReset, this, &Retriever::onModelReset); - if (model->rowCount(QModelIndex())) { - mValue = model->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1())); - emit valueChanged(); - } -} - -void Retriever::onRowsInserted(const QModelIndex &parent, int first, int last) -{ - if (!mValue.isValid()) { - mValue = mModel->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1())); - emit valueChanged(); - } -} - -void Retriever::onModelReset() -{ - mValue = QVariant(); -} diff --git a/framework/mail/retriever.h b/framework/mail/retriever.h deleted file mode 100644 index e454532d..00000000 --- a/framework/mail/retriever.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include - -/** - * A wrapper for a QAbstractItemModel to retrieve a value from a single index via property binding - * - * Assign a model that retrieves the index, set the property your interested in, and propery-bind "value". - */ -class Retriever : public QObject -{ - Q_OBJECT - Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel) - Q_PROPERTY(QString propertyName MEMBER mPropertyName) - Q_PROPERTY(QVariant value MEMBER mValue NOTIFY valueChanged) - -public: - explicit Retriever(QObject *parent = Q_NULLPTR); - - QAbstractItemModel* model() const; - void setModel(QAbstractItemModel* model); - -signals: - void valueChanged(); - -private slots: - void onRowsInserted(const QModelIndex &parent, int first, int last); - void onModelReset(); - -private: - QString mPropertyName; - QVariant mValue; - QAbstractItemModel *mModel; -}; diff --git a/framework/mail/singlemailcontroller.cpp b/framework/mail/singlemailcontroller.cpp deleted file mode 100644 index 8ee4acbb..00000000 --- a/framework/mail/singlemailcontroller.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "singlemailcontroller.h" - -SingleMailController::SingleMailController(QObject *parent) : QObject(parent), m_model(new MailListModel) -{ - -} - -SingleMailController::~SingleMailController() -{ - -} - -MailListModel* SingleMailController::model() const -{ - return m_model.data(); -} - - -void SingleMailController::loadMail(const QString &id) -{ - Sink::Query query; - query.liveQuery = false; - query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage"; - query.ids << id.toLatin1(); - m_model->runQuery(query); -} \ No newline at end of file diff --git a/framework/mail/singlemailcontroller.h b/framework/mail/singlemailcontroller.h deleted file mode 100644 index 283b03c4..00000000 --- a/framework/mail/singlemailcontroller.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (c) 2016 Michael Bohlender - Copyright (c) 2016 Christian Mollekopf - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#pragma once - -#include "maillistmodel.h" - -#include -#include -#include -#include - -class SingleMailController : public QObject -{ - Q_OBJECT - Q_PROPERTY (MailListModel *model READ model CONSTANT) - -public: - explicit SingleMailController(QObject *parent = Q_NULLPTR); - ~SingleMailController(); - - MailListModel *model() const; - -Q_SIGNALS: - void messageChanged(); - -public slots: - void loadMail(const QString &id); - -private: - QScopedPointer m_model; -}; diff --git a/framework/mail/stringhtmlwriter.cpp b/framework/mail/stringhtmlwriter.cpp deleted file mode 100644 index df108946..00000000 --- a/framework/mail/stringhtmlwriter.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- c++ -*- - filehtmlwriter.cpp - - This file is part of KMail, the KDE mail client. - Copyright (c) 2003 Marc Mutz - - KMail is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - KMail 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 - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#include "stringhtmlwriter.h" - -#include -#include -#include - -StringHtmlWriter::StringHtmlWriter() - : MessageViewer::HtmlWriter() - , mState(Ended) -{ -} - -StringHtmlWriter::~StringHtmlWriter() -{ -} - -void StringHtmlWriter::begin(const QString &css) -{ - if (mState != Ended) { - qWarning() << "begin() called on non-ended session!"; - reset(); - } - - mState = Begun; - mExtraHead.clear(); - mHtml.clear(); - - if (!css.isEmpty()) { - write(QLatin1String("\n")); - } -} - -void StringHtmlWriter::end() -{ - if (mState != Begun) { - qWarning() << "Called on non-begun or queued session!"; - } - - if (!mExtraHead.isEmpty()) { - insertExtraHead(); - mExtraHead.clear(); - } - resolveCidUrls(); - mState = Ended; -} - -void StringHtmlWriter::reset() -{ - if (mState != Ended) { - mHtml.clear(); - mExtraHead.clear(); - mState = Begun; // don't run into end()'s warning - end(); - mState = Ended; - } -} - -void StringHtmlWriter::write(const QString &str) -{ - if (mState != Begun) { - qWarning() << "Called in Ended or Queued state!"; - } - mHtml.append(str); -} - -void StringHtmlWriter::queue(const QString &str) -{ - write(str); -} - -void StringHtmlWriter::flush() -{ - mState = Begun; // don't run into end()'s warning - end(); -} - -void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) -{ - write("\n"); - mEmbeddedPartMap.insert(contentId, url); -} - -void StringHtmlWriter::resolveCidUrls() -{ - for (const auto &cid : mEmbeddedPartMap.keys()) { - mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString())); - } -} - -void StringHtmlWriter::extraHead(const QString &extraHead) -{ - if (mState != Ended) { - qWarning() << "Called on non-started session!"; - } - mExtraHead.append(extraHead); -} - - -void StringHtmlWriter::insertExtraHead() -{ - const QString headTag(QStringLiteral("")); - const int index = mHtml.indexOf(headTag); - if (index != -1) { - mHtml.insert(index + headTag.length(), mExtraHead); - } -} - -QString StringHtmlWriter::html() const -{ - if (mState != Ended) { - qWarning() << "Called on non-ended session!"; - } - return mHtml; -} diff --git a/framework/mail/stringhtmlwriter.h b/framework/mail/stringhtmlwriter.h deleted file mode 100644 index fa0a7aa5..00000000 --- a/framework/mail/stringhtmlwriter.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- c++ -*- - - Copyright (c) 2016 Sandro Knauß - - Kube is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - Kube 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 - - In addition, as a special exception, the copyright holders give - permission to link the code of this program with any edition of - the Qt library by Trolltech AS, Norway (or with modified versions - of Qt that use the same license as Qt), and distribute linked - combinations including the two. You must obey the GNU General - Public License in all respects for all of the code used other than - Qt. If you modify this file, you may extend this exception to - your version of the file, but you are not obligated to do so. If - you do not wish to do so, delete this exception statement from - your version. -*/ - -#ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ -#define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__ - -#include - -#include -#include - -class QString; - -class StringHtmlWriter : public MessageViewer::HtmlWriter -{ -public: - explicit StringHtmlWriter(); - virtual ~StringHtmlWriter(); - - void begin(const QString &cssDefs) Q_DECL_OVERRIDE; - void end() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - void write(const QString &str) Q_DECL_OVERRIDE; - void queue(const QString &str) Q_DECL_OVERRIDE; - void flush() Q_DECL_OVERRIDE; - void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; - void extraHead(const QString &str) Q_DECL_OVERRIDE; - - QString html() const; -private: - void insertExtraHead(); - void resolveCidUrls(); - - QString mHtml; - QString mExtraHead; - enum State { - Begun, - Queued, - Ended - } mState; - QMap mEmbeddedPartMap; -}; - -#endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__ -- cgit v1.2.3