cutelyst  3.7.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 
11 #include <QtCore/QLoggingCategory>
12 
13 #include <SimpleMail/mimemessage.h>
14 #include <SimpleMail/emailaddress.h>
15 #include <SimpleMail/mimetext.h>
16 #include <SimpleMail/serverreply.h>
17 
18 Q_LOGGING_CATEGORY(CUTELYST_VIEW_EMAIL, "cutelyst.view.email", QtWarningMsg)
19 
20 using namespace Cutelyst;
21 using namespace SimpleMail;
22 
23 ViewEmail::ViewEmail(QObject *parent, const QString &name) : View(new ViewEmailPrivate, parent, name)
24 {
25  initSender();
26 }
27 
28 QString ViewEmail::stashKey() const
29 {
30  Q_D(const ViewEmail);
31  return d->stashKey;
32 }
33 
34 void ViewEmail::setStashKey(const QString &stashKey)
35 {
36  Q_D(ViewEmail);
37  d->stashKey = stashKey;
38  Q_EMIT changed();
39 }
40 
41 QByteArray ViewEmail::defaultContentType() const
42 {
43  Q_D(const ViewEmail);
44  return d->defaultContentType;
45 }
46 
47 void ViewEmail::setDefaultContentType(const QByteArray &contentType)
48 {
49  Q_D(ViewEmail);
50  d->defaultContentType = contentType;
51  Q_EMIT changed();
52 }
53 
54 QByteArray ViewEmail::defaultCharset() const
55 {
56  Q_D(const ViewEmail);
57  return d->defaultCharset;
58 }
59 
60 void ViewEmail::setDefaultCharset(const QByteArray &charset)
61 {
62  Q_D(ViewEmail);
63  d->defaultCharset = charset;
64  Q_EMIT changed();
65 }
66 
67 QByteArray ViewEmail::defaultEncoding() const
68 {
69  Q_D(const ViewEmail);
70  return d->defaultEncoding;
71 }
72 
73 void ViewEmail::setDefaultEncoding(const QByteArray &encoding)
74 {
75  Q_D(ViewEmail);
76  d->defaultEncoding = encoding;
77  Q_EMIT changed();
78 }
79 
80 QString ViewEmail::senderHost() const
81 {
82  Q_D(const ViewEmail);
83  return d->sender->host();
84 }
85 
86 void ViewEmail::setSenderHost(const QString &host)
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 
140 QString ViewEmail::senderUser() const
141 {
142  Q_D(const ViewEmail);
143  return d->sender->user();
144 }
145 
146 void ViewEmail::setSenderUser(const QString &user)
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 
161 void ViewEmail::setSenderPassword(const QString &password)
162 {
163  Q_D(ViewEmail);
164  d->sender->setPassword(password);
165  if (d->server) {
166  d->server->setPassword(password);
167  }
168 }
169 
170 bool ViewEmail::async() const
171 {
172  Q_D(const ViewEmail);
173  return d->server;
174 }
175 
176 void 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(static_cast<Server::ConnectionType>(d->sender->connectionType()));
188  }
189  } else {
190  delete d->server;
191  d->server = nullptr;
192  }
193 }
194 
195 QByteArray ViewEmail::render(Context *c) const
196 {
197  Q_D(const ViewEmail);
198  QByteArray ret;
199  QVariantHash email = c->stash(d->stashKey).toHash();
200  if (email.isEmpty()) {
201  c->error(QStringLiteral("Cannot render template, template name or template stash key not defined"));
202  return ret;
203  }
204 
205  MimeMessage message;
206 
207  QVariant value;
208  value = email.value(QStringLiteral("to"));
209  if (value.type() == QVariant::String && !value.toString().isEmpty()) {
210  message.addTo(value.toString());
211  } else if (value.type() == QVariant::StringList) {
212  const auto rcpts = value.toStringList();
213  for (const QString &rcpt : rcpts) {
214  message.addTo(rcpt);
215  }
216  }
217 
218  value = email.value(QStringLiteral("cc"));
219  if (value.type() == QVariant::String && !value.toString().isEmpty()) {
220  message.addCc(value.toString());
221  } else if (value.type() == QVariant::StringList) {
222  const auto rcpts = value.toStringList();
223  for (const QString &rcpt : rcpts) {
224  message.addCc(rcpt);
225  }
226  }
227 
228  value = email.value(QStringLiteral("bcc"));
229  if (value.type() == QVariant::String && !value.toString().isEmpty()) {
230  message.addBcc(value.toString());
231  } else if (value.type() == QVariant::StringList) {
232  const auto rcpts = value.toStringList();
233  for (const QString &rcpt : rcpts) {
234  message.addBcc(rcpt);
235  }
236  }
237 
238  message.setSender(email.value(QStringLiteral("from")).toString());
239  message.setSubject(email.value(QStringLiteral("subject")).toString());
240 
241  QVariant body = email.value(QStringLiteral("body"));
242  QVariant parts = email.value(QStringLiteral("parts"));
243  if (body.isNull() && parts.isNull()) {
244  c->error(QStringLiteral("Can't send email without parts or body, check stash"));
245  return ret;
246  }
247 
248  if (!parts.isNull()) {
249  const QVariantList partsVariant = parts.toList();
250  for (const QVariant &part : partsVariant) {
251  auto mime = part.value<MimePart*>();
252  if (mime) {
253  message.addPart(mime);
254  } else {
255  qCCritical(CUTELYST_VIEW_EMAIL) << "Failed to cast MimePart";
256  }
257  }
258 
259  auto contentTypeIt = email.constFind(QStringLiteral("content_type"));
260  if (contentTypeIt != email.constEnd()
261  && !contentTypeIt.value().isNull()
262  && !contentTypeIt.value().toString().isEmpty()) {
263  const QByteArray contentType = contentTypeIt.value().toString().toLatin1();
264  qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified content_type" << contentType;
265  message.getContent().setContentType(contentType);
266  } else if (!d->defaultContentType.isEmpty()) {
267  qCDebug(CUTELYST_VIEW_EMAIL) << "Using default content_type" << d->defaultContentType;
268  message.getContent().setContentType(d->defaultContentType);
269  }
270  } else {
271  auto part = new MimeText(body.toString());
272  d->setupAttributes(part, email);
273  message.setContent(part);
274  }
275 
276  if (d->server) {
277  ServerReply *reply = d->server->sendMail(message);
278  connect(reply, &ServerReply::finished, reply, &ServerReply::deleteLater);
279  } else if (!d->sender->sendMail(message)) {
280  c->error(QString::fromLatin1(d->sender->responseText()));
281  return ret;
282  }
283 
284  return ret;
285 }
286 
287 ViewEmail::ViewEmail(ViewEmailPrivate *d, QObject *parent, const QString &name) : View(d, parent, name)
288 {
289  initSender();
290 }
291 
292 void ViewEmail::initSender()
293 {
294  Q_D(ViewEmail);
295  d->sender = new Sender(this);
296 
297  QVariantHash config;
298  const auto app = qobject_cast<Application *>(parent());
299  if (app) {
300  config = app->config(QStringLiteral("VIEW_EMAIL")).toHash();
301  }
302 
303  d->stashKey = config.value(QStringLiteral("stash_key"), QStringLiteral("email")).toString();
304 
305  if (!config.value(QStringLiteral("sender_host")).isNull()) {
306  d->sender->setHost(config.value(QStringLiteral("sender_host")).toString());
307  }
308  if (!config.value(QStringLiteral("sender_port")).isNull()) {
309  d->sender->setPort(quint16(config.value(QStringLiteral("sender_port")).toInt()));
310  }
311  if (!config.value(QStringLiteral("sender_username")).isNull()) {
312  d->sender->setUser(config.value(QStringLiteral("sender_username")).toString());
313  }
314  if (!config.value(QStringLiteral("sender_password")).isNull()) {
315  d->sender->setPassword(config.value(QStringLiteral("sender_password")).toString());
316  }
317 }
318 
319 
320 void ViewEmailPrivate::setupAttributes(MimePart *part, const QVariantHash &attrs) const
321 {
322  auto contentTypeIt = attrs.constFind(QStringLiteral("content_type"));
323  if (contentTypeIt != attrs.constEnd()
324  && !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()
336  && !charsetIt.value().isNull()
337  && !charsetIt.value().toString().isEmpty()) {
338  const QByteArray charset = charsetIt.value().toString().toLatin1();
339  qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified charset" << charset;
340  part->setCharset(charset);
341  } else if (!defaultCharset.isEmpty()) {
342  qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultCharset;
343  part->setCharset(defaultCharset);
344  }
345 
346  auto encodingIt = attrs.constFind(QStringLiteral("encoding"));
347  if (encodingIt != attrs.constEnd()
348  && !encodingIt.value().isNull()
349  && !encodingIt.value().toString().isEmpty()) {
350  const QByteArray encoding = encodingIt.value().toString().toLatin1();
351  qCDebug(CUTELYST_VIEW_EMAIL) << "Using specified encoding" << encoding;
352  setupEncoding(part, encoding);
353  } else if (!defaultEncoding.isEmpty()) {
354  qCDebug(CUTELYST_VIEW_EMAIL) << "Using default charset" << defaultEncoding;
355  setupEncoding(part, defaultEncoding);
356  }
357 }
358 
359 void ViewEmailPrivate::setupEncoding(MimePart *part, const QByteArray &encoding) const
360 {
361  if (encoding == "7bit") {
362  part->setEncoding(MimePart::_7Bit);
363  } else if (encoding == "8bit") {
364  part->setEncoding(MimePart::_8Bit);
365  } else if (encoding == "base64") {
366  part->setEncoding(MimePart::Base64);
367  } else if (encoding == "quoted-printable") {
368  part->setEncoding(MimePart::QuotedPrintable);
369  } else {
370  qCCritical(CUTELYST_VIEW_EMAIL) << "Unknown encoding" << encoding;
371  }
372 }
373 
374 #include "moc_viewemail.cpp"
The Cutelyst Context.
Definition: context.h:39
void stash(const QVariantHash &unite)
Definition: context.cpp:546
bool error() const noexcept
Returns true if an error was set.
Definition: context.cpp:50
QString senderUser() const
Definition: viewemail.cpp:140
void setSenderConnectionType(ConnectionType ct)
Definition: viewemail.cpp:116
int senderPort() const
Definition: viewemail.cpp:95
QString senderPassword() const
Definition: viewemail.cpp:155
void setSenderUser(const QString &user)
Definition: viewemail.cpp:146
void setSenderHost(const QString &host)
Definition: viewemail.cpp:86
ConnectionType senderConnectionType() const
Definition: viewemail.cpp:110
QString senderHost() const
Definition: viewemail.cpp:80
void setStashKey(const QString &stashKey)
Definition: viewemail.cpp:34
void setDefaultContentType(const QByteArray &contentType)
Definition: viewemail.cpp:47
void setAsync(bool enable)
Definition: viewemail.cpp:176
void setSenderPort(int port)
Definition: viewemail.cpp:101
void setSenderAuthMethod(AuthMethod method)
Definition: viewemail.cpp:131
void setDefaultCharset(const QByteArray &charset)
Definition: viewemail.cpp:60
void setDefaultEncoding(const QByteArray &encoding)
Definition: viewemail.cpp:73
AuthMethod senderAuthMethod() const
Definition: viewemail.cpp:125
ViewEmail(QObject *parent, const QString &name=QString())
Constructs a new ViewEmail object with the given parent and name.
Definition: viewemail.cpp:23
void setSenderPassword(const QString &password)
Definition: viewemail.cpp:161
virtual QByteArray render(Context *c) const override
Definition: viewemail.cpp:195
Cutelyst View abstract view component
Definition: view.h:22
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:8