cutelyst 5.0.0
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;
21using namespace Qt::StringLiterals;
22
24 : View(new ViewEmailPrivate, parent, name)
25{
26 initSender();
27}
28
30{
31 Q_D(const ViewEmail);
32 return d->stashKey;
33}
34
35void ViewEmail::setStashKey(const QString &stashKey)
36{
37 Q_D(ViewEmail);
38 d->stashKey = stashKey;
39 Q_EMIT changed();
40}
41
43{
44 Q_D(const ViewEmail);
45 return d->defaultContentType;
46}
47
49{
50 Q_D(ViewEmail);
51 d->defaultContentType = contentType;
52 Q_EMIT changed();
53}
54
56{
57 Q_D(const ViewEmail);
58 return d->defaultCharset;
59}
60
62{
63 Q_D(ViewEmail);
64 d->defaultCharset = charset;
65 Q_EMIT changed();
66}
67
69{
70 Q_D(const ViewEmail);
71 return d->defaultEncoding;
72}
73
75{
76 Q_D(ViewEmail);
77 d->defaultEncoding = encoding;
78 Q_EMIT changed();
79}
80
82{
83 Q_D(const ViewEmail);
84 return d->server->host();
85}
86
88{
89 Q_D(ViewEmail);
90 d->server->setHost(host);
91}
92
94{
95 Q_D(const ViewEmail);
96 return d->server->port();
97}
98
100{
101 Q_D(ViewEmail);
102 d->server->setPort(quint16(port));
103}
104
106{
107 Q_D(const ViewEmail);
108 return static_cast<ViewEmail::ConnectionType>(d->server->connectionType());
109}
110
112{
113 Q_D(ViewEmail);
114 d->server->setConnectionType(static_cast<Server::ConnectionType>(ct));
115}
116
118{
119 Q_D(const ViewEmail);
120 return static_cast<ViewEmail::AuthMethod>(d->server->authMethod());
121}
122
124{
125 Q_D(ViewEmail);
126 d->server->setAuthMethod(static_cast<Server::AuthMethod>(method));
127}
128
130{
131 Q_D(const ViewEmail);
132 return d->server->username();
133}
134
136{
137 Q_D(ViewEmail);
138 d->server->setUsername(user);
139}
140
142{
143 Q_D(const ViewEmail);
144 return d->server->password();
145}
146
148{
149 Q_D(ViewEmail);
150 d->server->setPassword(password);
151}
152
154{
155 Q_D(const ViewEmail);
156 QVariantHash email = c->stash(d->stashKey).toHash();
157 if (email.isEmpty()) {
158 c->appendError(QStringLiteral(
159 "Cannot render template, template name or template stash key not defined"));
160 return {};
161 }
162
163 MimeMessage message;
164
165 QVariant value;
166 value = email.value(u"to"_s);
167 if (value.typeId() == QMetaType::QString && !value.toString().isEmpty()) {
168 message.addTo(SimpleMail::EmailAddress{value.toString()});
169 } else if (value.typeId() == QMetaType::QStringList) {
170 const auto rcpts = value.toStringList();
171 for (const QString &rcpt : rcpts) {
172 message.addTo(SimpleMail::EmailAddress{rcpt});
173 }
174 }
175
176 value = email.value(u"cc"_s);
177 if (value.typeId() == QMetaType::QString && !value.toString().isEmpty()) {
178 message.addCc(SimpleMail::EmailAddress{value.toString()});
179 } else if (value.typeId() == QMetaType::QStringList) {
180 const auto rcpts = value.toStringList();
181 for (const QString &rcpt : rcpts) {
182 message.addCc(SimpleMail::EmailAddress{rcpt});
183 }
184 }
185
186 value = email.value(u"bcc"_s);
187 if (value.typeId() == QMetaType::QString && !value.toString().isEmpty()) {
188 message.addBcc(SimpleMail::EmailAddress{value.toString()});
189 } else if (value.typeId() == QMetaType::QStringList) {
190 const auto rcpts = value.toStringList();
191 for (const QString &rcpt : rcpts) {
192 message.addBcc(SimpleMail::EmailAddress{rcpt});
193 }
194 }
195
196 message.setSender(SimpleMail::EmailAddress{email.value(u"from"_s).toString()});
197 message.setSubject(email.value(u"subject"_s).toString());
198
199 QVariant body = email.value(u"body"_s);
200 QVariant parts = email.value(u"parts"_s);
201 if (body.isNull() && parts.isNull()) {
202 c->appendError(u"Can't send email without parts or body, check stash"_s);
203 return {};
204 }
205
206 if (!parts.isNull()) {
207 const QVariantList partsVariant = parts.toList();
208 for (const QVariant &part : partsVariant) {
209 auto mime = part.value<std::shared_ptr<MimePart>>();
210 if (mime) {
211 message.addPart(mime);
212 } else {
213 qCCritical(CUTELYST_VIEW_EMAIL) << "Failed to cast MimePart";
214 }
215 }
216
217 auto contentTypeIt = email.constFind(u"content_type"_s);
218 if (contentTypeIt != email.constEnd() && !contentTypeIt.value().isNull() &&
219 !contentTypeIt.value().toString().isEmpty()) {
220 const QByteArray contentType = contentTypeIt.value().toString().toLatin1();
221 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified content_type" << contentType;
222 message.getContent().setContentType(contentType);
223 } else if (!d->defaultContentType.isEmpty()) {
224 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default content_type" << d->defaultContentType;
225 message.getContent().setContentType(d->defaultContentType);
226 }
227 } else {
228 auto part = std::make_shared<MimeText>(body.toString());
229 d->setupAttributes(part, email);
230 message.setContent(part);
231 }
232
233 ServerReply *reply = d->server->sendMail(message);
234 connect(reply, &ServerReply::finished, reply, &ServerReply::deleteLater);
235
236 return {};
237}
238
239ViewEmail::ViewEmail(ViewEmailPrivate *d, QObject *parent, const QString &name)
240 : View(d, parent, name)
241{
242 initSender();
243}
244
245void ViewEmail::initSender()
246{
247 Q_D(ViewEmail);
248 d->server = new Server(this);
249
250 QVariantHash config;
251 const auto app = qobject_cast<Application *>(parent());
252 if (app) {
253 config = app->config(u"VIEW_EMAIL"_s).toHash();
254 }
255
256 d->stashKey = config.value(u"stash_key"_s, u"email"_s).toString();
257
258 if (!config.value(u"sender_host"_s).isNull()) {
259 d->server->setHost(config.value(u"sender_host"_s).toString());
260 }
261 if (!config.value(u"sender_port"_s).isNull()) {
262 d->server->setPort(quint16(config.value(u"sender_port"_s).toInt()));
263 }
264 if (!config.value(u"sender_username"_s).isNull()) {
265 d->server->setUsername(config.value(u"sender_username"_s).toString());
266 }
267 if (!config.value(u"sender_password"_s).isNull()) {
268 d->server->setPassword(config.value(u"sender_password"_s).toString());
269 }
270}
271
272void ViewEmailPrivate::setupAttributes(std::shared_ptr<MimePart> part,
273 const QVariantHash &attrs) const
274{
275 auto contentTypeIt = attrs.constFind(u"content_type"_s);
276 if (contentTypeIt != attrs.constEnd() && !contentTypeIt.value().isNull() &&
277 !contentTypeIt.value().toString().isEmpty()) {
278 const QByteArray contentType = contentTypeIt.value().toString().toLatin1();
279 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified content_type" << contentType;
280 part->setContentType(contentType);
281 } else if (!defaultContentType.isEmpty()) {
282 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default content_type" << defaultContentType;
283 part->setContentType(defaultContentType);
284 }
285
286 auto charsetIt = attrs.constFind(u"charset"_s);
287 if (charsetIt != attrs.constEnd() && !charsetIt.value().isNull() &&
288 !charsetIt.value().toString().isEmpty()) {
289 const QByteArray charset = charsetIt.value().toString().toLatin1();
290 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified charset" << charset;
291 part->setCharset(charset);
292 } else if (!defaultCharset.isEmpty()) {
293 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultCharset;
294 part->setCharset(defaultCharset);
295 }
296
297 auto encodingIt = attrs.constFind(u"encoding"_s);
298 if (encodingIt != attrs.constEnd() && !encodingIt.value().isNull() &&
299 !encodingIt.value().toString().isEmpty()) {
300 const QByteArray encoding = encodingIt.value().toString().toLatin1();
301 qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified encoding" << encoding;
302 setupEncoding(part, encoding);
303 } else if (!defaultEncoding.isEmpty()) {
304 qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultEncoding;
305 setupEncoding(part, defaultEncoding);
306 }
307}
308
309void ViewEmailPrivate::setupEncoding(std::shared_ptr<MimePart> part,
310 const QByteArray &encoding) const
311{
312 if (encoding == "7bit") {
313 part->setEncoding(MimePart::_7Bit);
314 } else if (encoding == "8bit") {
315 part->setEncoding(MimePart::_8Bit);
316 } else if (encoding == "base64") {
317 part->setEncoding(MimePart::Base64);
318 } else if (encoding == "quoted-printable") {
319 part->setEncoding(MimePart::QuotedPrintable);
320 } else {
321 qCCritical(CUTELYST_VIEW_EMAIL) << "Unknown encoding" << encoding;
322 }
323}
324
325#include "moc_viewemail.cpp"
The Cutelyst Context.
Definition context.h:42
void stash(const QVariantHash &unite)
Definition context.cpp:562
void appendError(const QString &error)
Definition context.cpp:57
Implements a web server.
Definition server.h:60
A view that sends stash data via e-mail.
Definition viewemail.h:24
QString senderUser() const
void setSenderConnectionType(ConnectionType ct)
QByteArray defaultEncoding
Definition viewemail.h:46
int senderPort() const
Definition viewemail.cpp:93
QString senderPassword() const
void setSenderUser(const QString &user)
QByteArray defaultContentType
Definition viewemail.h:36
QByteArray defaultCharset
Definition viewemail.h:41
void setSenderHost(const QString &host)
Definition viewemail.cpp:87
ConnectionType senderConnectionType() const
QString senderHost() const
Definition viewemail.cpp:81
void setStashKey(const QString &stashKey)
Definition viewemail.cpp:35
void setDefaultContentType(const QByteArray &contentType)
Definition viewemail.cpp:48
void setSenderPort(int port)
Definition viewemail.cpp:99
void setSenderAuthMethod(AuthMethod method)
void setDefaultCharset(const QByteArray &charset)
Definition viewemail.cpp:61
void setDefaultEncoding(const QByteArray &encoding)
Definition viewemail.cpp:74
ViewEmail(QObject *parent, const QString &name={})
Definition viewemail.cpp:23
AuthMethod senderAuthMethod() const
void setSenderPassword(const QString &password)
QByteArray render(Context *c) const override
Abstract View component for Cutelyst.
Definition view.h:25
The Cutelyst namespace holds all public Cutelyst API.
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
bool isNull() const const
QList< QVariant > toList() const const
QString toString() const const
T value() const const