summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--examples/mailtransportresource/CMakeLists.txt16
-rw-r--r--examples/mailtransportresource/facade.cpp142
-rw-r--r--examples/mailtransportresource/facade.h36
-rw-r--r--examples/mailtransportresource/mailtransport.cpp160
-rw-r--r--examples/mailtransportresource/mailtransport.h28
-rw-r--r--examples/mailtransportresource/mailtransportresource.cpp39
-rw-r--r--examples/mailtransportresource/mailtransportresource.h39
8 files changed, 461 insertions, 0 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 837903a..d5fcacf 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -8,3 +8,4 @@ if (BUILD_MAILDIR)
8 # a maildir resource implementation 8 # a maildir resource implementation
9 add_subdirectory(maildirresource) 9 add_subdirectory(maildirresource)
10endif() 10endif()
11add_subdirectory(mailtransportresource)
diff --git a/examples/mailtransportresource/CMakeLists.txt b/examples/mailtransportresource/CMakeLists.txt
new file mode 100644
index 0000000..c9b0401
--- /dev/null
+++ b/examples/mailtransportresource/CMakeLists.txt
@@ -0,0 +1,16 @@
1project(sink_resource_mailtransport)
2
3add_definitions(-DQT_PLUGIN)
4include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
5
6find_package(KF5 COMPONENTS REQUIRED Mime)
7find_package(CURL 7.20.0 REQUIRED)
8
9include_directories(${CURL_INCLUDE_DIRS})
10
11
12add_library(${PROJECT_NAME} SHARED facade.cpp mailtransportresource.cpp mailtransport.cpp)
13qt5_use_modules(${PROJECT_NAME} Core Network)
14target_link_libraries(${PROJECT_NAME} sink KF5::Mime ${CURL_LIBRARIES})
15
16install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SINK_RESOURCE_PLUGINS_PATH})
diff --git a/examples/mailtransportresource/facade.cpp b/examples/mailtransportresource/facade.cpp
new file mode 100644
index 0000000..b90df16
--- /dev/null
+++ b/examples/mailtransportresource/facade.cpp
@@ -0,0 +1,142 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "facade.h"
21
22#include <QDir>
23#include <QFileInfo>
24#include <QSettings>
25#include <QStandardPaths>
26#include <QUuid>
27#include <KMime/Message>
28
29#include "resultprovider.h"
30#include "mailtransport.h"
31#include <log.h>
32#include <resourceconfig.h>
33
34static QString dataDirectory(const QByteArray &identifier)
35{
36 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/mailtransport/" + identifier;
37}
38
39class Outbox {
40public:
41 Outbox(const QByteArray &identifier) : mIdentifier(identifier)
42 {
43
44 }
45
46 static QString fileName(const QByteArray &resourceId, const QByteArray &messageId)
47 {
48 return dataDirectory(resourceId)+"/" + messageId;
49 }
50
51 void add(const QByteArray &messageId, const QString &messagePath, QMap<QByteArray, QString> config)
52 {
53 QDir dir;
54 dir.mkpath(dataDirectory(mIdentifier));
55 if (!QFile(messagePath).rename(fileName(mIdentifier, messageId))) {
56 ErrorMsg() << "Failed to move the file:";
57 ErrorMsg() << messagePath << " to " << fileName(mIdentifier, messageId);
58 }
59 //TODO store settings
60 // QSettings settings(dataDirectory(mIdentifier) + "/messageId.ini", QSettings::IniFormat);
61 }
62
63 void dispatch(const QByteArray &messageId)
64 {
65 QFile mimeMessage(fileName(mIdentifier, messageId));
66 if (!mimeMessage.open(QIODevice::ReadOnly)) {
67 ErrorMsg() << "Failed to open mime message: " << mimeMessage.errorString();
68 ErrorMsg() << fileName(mIdentifier, messageId);
69 return;
70 }
71
72 auto msg = KMime::Message::Ptr::create();
73 msg->setHead(KMime::CRLFtoLF(mimeMessage.readAll()));
74 msg->parse();
75 MailTransport::sendMessage(msg, mServer, mUsername, mPassword, mCaCert);
76 Trace() << "Sent message: " << msg->subject();
77 }
78
79 void setServer(const QByteArray &server, const QByteArray &username, const QByteArray &caCert)
80 {
81 mServer = server;
82 mUsername = username;
83 mCaCert = caCert;
84 }
85
86 void setPassword(const QByteArray &password)
87 {
88 mPassword = password;
89 }
90
91private:
92 QByteArray mServer;
93 QByteArray mUsername;
94 QByteArray mPassword;
95 QByteArray mCaCert;
96 QByteArray mIdentifier;
97};
98
99MailtransportFacade::MailtransportFacade(const QByteArray &identifier) : Sink::StoreFacade<Sink::ApplicationDomain::Mail>(), mIdentifier(identifier)
100{
101}
102
103MailtransportFacade::~MailtransportFacade()
104{
105}
106
107KAsync::Job<void> MailtransportFacade::create(const Sink::ApplicationDomain::Mail &mail)
108{
109 Trace() << "Called create: ";
110 return KAsync::start<void>([mail, this]() {
111 auto config = ResourceConfig::getConfiguration(mIdentifier);
112
113 auto identifier = QUuid::createUuid().toByteArray();
114 Trace() << "Sending new message: " << identifier;
115 Trace() << config.value("server").toByteArray() << config.value("username").toByteArray() << config.value("cacert").toByteArray();
116
117 Outbox outbox(mIdentifier);
118 outbox.setServer(config.value("server").toByteArray(), config.value("username").toByteArray(), config.value("cacert").toByteArray());
119 //FIXME remove and somehow retrieve the password on demand
120 outbox.setPassword(config.value("password").toByteArray());
121
122 const QByteArray mimeMessage = mail.getProperty("mimeMessage").toByteArray();
123 QMap<QByteArray, QString> configurationValues;
124 outbox.add(identifier, mimeMessage, configurationValues);
125 outbox.dispatch(identifier);
126 });
127}
128
129KAsync::Job<void> MailtransportFacade::modify(const Sink::ApplicationDomain::Mail &mail)
130{
131 return KAsync::error<void>(0, "Not implemented.");
132}
133
134KAsync::Job<void> MailtransportFacade::remove(const Sink::ApplicationDomain::Mail &mail)
135{
136 return KAsync::error<void>(0, "Not implemented.");
137}
138
139QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::Mail::Ptr>::Ptr> MailtransportFacade::load(const Sink::Query &query)
140{
141 return qMakePair(KAsync::error<void>(0, "Not implemented."), Sink::ResultEmitter<Sink::ApplicationDomain::Mail::Ptr>::Ptr());
142}
diff --git a/examples/mailtransportresource/facade.h b/examples/mailtransportresource/facade.h
new file mode 100644
index 0000000..858f73a
--- /dev/null
+++ b/examples/mailtransportresource/facade.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#pragma once
21
22#include "common/facade.h"
23
24class MailtransportFacade : public Sink::StoreFacade<Sink::ApplicationDomain::Mail>
25{
26public:
27 MailtransportFacade(const QByteArray &instanceIdentifier);
28 virtual ~MailtransportFacade();
29 KAsync::Job<void> create(const Sink::ApplicationDomain::Mail &resource) Q_DECL_OVERRIDE;
30 KAsync::Job<void> modify(const Sink::ApplicationDomain::Mail &resource) Q_DECL_OVERRIDE;
31 KAsync::Job<void> remove(const Sink::ApplicationDomain::Mail &resource) Q_DECL_OVERRIDE;
32 QPair<KAsync::Job<void>, typename Sink::ResultEmitter<Sink::ApplicationDomain::Mail::Ptr>::Ptr> load(const Sink::Query &query) Q_DECL_OVERRIDE;
33private:
34 QByteArray mIdentifier;
35};
36
diff --git a/examples/mailtransportresource/mailtransport.cpp b/examples/mailtransportresource/mailtransport.cpp
new file mode 100644
index 0000000..49d858e
--- /dev/null
+++ b/examples/mailtransportresource/mailtransport.cpp
@@ -0,0 +1,160 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19#include "mailtransport.h"
20
21#include <QByteArray>
22#include <QList>
23#include <QDebug>
24
25extern "C" {
26
27#include <stdio.h>
28#include <string.h>
29#include <curl/curl.h>
30
31struct upload_status {
32 int offset;
33 const char *data;
34};
35
36static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
37{
38 struct upload_status *upload_ctx = (struct upload_status *)userp;
39 const char *data;
40
41 if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
42 return 0;
43 }
44
45 data = &upload_ctx->data[upload_ctx->offset];
46 if(data) {
47 size_t len = strlen(data);
48 if (len > size * nmemb) {
49 len = size * nmemb;
50 }
51 fprintf(stderr, "read n bytes: %d\n",len);
52 memcpy(ptr, data, len);
53 upload_ctx->offset += len;
54 return len;
55 }
56
57 return 0;
58}
59
60
61void 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)
62{
63 //For ssl use "smtps://mainserver.example.net
64 const char* cacert = 0; // = "/path/to/certificate.pem";
65
66 CURL *curl;
67 CURLcode res = CURLE_OK;
68 struct curl_slist *recipients = NULL;
69 struct upload_status upload_ctx;
70
71 upload_ctx.offset = 0;
72 upload_ctx.data = msg;
73
74 curl = curl_easy_init();
75 if(curl) {
76 curl_easy_setopt(curl, CURLOPT_USERNAME, username);
77 curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
78
79 curl_easy_setopt(curl, CURLOPT_URL, server);
80
81 if (useTls) {
82 curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
83 }
84
85 if (!verifyPeer) {
86 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
87 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
88 }
89 if (cacert) {
90 curl_easy_setopt(curl, CURLOPT_CAINFO, cacert);
91 }
92
93 if (from) {
94 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from);
95 }
96
97 for (int i = 0; i < numTos; i++) {
98 recipients = curl_slist_append(recipients, to[i]);
99 }
100 for (int i = 0; i < numCcs; i++) {
101 recipients = curl_slist_append(recipients, cc[i]);
102 }
103 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
104
105 /* We're using a callback function to specify the payload (the headers and
106 * body of the message). You could just use the CURLOPT_READDATA option to
107 * specify a FILE pointer to read from. */
108 curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
109 curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
110 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
111
112 /* Since the traffic will be encrypted, it is very useful to turn on debug
113 * information within libcurl to see what is happening during the transfer.
114 */
115 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
116
117 res = curl_easy_perform(curl);
118 if(res != CURLE_OK) {
119 fprintf(stderr, "curl_easy_perform() failed: %s\n",
120 curl_easy_strerror(res));
121 }
122 curl_slist_free_all(recipients);
123 curl_easy_cleanup(curl);
124 }
125}
126
127};
128
129void MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert)
130{
131 QByteArray msg = message->encodedContent();
132 qWarning() << "Sending message " << msg;
133
134 QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address());
135 QList<QByteArray> toList;
136 for (const auto &mb : message->to(true)->mailboxes()) {
137 toList << mb.address();
138 }
139 QList<QByteArray> ccList;
140 for (const auto &mb : message->cc(true)->mailboxes()) {
141 ccList << mb.address();
142 }
143 bool useTls = true;
144 bool verifyPeer = false;
145
146 const int numTos = toList.size();
147 const char* to[numTos];
148 for (int i = 0; i < numTos; i++) {
149 to[i] = toList.at(i);
150 }
151
152 const int numCcs = ccList.size();
153 const char* cc[numCcs];
154 for (int i = 0; i < numCcs; i++) {
155 cc[i] = ccList.at(i);
156 }
157
158 sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, server, verifyPeer);
159 qWarning() << "Message sent";
160}
diff --git a/examples/mailtransportresource/mailtransport.h b/examples/mailtransportresource/mailtransport.h
new file mode 100644
index 0000000..2eb30a0
--- /dev/null
+++ b/examples/mailtransportresource/mailtransport.h
@@ -0,0 +1,28 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QByteArray>
23#include <KMime/Message>
24
25namespace MailTransport
26{
27 void sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert);
28};
diff --git a/examples/mailtransportresource/mailtransportresource.cpp b/examples/mailtransportresource/mailtransportresource.cpp
new file mode 100644
index 0000000..6c0f0b3
--- /dev/null
+++ b/examples/mailtransportresource/mailtransportresource.cpp
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "mailtransportresource.h"
21#include "facade.h"
22#include "facadefactory.h"
23
24MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent)
25 : Sink::ResourceFactory(parent)
26{
27
28}
29
30Sink::Resource *MailtransportResourceFactory::createResource(const QByteArray &instanceIdentifier)
31{
32 return nullptr;
33}
34
35void MailtransportResourceFactory::registerFacades(Sink::FacadeFactory &factory)
36{
37 factory.registerFacade<Sink::ApplicationDomain::Mail, MailtransportFacade>(PLUGIN_NAME);
38}
39
diff --git a/examples/mailtransportresource/mailtransportresource.h b/examples/mailtransportresource/mailtransportresource.h
new file mode 100644
index 0000000..2ccca0a
--- /dev/null
+++ b/examples/mailtransportresource/mailtransportresource.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#pragma once
21
22#include "common/resource.h"
23
24//TODO: a little ugly to have this in two places, once here and once in Q_PLUGIN_METADATA
25#define PLUGIN_NAME "org.kde.mailtransport"
26
27class MailtransportResourceFactory : public Sink::ResourceFactory
28{
29 Q_OBJECT
30 Q_PLUGIN_METADATA(IID "org.kde.mailtransport")
31 Q_INTERFACES(Sink::ResourceFactory)
32
33public:
34 MailtransportResourceFactory(QObject *parent = 0);
35
36 Sink::Resource *createResource(const QByteArray &instanceIdentifier) Q_DECL_OVERRIDE;
37 void registerFacades(Sink::FacadeFactory &factory) Q_DECL_OVERRIDE;
38};
39