diff options
Diffstat (limited to 'examples/mailtransportresource')
4 files changed, 141 insertions, 33 deletions
diff --git a/examples/mailtransportresource/mailtransport.cpp b/examples/mailtransportresource/mailtransport.cpp index 3d56af9..84c1556 100644 --- a/examples/mailtransportresource/mailtransport.cpp +++ b/examples/mailtransportresource/mailtransport.cpp | |||
@@ -41,17 +41,17 @@ static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) | |||
41 | struct upload_status *upload_ctx = (struct upload_status *)userp; | 41 | struct upload_status *upload_ctx = (struct upload_status *)userp; |
42 | const char *data; | 42 | const char *data; |
43 | 43 | ||
44 | if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { | 44 | if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { |
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | data = &upload_ctx->data[upload_ctx->offset]; | 48 | data = &upload_ctx->data[upload_ctx->offset]; |
49 | if(data) { | 49 | if (data) { |
50 | size_t len = strlen(data); | 50 | size_t len = strlen(data); |
51 | if (len > size * nmemb) { | 51 | if (len > size * nmemb) { |
52 | len = size * nmemb; | 52 | len = size * nmemb; |
53 | } | 53 | } |
54 | fprintf(stderr, "read n bytes: %d\n", int(len)); | 54 | fprintf(stdout, "read n bytes: %d\n", int(len)); |
55 | memcpy(ptr, data, len); | 55 | memcpy(ptr, data, len); |
56 | upload_ctx->offset += len; | 56 | upload_ctx->offset += len; |
57 | return len; | 57 | return len; |
@@ -69,8 +69,17 @@ static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow | |||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int debug_callback(CURL *handle, | ||
73 | curl_infotype type, | ||
74 | char *data, | ||
75 | size_t size, | ||
76 | void *userptr) | ||
77 | { | ||
78 | fprintf(stdout, "CURL_DEBUG: %s", data); | ||
79 | return 0; | ||
80 | } | ||
72 | 81 | ||
73 | bool 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, const QByteArray &cacert) | 82 | bool 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, const QByteArray &cacert, QByteArray &errorMessage) |
74 | { | 83 | { |
75 | CURL *curl; | 84 | CURL *curl; |
76 | CURLcode res = CURLE_OK; | 85 | CURLcode res = CURLE_OK; |
@@ -88,7 +97,7 @@ bool sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, | |||
88 | curl_easy_setopt(curl, CURLOPT_URL, server); | 97 | curl_easy_setopt(curl, CURLOPT_URL, server); |
89 | 98 | ||
90 | if (useTls) { | 99 | if (useTls) { |
91 | curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); | 100 | curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); |
92 | } | 101 | } |
93 | 102 | ||
94 | if (!verifyPeer) { | 103 | if (!verifyPeer) { |
@@ -121,19 +130,29 @@ bool sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, | |||
121 | /* Since the traffic will be encrypted, it is very useful to turn on debug | 130 | /* Since the traffic will be encrypted, it is very useful to turn on debug |
122 | * information within libcurl to see what is happening during the transfer. | 131 | * information within libcurl to see what is happening during the transfer. |
123 | */ | 132 | */ |
124 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); | 133 | // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); |
134 | curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_callback); | ||
125 | 135 | ||
126 | // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L); | 136 | // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L); |
127 | //Connection timeout of 10s | 137 | //Connection timeout of 40s |
128 | curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); | 138 | curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 40L); |
129 | 139 | ||
130 | curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); | 140 | curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); |
131 | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); | 141 | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); |
142 | char errorBuffer[CURL_ERROR_SIZE]; | ||
143 | curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer); | ||
132 | 144 | ||
133 | res = curl_easy_perform(curl); | 145 | res = curl_easy_perform(curl); |
134 | if(res != CURLE_OK) { | 146 | if(res != CURLE_OK) { |
135 | fprintf(stderr, "curl_easy_perform() failed: %s\n", | 147 | errorMessage += curl_easy_strerror(res); |
136 | curl_easy_strerror(res)); | 148 | errorMessage += "; "; |
149 | } | ||
150 | long http_code = 0; | ||
151 | curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code); | ||
152 | if (http_code == 200 && res != CURLE_ABORTED_BY_CALLBACK) { | ||
153 | //Succeeded | ||
154 | } else { | ||
155 | errorMessage += errorBuffer; | ||
137 | } | 156 | } |
138 | curl_slist_free_all(recipients); | 157 | curl_slist_free_all(recipients); |
139 | curl_easy_cleanup(curl); | 158 | curl_easy_cleanup(curl); |
@@ -147,8 +166,6 @@ bool sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, | |||
147 | bool MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert, MailTransport::Options options) | 166 | bool MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert, MailTransport::Options options) |
148 | { | 167 | { |
149 | QByteArray msg = message->encodedContent(); | 168 | QByteArray msg = message->encodedContent(); |
150 | SinkLog() << "Sending message " << server << username << password << cacert; | ||
151 | SinkTrace() << "Sending message " << msg; | ||
152 | 169 | ||
153 | QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address()); | 170 | QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address()); |
154 | QList<QByteArray> toList; | 171 | QList<QByteArray> toList; |
@@ -159,8 +176,11 @@ bool MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteA | |||
159 | for (const auto &mb : message->cc(true)->mailboxes()) { | 176 | for (const auto &mb : message->cc(true)->mailboxes()) { |
160 | ccList << mb.address(); | 177 | ccList << mb.address(); |
161 | } | 178 | } |
162 | bool verifyPeer = options & VerifyPeers; | 179 | const bool verifyPeer = options.testFlag(VerifyPeers); |
163 | bool useTls = options & UseTls; | 180 | const bool useTls = options.testFlag(UseTls); |
181 | |||
182 | SinkLog() << "Sending message " << server << username << password << "CaCert: " << cacert << "Use tls: " << useTls << " Verify peer: " << verifyPeer; | ||
183 | SinkTrace() << "Sending message " << msg; | ||
164 | 184 | ||
165 | const int numTos = toList.size(); | 185 | const int numTos = toList.size(); |
166 | const char* to[numTos]; | 186 | const char* to[numTos]; |
@@ -173,6 +193,14 @@ bool MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteA | |||
173 | for (int i = 0; i < numCcs; i++) { | 193 | for (int i = 0; i < numCcs; i++) { |
174 | cc[i] = ccList.at(i); | 194 | cc[i] = ccList.at(i); |
175 | } | 195 | } |
176 | 196 | //Because curl will fail with smtps, but it won't tell you why. | |
177 | return sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, server, verifyPeer, cacert); | 197 | auto serverAddress = server; |
198 | serverAddress.replace("smtps://", "smtp://"); | ||
199 | |||
200 | QByteArray errorMessage; | ||
201 | auto ret = sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, serverAddress, verifyPeer, cacert, errorMessage); | ||
202 | if (!ret) { | ||
203 | SinkWarning() << "Failed to send message: " << errorMessage; | ||
204 | } | ||
205 | return ret; | ||
178 | } | 206 | } |
diff --git a/examples/mailtransportresource/mailtransport.h b/examples/mailtransportresource/mailtransport.h index 3ef4a6d..662fdc9 100644 --- a/examples/mailtransportresource/mailtransport.h +++ b/examples/mailtransportresource/mailtransport.h | |||
@@ -26,8 +26,8 @@ | |||
26 | namespace MailTransport | 26 | namespace MailTransport |
27 | { | 27 | { |
28 | enum Option { | 28 | enum Option { |
29 | UseTls, | 29 | UseTls = 1, |
30 | VerifyPeers | 30 | VerifyPeers = 2 |
31 | }; | 31 | }; |
32 | Q_DECLARE_FLAGS(Options, Option); | 32 | Q_DECLARE_FLAGS(Options, Option); |
33 | 33 | ||
diff --git a/examples/mailtransportresource/mailtransportresource.cpp b/examples/mailtransportresource/mailtransportresource.cpp index 88a90c6..8a4ef92 100644 --- a/examples/mailtransportresource/mailtransportresource.cpp +++ b/examples/mailtransportresource/mailtransportresource.cpp | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <KMime/Message> | 30 | #include <KMime/Message> |
31 | 31 | ||
32 | #include "mailtransport.h" | 32 | #include "mailtransport.h" |
33 | #include "mail_generated.h" | ||
34 | #include "inspection.h" | 33 | #include "inspection.h" |
35 | #include <synchronizer.h> | 34 | #include <synchronizer.h> |
36 | #include <log.h> | 35 | #include <log.h> |
@@ -44,6 +43,47 @@ SINK_DEBUG_AREA("mailtransportresource") | |||
44 | 43 | ||
45 | using namespace Sink; | 44 | using namespace Sink; |
46 | 45 | ||
46 | class MailtransportPreprocessor : public Sink::Preprocessor | ||
47 | { | ||
48 | public: | ||
49 | MailtransportPreprocessor() : Sink::Preprocessor() {} | ||
50 | |||
51 | QByteArray getTargetResource() | ||
52 | { | ||
53 | using namespace Sink::ApplicationDomain; | ||
54 | |||
55 | auto resource = Store::readOne<ApplicationDomain::SinkResource>(Query{}.filter(resourceInstanceIdentifier()).request<ApplicationDomain::SinkResource::Account>()); | ||
56 | if (resource.identifier().isEmpty()) { | ||
57 | SinkWarning() << "Failed to retrieve this resource: " << resourceInstanceIdentifier(); | ||
58 | } | ||
59 | Query query; | ||
60 | query.containsFilter<ApplicationDomain::SinkResource::Capabilities>(ApplicationDomain::ResourceCapabilities::Mail::sent); | ||
61 | query.filter<ApplicationDomain::SinkResource::Account>(resource.getAccount()); | ||
62 | auto targetResource = Store::readOne<ApplicationDomain::SinkResource>(query); | ||
63 | if (targetResource.identifier().isEmpty()) { | ||
64 | SinkWarning() << "Failed to find target resource: " << targetResource.identifier(); | ||
65 | } | ||
66 | return targetResource.identifier(); | ||
67 | } | ||
68 | |||
69 | virtual Result processModification(Type type, const ApplicationDomain::ApplicationDomainType ¤t, ApplicationDomain::ApplicationDomainType &diff) Q_DECL_OVERRIDE | ||
70 | { | ||
71 | if (type == Preprocessor::Modification) { | ||
72 | using namespace Sink::ApplicationDomain; | ||
73 | if (diff.changedProperties().contains(Mail::Trash::name)) { | ||
74 | //Move back to regular resource | ||
75 | diff.setResource(getTargetResource()); | ||
76 | return {MoveToResource}; | ||
77 | } else if (diff.changedProperties().contains(Mail::Draft::name)) { | ||
78 | //Move back to regular resource | ||
79 | diff.setResource(getTargetResource()); | ||
80 | return {MoveToResource}; | ||
81 | } | ||
82 | } | ||
83 | return {NoAction}; | ||
84 | } | ||
85 | }; | ||
86 | |||
47 | class MailtransportSynchronizer : public Sink::Synchronizer { | 87 | class MailtransportSynchronizer : public Sink::Synchronizer { |
48 | public: | 88 | public: |
49 | MailtransportSynchronizer(const Sink::ResourceContext &resourceContext) | 89 | MailtransportSynchronizer(const Sink::ResourceContext &resourceContext) |
@@ -55,17 +95,22 @@ public: | |||
55 | 95 | ||
56 | KAsync::Job<void> send(const ApplicationDomain::Mail &mail, const MailtransportResource::Settings &settings) | 96 | KAsync::Job<void> send(const ApplicationDomain::Mail &mail, const MailtransportResource::Settings &settings) |
57 | { | 97 | { |
58 | return KAsync::start<void>([=] { | 98 | return KAsync::start([=] { |
59 | if (!syncStore().readValue(mail.identifier()).isEmpty()) { | 99 | if (!syncStore().readValue(mail.identifier()).isEmpty()) { |
60 | SinkLog() << "Mail is already sent: " << mail.identifier(); | 100 | SinkLog() << "Mail is already sent: " << mail.identifier(); |
61 | return KAsync::null(); | 101 | return KAsync::null(); |
62 | } | 102 | } |
103 | emitNotification(Notification::Info, ApplicationDomain::SyncInProgress, "Sending message.", {}, {mail.identifier()}); | ||
63 | const auto data = mail.getMimeMessage(); | 104 | const auto data = mail.getMimeMessage(); |
64 | auto msg = KMime::Message::Ptr::create(); | 105 | auto msg = KMime::Message::Ptr::create(); |
65 | msg->setHead(KMime::CRLFtoLF(data)); | 106 | msg->setHead(KMime::CRLFtoLF(data)); |
66 | msg->parse(); | 107 | msg->parse(); |
67 | if (settings.testMode) { | 108 | if (settings.testMode) { |
68 | SinkLog() << "I would totally send that mail, but I'm in test mode." << mail.identifier(); | 109 | auto subject = msg->subject(true)->asUnicodeString(); |
110 | SinkLog() << "I would totally send that mail, but I'm in test mode." << mail.identifier() << subject; | ||
111 | if (!subject.contains("send")) { | ||
112 | return KAsync::error("Failed to send the message."); | ||
113 | } | ||
69 | auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/"; | 114 | auto path = resourceStorageLocation(mResourceInstanceIdentifier) + "/test/"; |
70 | SinkTrace() << path; | 115 | SinkTrace() << path; |
71 | QDir dir; | 116 | QDir dir; |
@@ -77,11 +122,16 @@ public: | |||
77 | } else { | 122 | } else { |
78 | MailTransport::Options options; | 123 | MailTransport::Options options; |
79 | if (settings.server.contains("smtps")) { | 124 | if (settings.server.contains("smtps")) { |
80 | options &= MailTransport::UseTls; | 125 | options |= MailTransport::UseTls; |
81 | } | 126 | } |
82 | if (!MailTransport::sendMessage(msg, settings.server.toUtf8(), settings.username.toUtf8(), settings.password.toUtf8(), settings.cacert.toUtf8(), options)) { | 127 | if (!MailTransport::sendMessage(msg, settings.server.toUtf8(), settings.username.toUtf8(), settings.password.toUtf8(), settings.cacert.toUtf8(), options)) { |
83 | SinkWarning() << "Failed to send message: " << mail; | 128 | SinkWarning() << "Failed to send message: " << mail; |
129 | emitNotification(Notification::Warning, ApplicationDomain::SyncError, "Failed to send message.", {}, {mail.identifier()}); | ||
130 | emitNotification(Notification::Warning, ApplicationDomain::TransmissionError, "Failed to send message.", {}, {mail.identifier()}); | ||
84 | return KAsync::error("Failed to send the message."); | 131 | return KAsync::error("Failed to send the message."); |
132 | } else { | ||
133 | emitNotification(Notification::Info, ApplicationDomain::SyncSuccess, "Message successfully sent.", {}, {mail.identifier()}); | ||
134 | emitNotification(Notification::Info, ApplicationDomain::TransmissionSuccess, "Message successfully sent.", {}, {mail.identifier()}); | ||
85 | } | 135 | } |
86 | } | 136 | } |
87 | syncStore().writeValue(mail.identifier(), "sent"); | 137 | syncStore().writeValue(mail.identifier(), "sent"); |
@@ -100,9 +150,8 @@ public: | |||
100 | query.filter<ApplicationDomain::SinkResource::Account>(resource.getAccount()); | 150 | query.filter<ApplicationDomain::SinkResource::Account>(resource.getAccount()); |
101 | return Store::fetchOne<ApplicationDomain::SinkResource>(query) | 151 | return Store::fetchOne<ApplicationDomain::SinkResource>(query) |
102 | .then([this, modifiedMail](const ApplicationDomain::SinkResource &resource) { | 152 | .then([this, modifiedMail](const ApplicationDomain::SinkResource &resource) { |
103 | //First modify the mail to have the sent property set to true | 153 | //Modify the mail to have the sent property set to true, and move it to the new resource. |
104 | modify(modifiedMail, resource.identifier(), true); | 154 | modify(modifiedMail, resource.identifier(), true); |
105 | return KAsync::null<void>(); | ||
106 | }); | 155 | }); |
107 | }); | 156 | }); |
108 | } | 157 | } |
@@ -112,12 +161,10 @@ public: | |||
112 | return KAsync::start<void>([this]() { | 161 | return KAsync::start<void>([this]() { |
113 | QList<ApplicationDomain::Mail> toSend; | 162 | QList<ApplicationDomain::Mail> toSend; |
114 | SinkLog() << "Looking for mails to send."; | 163 | SinkLog() << "Looking for mails to send."; |
115 | store().readAll<ApplicationDomain::Mail>([&](const ApplicationDomain::Mail &mail) -> bool { | 164 | store().readAll<ApplicationDomain::Mail>([&](const ApplicationDomain::Mail &mail) { |
116 | SinkTrace() << "Found mail: " << mail.identifier(); | ||
117 | if (!mail.getSent()) { | 165 | if (!mail.getSent()) { |
118 | toSend << mail; | 166 | toSend << mail; |
119 | } | 167 | } |
120 | return true; | ||
121 | }); | 168 | }); |
122 | SinkLog() << "Found " << toSend.size() << " mails to send"; | 169 | SinkLog() << "Found " << toSend.size() << " mails to send"; |
123 | auto job = KAsync::null<void>(); | 170 | auto job = KAsync::null<void>(); |
@@ -192,7 +239,7 @@ MailtransportResource::MailtransportResource(const Sink::ResourceContext &resour | |||
192 | setupSynchronizer(synchronizer); | 239 | setupSynchronizer(synchronizer); |
193 | setupInspector(QSharedPointer<MailtransportInspector>::create(resourceContext)); | 240 | setupInspector(QSharedPointer<MailtransportInspector>::create(resourceContext)); |
194 | 241 | ||
195 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new MailPropertyExtractor); | 242 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new MailPropertyExtractor << new MailtransportPreprocessor); |
196 | } | 243 | } |
197 | 244 | ||
198 | MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent) | 245 | MailtransportResourceFactory::MailtransportResourceFactory(QObject *parent) |
diff --git a/examples/mailtransportresource/tests/mailtransporttest.cpp b/examples/mailtransportresource/tests/mailtransporttest.cpp index 3b848b3..e4cc447 100644 --- a/examples/mailtransportresource/tests/mailtransporttest.cpp +++ b/examples/mailtransportresource/tests/mailtransporttest.cpp | |||
@@ -47,7 +47,8 @@ private slots: | |||
47 | 47 | ||
48 | void cleanup() | 48 | void cleanup() |
49 | { | 49 | { |
50 | VERIFYEXEC(ResourceControl::shutdown(mResourceInstanceIdentifier)); | 50 | VERIFYEXEC(Store::removeDataFromDisk(mResourceInstanceIdentifier)); |
51 | VERIFYEXEC(Store::removeDataFromDisk(mStorageResource)); | ||
51 | } | 52 | } |
52 | 53 | ||
53 | void init() | 54 | void init() |
@@ -58,7 +59,8 @@ private slots: | |||
58 | void testSendMail() | 59 | void testSendMail() |
59 | { | 60 | { |
60 | auto message = KMime::Message::Ptr::create(); | 61 | auto message = KMime::Message::Ptr::create(); |
61 | message->subject(true)->fromUnicodeString(QString::fromLatin1("Foobar"), "utf8"); | 62 | message->messageID(true)->generate("foo.com"); |
63 | message->subject(true)->fromUnicodeString(QString::fromLatin1("send: Foobar"), "utf8"); | ||
62 | message->assemble(); | 64 | message->assemble(); |
63 | 65 | ||
64 | auto mail = ApplicationDomain::Mail::create(mResourceInstanceIdentifier); | 66 | auto mail = ApplicationDomain::Mail::create(mResourceInstanceIdentifier); |
@@ -67,9 +69,10 @@ private slots: | |||
67 | VERIFYEXEC(Store::create(mail)); | 69 | VERIFYEXEC(Store::create(mail)); |
68 | VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); | 70 | VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); |
69 | 71 | ||
72 | //FIXME the email is sent already because changereplay kicks of automatically | ||
70 | //Ensure the mail is queryable in the outbox | 73 | //Ensure the mail is queryable in the outbox |
71 | auto mailInOutbox = Store::readOne<ApplicationDomain::Mail>(Query().resourceFilter(mResourceInstanceIdentifier).filter<Mail::Sent>(false).request<Mail::Subject>().request<Mail::Folder>().request<Mail::MimeMessage>().request<Mail::Sent>()); | 74 | // auto mailInOutbox = Store::readOne<ApplicationDomain::Mail>(Query().resourceFilter(mResourceInstanceIdentifier).filter<Mail::Sent>(false).request<Mail::Subject>().request<Mail::Folder>().request<Mail::MimeMessage>().request<Mail::Sent>()); |
72 | QVERIFY(!mailInOutbox.identifier().isEmpty()); | 75 | // QVERIFY(!mailInOutbox.identifier().isEmpty()); |
73 | 76 | ||
74 | //Ensure the mail is sent and moved to the sent mail folder on sync | 77 | //Ensure the mail is sent and moved to the sent mail folder on sync |
75 | VERIFYEXEC(Store::synchronize(Query().resourceFilter(mResourceInstanceIdentifier))); | 78 | VERIFYEXEC(Store::synchronize(Query().resourceFilter(mResourceInstanceIdentifier))); |
@@ -81,7 +84,37 @@ private slots: | |||
81 | QVERIFY(!mailInSentMailFolder.getSubject().isEmpty()); | 84 | QVERIFY(!mailInSentMailFolder.getSubject().isEmpty()); |
82 | } | 85 | } |
83 | 86 | ||
84 | //TODO test mail that fails to be sent. add a special header to the mail and have the resource fail sending. Ensure we can modify the mail to fix sending of the message. | 87 | void testSendFailure() |
88 | { | ||
89 | auto message = KMime::Message::Ptr::create(); | ||
90 | message->messageID(true)->generate("foo.com"); | ||
91 | message->subject(true)->fromUnicodeString(QString::fromLatin1("error: Foobar"), "utf8"); | ||
92 | message->assemble(); | ||
93 | |||
94 | auto mail = ApplicationDomain::Mail::create(mResourceInstanceIdentifier); | ||
95 | mail.setMimeMessage(message->encodedContent()); | ||
96 | |||
97 | VERIFYEXEC(Store::create(mail)); | ||
98 | VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); | ||
99 | |||
100 | //Ensure the mail is queryable in the outbox | ||
101 | auto mailInOutbox = Store::readOne<ApplicationDomain::Mail>(Query().resourceFilter(mResourceInstanceIdentifier).filter<Mail::Sent>(false)); | ||
102 | QVERIFY(!mailInOutbox.identifier().isEmpty()); | ||
103 | |||
104 | //Modify back to drafts | ||
105 | auto modifiedMail = mailInOutbox; | ||
106 | modifiedMail.setDraft(true); | ||
107 | VERIFYEXEC(Store::modify(modifiedMail)); | ||
108 | VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); | ||
109 | |||
110 | QTest::qWait(100); | ||
111 | auto mailsInOutbox = Store::read<ApplicationDomain::Mail>(Query().resourceFilter(mResourceInstanceIdentifier)); | ||
112 | QCOMPARE(mailsInOutbox.size(), 0); | ||
113 | |||
114 | auto mailsInDrafts = Store::read<ApplicationDomain::Mail>(Query().resourceFilter(mStorageResource)); | ||
115 | QCOMPARE(mailsInDrafts.size(), 1); | ||
116 | |||
117 | } | ||
85 | 118 | ||
86 | }; | 119 | }; |
87 | 120 | ||