cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
viewemail.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2015-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "viewemail_p.h"
6
7#include <Cutelyst/application.h>
8#include <Cutelyst/context.h>
9#include <Cutelyst/response.h>
10#include <SimpleMail/emailaddress.h>
11#include <SimpleMail/mimemessage.h>
12#include <SimpleMail/mimetext.h>
13#include <SimpleMail/serverreply.h>
14
15#include <QtCore/QLoggingCategory>
16
17Q_LOGGING_CATEGORY(CUTELYST_VIEW_EMAIL, "cutelyst.view.email", QtWarningMsg)
18
19using namespace Cutelyst;
20using namespace SimpleMail;
21
23 : View(new ViewEmailPrivate, parent, name)
24{
25 initSender();
26}
27
29{
30 Q_D(const ViewEmail);
31 return d->stashKey;
32}
33
34void ViewEmail::setStashKey(const QString &stashKey)
35{
36 Q_D(ViewEmail);
37 d->stashKey = stashKey;
38 Q_EMIT changed();
39}
40
42{
43 Q_D(const ViewEmail);
44 return d->defaultContentType;
45}
46
48{
49 Q_D(ViewEmail);
50 d->defaultContentType = contentType;
51 Q_EMIT changed();
52}
53
55{
56 Q_D(const ViewEmail);
57 return d->defaultCharset;
58}
59
61{
62 Q_D(ViewEmail);
63 d->defaultCharset = charset;
64 Q_EMIT changed();
65}
66
68{
69 Q_D(const ViewEmail);
70 return d->defaultEncoding;
71}
72
74{
75 Q_D(ViewEmail);
76 d->defaultEncoding = encoding;
77 Q_EMIT changed();
78}
79
81{
82 Q_D(const ViewEmail);
83 return d->sender->host();
84}
85
87{
88 Q_D(ViewEmail);
89 d->sender->setHost(host);
90 if (d->server) {
91 d->server->setHost(host);
92 }
93}
94
96{
97 Q_D(const ViewEmail);
98 return d->sender->port();
99}
100
102{
103 Q_D(ViewEmail);
104 d->sender->setPort(quint16(port));
105 if (d->server) {
106 d->server->setPort(quint16(port));
107 }
108}
109
111{
112 Q_D(const ViewEmail);
113 return static_cast<ViewEmail::ConnectionType>(d->sender->connectionType());
114}
115
117{
118 Q_D(ViewEmail);
119 d->sender->setConnectionType(static_cast<Sender::ConnectionType>(ct));
120 if (d->server) {
121 d->server->setConnectionType(static_cast<Server::ConnectionType>(ct));
122 }
123}
124
126{
127 Q_D(const ViewEmail);
128 return static_cast<ViewEmail::AuthMethod>(d->sender->authMethod());
129}
130
132{
133 Q_D(ViewEmail);
134 d->sender->setAuthMethod(static_cast<Sender::AuthMethod>(method));
135 if (d->server) {
136 d->server->setAuthMethod(static_cast<Server::AuthMethod>(method));
137 }
138}
139
141{
142 Q_D(const ViewEmail);
143 return d->sender->user();
144}
145
147{
148 Q_D(ViewEmail);
149 d->sender->setUser(user);
150 if (d->server) {
151 d->server->setUsername(user);
152 }
153}
154
156{
157 Q_D(const ViewEmail);
158 return d->sender->password();
159}
160
162{
163 Q_D(ViewEmail);
164 d->sender->setPassword(password);
165 if (d->server) {
166 d->server->setPassword(password);
167 }
168}
169
171{
172 Q_D(const ViewEmail);
173 return d->server;
174}
175
176void ViewEmail::setAsync(bool enable)
177{
178 Q_D(ViewEmail);
179 if (enable) {
180 if (!d->server) {
181 d->server = new Server(this);
182 d->server->setHost(d->sender->host());
183 d->server->setPort(d->sender->port());
184 d->server->setUsername(d->sender->user());
185 d->server->setPassword(d->sender->password());
186 d->server->setAuthMethod(static_cast<Server::AuthMethod>(d->sender->authMethod()));
187 d->server->setConnectionType(
188 static_cast<Server::ConnectionType>(d->sender->connectionType()));
189 }
190 } else {
191 delete d->server;
192 d->server = nullptr;
193 }
194}
195
197{
198 Q_D(const ViewEmail);
199 QByteArray ret;
200 QVariantHash email = c->stash(d->stashKey).toHash();
201 if (email.isEmpty()) {
202 c->error(QStringLiteral(
203 "Cannot render template, template name or template stash key not defined"));
204 return ret;
205 }
206
207 MimeMessage message;
208
209 QVariant value;
210 value = email.value(QStringLiteral("to"));
211 if (value.type() == QVariant::String && !value.toString().isEmpty()) {
212 message.addTo(value.toString());
213 } else if (value.type() == QVariant::StringList) {
214 const auto rcpts = value.toStringList();
215 for (const QString &rcpt : rcpts) {
216 message.addTo(rcpt);
217 }
218 }
219
220 value = email.value(QStringLiteral("cc"));
221 if (value.type() == QVariant::String && !value.toString().isEmpty()) {
222 message.addCc(value.toString());
223 } else if (value.type() == QVariant::StringList) {
224 const auto rcpts = value.toStringList();
225 for (const QString &rcpt : rcpts) {
226 message.addCc(rcpt);
227 }
228 }
229
230 value = email.value(QStringLiteral("bcc"));
231 if (value.type() == QVariant::String && !value.toString().isEmpty()) {
232 message.addBcc(value.toString());
233 } else if (value.type() == QVariant::StringList) {
234 const auto rcpts = value.toStringList();
235 for (const QString &rcpt : rcpts) {
236 message.addBcc(rcpt);
237 }
238 }
239
240 message.setSender(email.value(QStringLiteral("from")).toString());
241 message.setSubject(email.value(QStringLiteral("subject")).toString());
242
243 QVariant body = email.value(QStringLiteral("body"));
244 QVariant parts = email.value(QStringLiteral("parts"));
245 if (body.isNull() && parts.isNull()) {
246 c->error(QStringLiteral("Can't send email without parts or body, check stash"));
247 return ret;
248 }
249
250 if (!parts.isNull()) {
251 const QVariantList partsVariant = parts.toList();
252 for (const QVariant &part : partsVariant) {
253 auto mime = part.value<MimePart *>();
254 if (mime) {
255 message.addPart(mime);
256 } else {
257 qCCritical(CUTELYST_VIEW_EMAIL) << "Failed to cast MimePart";
258 }
259 }
260
261 auto contentTypeIt = email.constFind(QStringLiteral("content_type"));
262 if (contentTypeIt != email.constEnd() && !contentTypeIt.value().isNull() &&
263 !contentTypeIt.value().toString().isEmpty()) {
264 const QByteArray contentType = contentTypeIt.value().toString().toLatin1();
265 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified content_type" << contentType;
266 message.getContent().setContentType(contentType);
267 } else if (!d->defaultContentType.isEmpty()) {
268 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default content_type" << d->defaultContentType;
269 message.getContent().setContentType(d->defaultContentType);
270 }
271 } else {
272 auto part = new MimeText(body.toString());
273 d->setupAttributes(part, email);
274 message.setContent(part);
275 }
276
277 if (d->server) {
278 ServerReply *reply = d->server->sendMail(message);
279 connect(reply, &ServerReply::finished, reply, &ServerReply::deleteLater);
280 } else if (!d->sender->sendMail(message)) {
281 c->error(QString::fromLatin1(d->sender->responseText()));
282 return ret;
283 }
284
285 return ret;
286}
287
288ViewEmail::ViewEmail(ViewEmailPrivate *d, QObject *parent, const QString &name)
289 : View(d, parent, name)
290{
291 initSender();
292}
293
294void ViewEmail::initSender()
295{
296 Q_D(ViewEmail);
297 d->sender = new Sender(this);
298
299 QVariantHash config;
300 const auto app = qobject_cast<Application *>(parent());
301 if (app) {
302 config = app->config(QStringLiteral("VIEW_EMAIL")).toHash();
303 }
304
305 d->stashKey = config.value(QStringLiteral("stash_key"), QStringLiteral("email")).toString();
306
307 if (!config.value(QStringLiteral("sender_host")).isNull()) {
308 d->sender->setHost(config.value(QStringLiteral("sender_host")).toString());
309 }
310 if (!config.value(QStringLiteral("sender_port")).isNull()) {
311 d->sender->setPort(quint16(config.value(QStringLiteral("sender_port")).toInt()));
312 }
313 if (!config.value(QStringLiteral("sender_username")).isNull()) {
314 d->sender->setUser(config.value(QStringLiteral("sender_username")).toString());
315 }
316 if (!config.value(QStringLiteral("sender_password")).isNull()) {
317 d->sender->setPassword(config.value(QStringLiteral("sender_password")).toString());
318 }
319}
320
321void ViewEmailPrivate::setupAttributes(MimePart *part, const QVariantHash &attrs) const
322{
323 auto contentTypeIt = attrs.constFind(QStringLiteral("content_type"));
324 if (contentTypeIt != attrs.constEnd() && !contentTypeIt.value().isNull() &&
325 !contentTypeIt.value().toString().isEmpty()) {
326 const QByteArray contentType = contentTypeIt.value().toString().toLatin1();
327 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified content_type" << contentType;
328 part->setContentType(contentType);
329 } else if (!defaultContentType.isEmpty()) {
330 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default content_type" << defaultContentType;
331 part->setContentType(defaultContentType);
332 }
333
334 auto charsetIt = attrs.constFind(QStringLiteral("charset"));
335 if (charsetIt != attrs.constEnd() && !charsetIt.value().isNull() &&
336 !charsetIt.value().toString().isEmpty()) {
337 const QByteArray charset = charsetIt.value().toString().toLatin1();
338 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified charset" << charset;
339 part->setCharset(charset);
340 } else if (!defaultCharset.isEmpty()) {
341 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultCharset;
342 part->setCharset(defaultCharset);
343 }
344
345 auto encodingIt = attrs.constFind(QStringLiteral("encoding"));
346 if (encodingIt != attrs.constEnd() && !encodingIt.value().isNull() &&
347 !encodingIt.value().toString().isEmpty()) {
348 const QByteArray encoding = encodingIt.value().toString().toLatin1();
349 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified encoding" << encoding;
350 setupEncoding(part, encoding);
351 } else if (!defaultEncoding.isEmpty()) {
352 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultEncoding;
353 setupEncoding(part, defaultEncoding);
354 }
355}
356
357void ViewEmailPrivate::setupEncoding(MimePart *part, const QByteArray &encoding) const
358{
359 if (encoding == "7bit") {
360 part->setEncoding(MimePart::_7Bit);
361 } else if (encoding == "8bit") {
362 part->setEncoding(MimePart::_8Bit);
363 } else if (encoding == "base64") {
364 part->setEncoding(MimePart::Base64);
365 } else if (encoding == "quoted-printable") {
366 part->setEncoding(MimePart::QuotedPrintable);
367 } else {
368 qCCritical(CUTELYST_VIEW_EMAIL) << "Unknown encoding" << encoding;
369 }
370}
371
372#include "moc_viewemail.cpp"
QString name() const
Definition component.cpp:33
The Cutelyst Context.
Definition context.h:39
void stash(const QVariantHash &unite)
Definition context.cpp:566
bool error() const noexcept
Returns true if an error was set.
Definition context.cpp:49
QString senderUser() const
void setSenderConnectionType(ConnectionType ct)
int senderPort() const
Definition viewemail.cpp:95
QByteArray defaultEncoding() const
Definition viewemail.cpp:67
QString stashKey() const
Definition viewemail.cpp:28
QString senderPassword() const
void setSenderUser(const QString &user)
void setSenderHost(const QString &host)
Definition viewemail.cpp:86
bool async() const
ConnectionType senderConnectionType() const
QString senderHost() const
Definition viewemail.cpp:80
QByteArray defaultCharset() const
Definition viewemail.cpp:54
void setStashKey(const QString &stashKey)
Definition viewemail.cpp:34
void setDefaultContentType(const QByteArray &contentType)
Definition viewemail.cpp:47
void setAsync(bool enable)
void setSenderPort(int port)
QByteArray defaultContentType() const
Definition viewemail.cpp:41
void setSenderAuthMethod(AuthMethod method)
void setDefaultCharset(const QByteArray &charset)
Definition viewemail.cpp:60
void setDefaultEncoding(const QByteArray &encoding)
Definition viewemail.cpp:73
AuthMethod senderAuthMethod() const
ViewEmail(QObject *parent, const QString &name=QString())
Constructs a new ViewEmail object with the given parent and name.
Definition viewemail.cpp:22
void setSenderPassword(const QString &password)
virtual QByteArray render(Context *c) const override
View(QObject *parent, const QString &name)
Definition view.cpp:18
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
QObject(QObject *parent)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
T qobject_cast(QObject *object)
QString fromLatin1(const char *str, int size)
bool isNull() const const
QList< QVariant > toList() const const
QString toString() const const
T value() const const