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