@tiledesk/tiledesk-server 2.3.49 → 2.3.50
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +4 -0
- package/app.js +2 -1
- package/package.json +4 -1
- package/pubmodules/apps/index.js +8 -0
- package/pubmodules/apps/listener.js +27 -0
- package/pubmodules/kaleyra/index.js +6 -0
- package/pubmodules/kaleyra/listener.js +32 -0
- package/pubmodules/pubModulesManager.js +67 -0
- package/pubmodules/whatsapp/index.js +7 -0
- package/pubmodules/whatsapp/listener.js +32 -0
- package/routes/email.js +26 -2
- package/services/emailService.js +97 -6
- package/template/email/beenInvitedExistingUser.html +1 -1
- package/template/email/beenInvitedNewUser.html +1 -1
- package/template/email/emailDirect.html +121 -0
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.48)
|
7
7
|
|
8
|
+
# Untagged
|
9
|
+
- Added new email sending endpoint
|
10
|
+
- Emails endpoint is now usable by agents
|
11
|
+
|
8
12
|
# 2.3.49 -> PROD
|
9
13
|
- @tiledesk/tiledesk-tybot-connector": "^0.1.22
|
10
14
|
|
package/app.js
CHANGED
@@ -481,7 +481,8 @@ app.use('/:projectid/labels', [fetchLabels],labels);
|
|
481
481
|
|
482
482
|
app.use('/:projectid/campaigns',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], campaigns);
|
483
483
|
|
484
|
-
app.use('/:projectid/emails',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('
|
484
|
+
app.use('/:projectid/emails',[passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], email);
|
485
|
+
|
485
486
|
|
486
487
|
|
487
488
|
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tiledesk/tiledesk-server",
|
3
3
|
"description": "The Tiledesk server module",
|
4
|
-
"version": "2.3.
|
4
|
+
"version": "2.3.50",
|
5
5
|
"scripts": {
|
6
6
|
"start": "node ./bin/www",
|
7
7
|
"pretest": "mongodb-runner start",
|
@@ -36,6 +36,9 @@
|
|
36
36
|
"@tiledesk-ent/tiledesk-server-enterprise": "^1.0.0"
|
37
37
|
},
|
38
38
|
"dependencies": {
|
39
|
+
"@tiledesk/tiledesk-apps": "^1.0.6",
|
40
|
+
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.19",
|
41
|
+
"@tiledesk/tiledesk-kaleyra-proxy": "^0.1.5",
|
39
42
|
"@tiledesk/tiledesk-chat21-app": "^1.1.7",
|
40
43
|
"@tiledesk/tiledesk-chatbot-util": "^0.8.33",
|
41
44
|
"@tiledesk/tiledesk-json-rules-engine": "^4.0.3",
|
@@ -0,0 +1,27 @@
|
|
1
|
+
const apps = require("@tiledesk/tiledesk-apps");
|
2
|
+
var winston = require('../../config/winston');
|
3
|
+
|
4
|
+
class Listener {
|
5
|
+
|
6
|
+
listen(config) {
|
7
|
+
|
8
|
+
winston.info("Apps Listener listen");
|
9
|
+
|
10
|
+
if (config.databaseUri) {
|
11
|
+
winston.debug("apps config databaseUri: " + config.databaseUri);
|
12
|
+
}
|
13
|
+
|
14
|
+
apps.startApp({
|
15
|
+
ACCESS_TOKEN_SECRET: process.env.APPS_ACCESS_TOKEN_SECRET || 'nodeauthsecret',
|
16
|
+
MONGODB_URI: process.env.APPS_MONGODB_URI || config.databaseUri,
|
17
|
+
}, () => {
|
18
|
+
winston.info("Tiledesk Apps proxy server succesfully started.")
|
19
|
+
})
|
20
|
+
|
21
|
+
}
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
var listener = new Listener();
|
26
|
+
|
27
|
+
module.exports = listener;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
const kaleyra = require("@tiledesk/tiledesk-kaleyra-proxy");
|
2
|
+
var winston = require('../../config/winston');
|
3
|
+
var configGlobal = require('../../config/global');
|
4
|
+
|
5
|
+
const apiUrl = process.env.API_URL || configGlobal.apiUrl;
|
6
|
+
winston.info("Kaleyra apiUrl: " + apiUrl);
|
7
|
+
|
8
|
+
class Listener {
|
9
|
+
|
10
|
+
listen(config) {
|
11
|
+
winston.info("Kaleyra Listener listen");
|
12
|
+
if (config.databaseUri) {
|
13
|
+
winston.debug("kaleyra config databaseUri: " + config.databaseUri);
|
14
|
+
}
|
15
|
+
|
16
|
+
kaleyra.startApp({
|
17
|
+
MONGODB_URL: config.databaseUri,
|
18
|
+
API_URL: apiUrl,
|
19
|
+
BASE_URL: apiUrl + "/modules/kaleyra",
|
20
|
+
APPS_API_URL: apiUrl + "/modules/apps",
|
21
|
+
KALEYRA_API_URL: process.env.KALEYRA_API_URL,
|
22
|
+
API_KEY: process.env.API_KEY,
|
23
|
+
log: process.env.KALEYRA_LOG
|
24
|
+
}, () => {
|
25
|
+
winston.info("Tiledesk Kaleyra proxy server succesfully started.");
|
26
|
+
})
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
var listener = new Listener();
|
31
|
+
|
32
|
+
module.exports = listener;
|
@@ -21,6 +21,15 @@ class PubModulesManager {
|
|
21
21
|
this.rasa = undefined;
|
22
22
|
this.rasaRoute = undefined;
|
23
23
|
|
24
|
+
this.apps = undefined;
|
25
|
+
this.appsRoute = undefined;
|
26
|
+
|
27
|
+
this.whatsapp = undefined;
|
28
|
+
this.whatsappRoute = undefined;
|
29
|
+
|
30
|
+
this.kaleyra = undefined;
|
31
|
+
this.kaleyraRoute = undefined;
|
32
|
+
|
24
33
|
this.activityArchiver = undefined;
|
25
34
|
this.activityRoute = undefined;
|
26
35
|
|
@@ -53,6 +62,18 @@ class PubModulesManager {
|
|
53
62
|
app.use('/modules/rasa', this.rasaRoute);
|
54
63
|
winston.info("ModulesManager rasaRoute controller loaded");
|
55
64
|
}
|
65
|
+
if (this.appsRoute) {
|
66
|
+
app.use('/modules/apps', this.appsRoute);
|
67
|
+
winston.info("ModulesManager appsRoute controller loaded");
|
68
|
+
}
|
69
|
+
if (this.whatsappRoute) {
|
70
|
+
app.use('/modules/whatsapp', this.whatsappRoute);
|
71
|
+
winston.info("ModulesManager whatsappRoute controller loaded");
|
72
|
+
}
|
73
|
+
if (this.kaleyraRoute) {
|
74
|
+
app.use('/modules/kaleyra', this.kaleyraRoute);
|
75
|
+
winston.info("ModulesManager kaleyraRoute controller loaded");
|
76
|
+
}
|
56
77
|
if (this.tilebotRoute) {
|
57
78
|
app.use('/modules/tilebot', this.tilebotRoute);
|
58
79
|
winston.info("ModulesManager tilebot controller loaded");
|
@@ -217,7 +238,53 @@ class PubModulesManager {
|
|
217
238
|
}
|
218
239
|
}
|
219
240
|
|
241
|
+
try {
|
242
|
+
this.apps = require('./apps');
|
243
|
+
winston.debug("this.apps: " + this.apps);
|
244
|
+
this.apps.listener.listen(config);
|
245
|
+
|
246
|
+
this.appsRoute = this.apps.appsRoute;
|
247
|
+
|
248
|
+
winston.info("PubModulesManager initialized apps.");
|
249
|
+
} catch(err) {
|
250
|
+
if (err.code == 'MODULE_NOT_FOUND') {
|
251
|
+
winston.info("PubModulesManager init apps module not found");
|
252
|
+
}else {
|
253
|
+
winston.info("PubModulesManager error initializing init apps module", err);
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
try {
|
258
|
+
this.whatsapp = require('./whatsapp');
|
259
|
+
winston.debug("this.whatsapp: " + this.whatsapp);
|
260
|
+
this.whatsapp.listener.listen(config);
|
220
261
|
|
262
|
+
this.whatsappRoute = this.whatsapp.whatsappRoute;
|
263
|
+
|
264
|
+
winston.info("PubModulesManager initialized apps.");
|
265
|
+
} catch(err) {
|
266
|
+
if (err.code == 'MODULE_NOT_FOUND') {
|
267
|
+
winston.info("PubModulesManager init apps module not found");
|
268
|
+
}else {
|
269
|
+
winston.info("PubModulesManager error initializing init apps module", err);
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
try {
|
274
|
+
this.kaleyra = require('./kaleyra');
|
275
|
+
winston.debug("this.kaleyra: " + this.kaleyra);
|
276
|
+
this.kaleyra.listener.listen(config);
|
277
|
+
|
278
|
+
this.kaleyraRoute = this.kaleyra.kaleyraRoute;
|
279
|
+
|
280
|
+
winston.info("PubModulesManager initialized apps.");
|
281
|
+
} catch(err) {
|
282
|
+
if (err.code == 'MODULE_NOT_FOUND') {
|
283
|
+
winston.info("PubModulesManager init apps module not found");
|
284
|
+
}else {
|
285
|
+
winston.info("PubModulesManager error initializing init apps module", err);
|
286
|
+
}
|
287
|
+
}
|
221
288
|
|
222
289
|
try {
|
223
290
|
this.activityArchiver = require('./activities').activityArchiver;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
const whatsapp = require("@tiledesk/tiledesk-whatsapp-connector");
|
2
|
+
var winston = require('../../config/winston');
|
3
|
+
var configGlobal = require('../../config/global');
|
4
|
+
|
5
|
+
const apiUrl = process.env.API_URL || configGlobal.apiUrl;
|
6
|
+
winston.info('Whatsapp apiUrl: ' + apiUrl);
|
7
|
+
|
8
|
+
class Listener {
|
9
|
+
|
10
|
+
listen(config) {
|
11
|
+
winston.info("WhatsApp Listener listen");
|
12
|
+
if (config.databaseUri) {
|
13
|
+
winston.debug("whatsapp config databaseUri: " + config.databaseUri);
|
14
|
+
}
|
15
|
+
|
16
|
+
whatsapp.startApp({
|
17
|
+
MONGODB_URL: config.databaseUri,
|
18
|
+
API_URL: apiUrl,
|
19
|
+
GRAPH_URL: process.env.META_GRAPH_URL || config.graphUrl,
|
20
|
+
BASE_URL: apiUrl + "/modules/whatsapp",
|
21
|
+
APPS_API_URL: apiUrl + "/modules/apps",
|
22
|
+
log: process.env.WHATSAPP_LOG
|
23
|
+
}, () => {
|
24
|
+
winston.info("Tiledesk WhatsApp Connector proxy server succesfully started.");
|
25
|
+
})
|
26
|
+
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
var listener = new Listener();
|
31
|
+
|
32
|
+
module.exports = listener;
|
package/routes/email.js
CHANGED
@@ -17,10 +17,10 @@ router.get('/templates/:templateid',
|
|
17
17
|
router.post('/test/send',
|
18
18
|
async (req, res) => {
|
19
19
|
let to = req.body.to;
|
20
|
-
winston.
|
20
|
+
winston.debug("to",to);
|
21
21
|
|
22
22
|
let configEmail = req.body.config;
|
23
|
-
winston.
|
23
|
+
winston.debug("configEmail", configEmail);
|
24
24
|
|
25
25
|
emailService.sendTest(to, configEmail, function(err,obj) {
|
26
26
|
// winston.info("sendTest rest", err, obj);
|
@@ -29,4 +29,28 @@ router.post('/test/send',
|
|
29
29
|
|
30
30
|
});
|
31
31
|
|
32
|
+
|
33
|
+
router.post('/send',
|
34
|
+
async (req, res) => {
|
35
|
+
let to = req.body.to;
|
36
|
+
winston.info("to: " + to);
|
37
|
+
|
38
|
+
let text = req.body.text;
|
39
|
+
winston.info("text: " + text);
|
40
|
+
|
41
|
+
let request_id = req.body.request_id;
|
42
|
+
winston.info("request_id: " + request_id);
|
43
|
+
|
44
|
+
let subject = req.body.subject;
|
45
|
+
winston.info("subject: " + subject);
|
46
|
+
|
47
|
+
winston.info("req.project", req.project);
|
48
|
+
|
49
|
+
//sendEmailDirect(to, text, project, request_id, subject, tokenQueryString, sourcePage)
|
50
|
+
emailService.sendEmailDirect(to, text, req.project, request_id, subject, undefined, undefined);
|
51
|
+
|
52
|
+
res.json({"queued": true});
|
53
|
+
|
54
|
+
});
|
55
|
+
|
32
56
|
module.exports = router;
|
package/services/emailService.js
CHANGED
@@ -1030,7 +1030,7 @@ class EmailService {
|
|
1030
1030
|
|
1031
1031
|
}
|
1032
1032
|
|
1033
|
-
|
1033
|
+
|
1034
1034
|
|
1035
1035
|
async sendEmailChannelNotification(to, message, project, tokenQueryString, sourcePage) {
|
1036
1036
|
|
@@ -1360,10 +1360,6 @@ class EmailService {
|
|
1360
1360
|
}
|
1361
1361
|
|
1362
1362
|
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
1363
|
/*
|
1368
1364
|
sendEmailChannelTakingNotification(to, request, project, tokenQueryString) {
|
1369
1365
|
|
@@ -1411,6 +1407,102 @@ class EmailService {
|
|
1411
1407
|
}
|
1412
1408
|
*/
|
1413
1409
|
|
1410
|
+
|
1411
|
+
|
1412
|
+
|
1413
|
+
|
1414
|
+
|
1415
|
+
|
1416
|
+
async sendEmailDirect(to, text, project, request_id, subject, tokenQueryString, sourcePage) {
|
1417
|
+
|
1418
|
+
var that = this;
|
1419
|
+
|
1420
|
+
|
1421
|
+
if (project.toJSON) {
|
1422
|
+
project = project.toJSON();
|
1423
|
+
}
|
1424
|
+
|
1425
|
+
var html = await this.readTemplate('emailDirect.html', project.settings);
|
1426
|
+
|
1427
|
+
var envTemplate = process.env.EMAIL_DIRECT_HTML_TEMPLATE;
|
1428
|
+
winston.debug("envTemplate: " + envTemplate);
|
1429
|
+
|
1430
|
+
if (envTemplate) {
|
1431
|
+
html = envTemplate;
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
winston.debug("html: " + html);
|
1435
|
+
|
1436
|
+
var template = handlebars.compile(html);
|
1437
|
+
|
1438
|
+
var baseScope = JSON.parse(JSON.stringify(that));
|
1439
|
+
delete baseScope.pass;
|
1440
|
+
|
1441
|
+
|
1442
|
+
let msgText = text;
|
1443
|
+
msgText = encode(msgText);
|
1444
|
+
if (this.markdown) {
|
1445
|
+
msgText = marked(msgText);
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
winston.debug("msgText: " + msgText);
|
1449
|
+
winston.debug("baseScope: " + JSON.stringify(baseScope));
|
1450
|
+
|
1451
|
+
|
1452
|
+
var replacements = {
|
1453
|
+
project: project,
|
1454
|
+
seamlessPage: sourcePage,
|
1455
|
+
msgText: msgText,
|
1456
|
+
tokenQueryString: tokenQueryString,
|
1457
|
+
baseScope: baseScope
|
1458
|
+
};
|
1459
|
+
|
1460
|
+
var html = template(replacements);
|
1461
|
+
winston.debug("html: " + html);
|
1462
|
+
|
1463
|
+
|
1464
|
+
let replyTo;
|
1465
|
+
if (this.replyEnabled) {
|
1466
|
+
replyTo = request_id + this.inboundDomainDomainWithAt;
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
let from;
|
1470
|
+
let configEmail;
|
1471
|
+
if (project && project.settings && project.settings.email) {
|
1472
|
+
if (project.settings.email.config) {
|
1473
|
+
configEmail = project.settings.email.config;
|
1474
|
+
winston.verbose("custom email configEmail setting found: ", configEmail);
|
1475
|
+
}
|
1476
|
+
if (project.settings.email.from) {
|
1477
|
+
from = project.settings.email.from;
|
1478
|
+
winston.verbose("custom from email setting found: "+ from);
|
1479
|
+
}
|
1480
|
+
}
|
1481
|
+
|
1482
|
+
|
1483
|
+
// if (message.request && message.request.lead && message.request.lead.email) {
|
1484
|
+
// winston.info("message.request.lead.email: " + message.request.lead.email);
|
1485
|
+
// replyTo = replyTo + ", "+ message.request.lead.email;
|
1486
|
+
// }
|
1487
|
+
|
1488
|
+
// if (!subject) {
|
1489
|
+
// subject = "Tiledesk"
|
1490
|
+
// }
|
1491
|
+
|
1492
|
+
that.send({
|
1493
|
+
from:from,
|
1494
|
+
to:to,
|
1495
|
+
replyTo: replyTo,
|
1496
|
+
subject:subject,
|
1497
|
+
text:html,
|
1498
|
+
html:html,
|
1499
|
+
config:configEmail,
|
1500
|
+
});
|
1501
|
+
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
|
1505
|
+
|
1414
1506
|
// ok
|
1415
1507
|
async sendPasswordResetRequestEmail(to, resetPswRequestId, userFirstname, userLastname) {
|
1416
1508
|
|
@@ -1693,6 +1785,5 @@ async sendRequestTranscript(to, messages, request, project) {
|
|
1693
1785
|
|
1694
1786
|
var emailService = new EmailService();
|
1695
1787
|
|
1696
|
-
// emailService.sendTest("abc@abc.it");
|
1697
1788
|
|
1698
1789
|
module.exports = emailService;
|
@@ -94,7 +94,7 @@
|
|
94
94
|
{{currentUserFirstname}} {{currentUserLastname}} has invited you to the TileDesk project <strong> {{projectName}}</strong>
|
95
95
|
</h2>
|
96
96
|
|
97
|
-
<br> <br
|
97
|
+
<br> <br><strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Hi {{invitedUserFirstname}} {{invitedUserLastname}},</strong>
|
98
98
|
|
99
99
|
<br> <br>
|
100
100
|
I invited you to take on the role of {{invitedUserRole}} of the TileDesk <strong> {{projectName}}</strong> project
|
@@ -95,7 +95,7 @@
|
|
95
95
|
{{currentUserFirstname}} {{currentUserLastname}} has invited you to the Tiledesk project <strong> {{projectName}}</strong>
|
96
96
|
</h2>
|
97
97
|
|
98
|
-
<br> <br
|
98
|
+
<br> <br><strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{to}},</strong>
|
99
99
|
|
100
100
|
<br> <br>
|
101
101
|
I invited you to take on the role of {{invitedUserRole}} of the Tiledesk <strong> {{projectName}}</strong> project
|
@@ -0,0 +1,121 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta name="viewport" content="width=device-width" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7
|
+
<title>New Ticket from TileDesk</title>
|
8
|
+
|
9
|
+
<style type="text/css">
|
10
|
+
img {
|
11
|
+
max-width: 100%;
|
12
|
+
margin-left:16px;
|
13
|
+
margin-bottom:16px;
|
14
|
+
text-align:center !important;
|
15
|
+
}
|
16
|
+
body {
|
17
|
+
-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em;
|
18
|
+
}
|
19
|
+
body {
|
20
|
+
background-color: #f6f6f6;
|
21
|
+
}
|
22
|
+
|
23
|
+
@media only screen and (max-width: 640px) {
|
24
|
+
body {
|
25
|
+
padding: 0 !important;
|
26
|
+
}
|
27
|
+
h1 {
|
28
|
+
font-weight: 800 !important; margin: 20px 0 5px !important;
|
29
|
+
text-align:center !important;
|
30
|
+
}
|
31
|
+
h2 {
|
32
|
+
font-weight: 800 !important; margin: 20px 0 5px !important;
|
33
|
+
}
|
34
|
+
h3 {
|
35
|
+
font-weight: 800 !important; margin: 20px 0 5px !important;
|
36
|
+
}
|
37
|
+
h4 {
|
38
|
+
font-weight: 800 !important; margin: 20px 0 5px !important;
|
39
|
+
}
|
40
|
+
h1 {
|
41
|
+
font-size: 22px !important;
|
42
|
+
}
|
43
|
+
h2 {
|
44
|
+
font-size: 18px !important;
|
45
|
+
}
|
46
|
+
h3 {
|
47
|
+
font-size: 16px !important;
|
48
|
+
}
|
49
|
+
.container {
|
50
|
+
padding: 0 !important; width: 100% !important;
|
51
|
+
}
|
52
|
+
.content {
|
53
|
+
padding: 0 !important;
|
54
|
+
}
|
55
|
+
.content-wrap {
|
56
|
+
padding: 10px !important;
|
57
|
+
}
|
58
|
+
.invoice {
|
59
|
+
width: 100% !important;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
</style>
|
63
|
+
</head>
|
64
|
+
|
65
|
+
<body itemscope itemtype="http://schema.org/EmailMessage" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
|
66
|
+
|
67
|
+
{{#if baseScope.replyEnabled}}
|
68
|
+
<div>\# Please type your reply above this line \#</div>
|
69
|
+
{{/if}}
|
70
|
+
|
71
|
+
<table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
|
72
|
+
|
73
|
+
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
74
|
+
<td class="alert alert-warning" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; margin: 0;" align="center" valign="top">
|
75
|
+
|
76
|
+
<div style="text-align:center">
|
77
|
+
<a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
|
78
|
+
<!-- <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:20%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd"> -->
|
79
|
+
<img src="https://tiledesk.com/wp-content/uploads/2022/09/tiledeesk_log_email.png" style="max-width:200px;outline:none;text-decoration:none;border:none;height:auto;margin-left:0px;" class="CToWUd">
|
80
|
+
</a>
|
81
|
+
</div>
|
82
|
+
</td>
|
83
|
+
</tr>
|
84
|
+
|
85
|
+
|
86
|
+
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
87
|
+
<td class="content-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;" valign="top">
|
88
|
+
<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
94
|
+
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
95
|
+
<div style="white-space: pre-wrap;">{{{msgText}}}</div>
|
96
|
+
</td>
|
97
|
+
</tr>
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
103
|
+
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
104
|
+
</td>
|
105
|
+
</tr>
|
106
|
+
</table>
|
107
|
+
</td>
|
108
|
+
</tr>
|
109
|
+
</table>
|
110
|
+
<div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
|
111
|
+
<table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
112
|
+
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
113
|
+
<td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">
|
114
|
+
<span><a href="http://www.tiledesk.com" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;" > Tiledesk.com </a></span>
|
115
|
+
<!-- <br><span><a href="%unsubscribe_url%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">Unsubscribe</a></span> -->
|
116
|
+
</td>
|
117
|
+
</tr>
|
118
|
+
</table>
|
119
|
+
|
120
|
+
</body>
|
121
|
+
</html>
|