From 6adeb32d468c7f83ffff3c32b3cc021a7dd79eeb Mon Sep 17 00:00:00 2001 From: Paolo Arena Date: Wed, 4 Dec 2019 02:03:44 +0100 Subject: [PATCH] - Import emails from a list to a DB - Create Template Emails - Options Email --- emails/newsletter/it/html.pug | 282 ++++++++++++++------- package.json | 1 - src/server/models/discipline.js | 18 +- src/server/models/mailinglist.js | 43 +++- src/server/models/myevent.js | 26 ++ src/server/models/newstosent.js | 38 ++- src/server/models/opzemail.js | 47 ++++ src/server/models/settings.js | 17 +- src/server/models/templemail.js | 66 +++++ src/server/router/booking_router.js | 8 +- src/server/router/index_router.js | 17 +- src/server/router/myevent_router.js | 4 +- src/server/router/newsletter_router.js | 305 ++++++++++++++++++++--- src/server/router/sendmsg_router.js | 4 +- src/server/router/users_router.js | 2 +- src/server/sendemail.js | 330 ++++++++++++++++++++----- src/server/server.js | 5 +- src/server/tools/general.js | 30 +++ src/server/tools/server_constants.js | 29 +++ 19 files changed, 1061 insertions(+), 211 deletions(-) create mode 100644 src/server/models/opzemail.js create mode 100644 src/server/models/templemail.js diff --git a/emails/newsletter/it/html.pug b/emails/newsletter/it/html.pug index 6b1b470..8001717 100644 --- a/emails/newsletter/it/html.pug +++ b/emails/newsletter/it/html.pug @@ -3,20 +3,19 @@ -var date = new Date(dateString); -var d = date.getDate(); -var monthNames = [ "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic" ]; + -var monthDays = ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"]; -var m = monthNames[date.getMonth()]; -var y = date.getFullYear(); - -return d+' '+m+' '+y; + -var day = monthDays[date.getDay()]; + -return day+ ' '+d+' '+m+' '+y; -} -- var urlweb = 'http://www.prova.it' -- var urlevent = 'http://www.evento.it' -- var urlunsibscribe = '' -- var urltwitter = '' -- var urlfb = '' -- var imgtwitter = 'https://associazioneshen.it/statics/images/logo.png' -- var imgfb = 'https://associazioneshen.it/statics/images/logo.png' -- var baseurl = 'https://associazioneshen.it/' -- var baseimg = baseurl + 'statics/' +- var urlcal = baseurl + '/calendario-eventi/' +- var imginstagram = baseurl + '/statics/images/images/footer-instagram-icon.png' +- var imgtwitter = baseurl + '/statics/images/images/footer-twitter-icon.png' +- var imgyoutube = baseurl + '/statics/images/images/footer-youtube-icon.png' +- var imgfb = baseurl + '/statics/images/images/footer-facebook-icon.png' +- var baseimg = baseurl + '/statics/' doctype html html head @@ -40,102 +39,213 @@ html span(id='body_style', style='display:block') table(class="preheader", cellpadding="0", cellspacing="0", width="100%") tr - td.preheaderContent - p Preloader td.webversion p non vedi le immagini?  - a(href=urlweb) Apri la pagina qui + a(href=urlcal) Apri il Calendario table(class="topHeader", cellpadding="0", cellspacing="0", width="100%") tr td - table(cellpadding="0", cellspacing="0", width="300", align="center", summary="") + table(cellpadding="0", cellspacing="0", align="center", summary="") tr td.logoContainer - a(href=urlweb, title='logo') - img.logo(src="https://associazioneshen.it/statics/images/logo.png") + a(href=baseurl, title='logo') + img.logo(src=baseurl+"/statics/images/logo.png", height=dataemail.height_logo) + tr + td.testomail + p!= dataemail.templ.testoheadermail + + - if (dataemail.templ.options.includes('SHOW_PROMO')) + tr + td.clpromo + p!= dataemail.textpromo + + - if (dataemail.templ.content) + table(cellpadding="0", cellspacing="0", width="95%", align="center") + tr + td(class="textIniContainer", valign="top") + p!=dataemail.templ.content + - if (dataemail.templ.img) + img(src=baseimg + dataemail.templ.img, alt="", class="myimg") + - if (dataemail.templ.content2) + p!=dataemail.templ.content2 + - if (dataemail.templ.img2) + img(src=baseimg + dataemail.templ.img2, alt="", class="myimg") table(cellpadding="0", cellspacing="0", width="640", align="center") - tr - td(class="whitespace", height="10") - p   - tr - td(class="emailContainer", valign="top") + - if (dataemail.templ.options.includes('SHOW_EVENTS')) + tr + td(class="whitespace", height="10") + p   + tr + td(class="emailContainer", valign="top") - each event in arrevents - - var urlevent = baseurl + 'event/' + event.typol + '/' + event._id - - var imgev = event.img_small - - var mydate = prettyDate(event.dateTimeStart) - unless (imgev) - - var imgev = event.img + each event in arrevents + - var urlevent = baseurl + '/event/' + event.typol + '/' + event._id + - var imgev = event.img_small + - var mydate = prettyDate(event.dateTimeStart) + unless (imgev) + - imgev = event.img + - var teacher1 = '' + - var teacher2 = '' + - var contrib = '' + - var myclteach = 'q-chip' + - if (event.op1[0]) + - teacher1 = event.op1[0].name + ' ' + event.op1[0].surname + - if (event.op2[0]) + - teacher2 = event.op2[0].name + ' ' + event.op2[0].surname + - myclteach = 'q-chip2' - table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") + - if (event.contrib[0]) + - contrib = event.contrib[0].label + - if (event.contrib[0].showprice) + - contrib += ' ' + event.price + ' €' + + + table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") + tr + td(class="column sectionArticleImage", valign="top") + table(cellpadding="0", cellspacing="0", summary="", border="0") + - if (event.news) + tr + td + p(class="q-chip row inline no-wrap items-center cltexth5 chipnews shadow-5 glossy text-right bg-red text-white") Novità + tr + td + img(src=baseimg + imgev, alt="", width="150") + p(class="teacher") #{teacher1}
#{teacher2} + td(class="column", valign="top") + + table(cellpadding="0", cellspacing="0", summary="", border="0") + tr + td(class="sectionContentTitle boldhigh", valign="top") + p #{event.title} + tr + td(class="sectionContentSubTitle", valign="top") + p(class="q-chip row inline no-wrap items-center cltexth5 chipnews shadow-5 glossy text-right bg-blue text-white") #{mydate} + tr + td(class="sectionContent", valign="top") + p!= event.details + p.contrib= contrib + tr + td(class="buttonContainer") + table(width="50%", cellpadding="0", cellspacing="0", summary="", border="0") + tr + td(class="button hoverLink") + a(href=urlevent, title='Evento', target='_blank') Apri l'Evento + + tr + table(cellpadding="0", cellspacing="0", summary="", border="0", align="center", class="") tr - td(class="column sectionArticleImage", valign="top") - img(src=baseimg + imgev, alt="", width="150") - td(class="column", valign="top") + td(class="whitespace", height="10") + p   + tr + td.center_img(class="button2 hoverLink") + a(href=urlcal, title='Calendario Eventi', target='_blank') Calendario Eventi + tr + td(class="whitespace", height="10") + p   - table(cellpadding="0", cellspacing="0", summary="", border="0") - tr - td(class="sectionContentTitle", valign="top") - p #{event.title} - tr - td(class="sectionContentSubTitle", valign="top") - p(style='color:blue;') #{mydate} - tr - td(class="sectionContent", valign="top") - p!= event.details - tr - td(class="buttonContainer") - table(width="50%", cellpadding="0", cellspacing="0", summary="", border="0") - tr - td(class="button") - a(href=urlevent, title='Evento') Apri l'Evento + - if (dataemail.templ.options.includes('SHOW_DISC')) + tr + td(class="whitespace bg-white", height="20") + p(class="bg-white")   + tr + td(class="center") + p(class="cltitle_disc") #{dataemail.disc_title} + tr + td(class="discContainer", valign="top") + + each disc in dataemail.arrdiscipline + - var urldisc = baseurl + disc.linkpage + - var imgdisc = disc.img_small + unless (imgdisc) + - imgdisc = disc.img + + table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") + tr + td(class="column sectionArticleImage", valign="top") + table(cellpadding="0", cellspacing="0", summary="", border="0") + tr + td + img(src=baseimg + imgdisc, alt="", width="150") + td(class="column", valign="top") + + table(cellpadding="0", cellspacing="0", summary="", border="0") + tr + td(class="sectionContentTitle boldhigh center LinkDisc", valign="top") + a(href=urldisc, title='Disciplina', target='_blank') + p(class="q-chip row inline no-wrap items-center cltexth4 chipnews shadow-5 glossy text-right text-white pDisc", style=`background-color: `+disc.color) #{disc.label} + tr + td(class="sectionContent", valign="top") + p!= disc.description tr td(class="whitespace", height="20") p   - tr - td(class="whitespace", height="20") - p   - // Social Media - table.socialMedia(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") - tr - td(class="whitespace", height="20") - p   - tr - td - table(width="120", cellpadding="0", cellspacing="0", summary="", border="0", align="center") - tr - td(width="32", align="center") - a(href=urltwitter, title='Twitter') - img(src=imgtwitter, alt="Twitter", width="29") - td(width="32", align="center") - a(href=urlfb, title='Facebook') - img(src=imgfb, alt="Facebook", width="29") + - if (dataemail.content_after_events) + tr + table(cellpadding="0", cellspacing="0", summary="", border="0") + tr + td.testomail + p!=dataemail.content_after_events + tr + td(class="whitespace", height="20") + p   - tr - td(class="whitespace", height="20") - p   + tr + td(class="whitespace", height="20") + p   - // Footer - table.footer(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") - tr - td(class="whitespace", height="10") - p   - tr - td.whitespace - table(width="50%", cellpadding="0", cellspacing="0", summary="", border="0") - tr - td(class="footNotes", align="center") - a(href=urlunsibscribe, title='Disiscriviti') Disiscriviti - td(class="footNotes", align="center") - a(href="#", title='Lorem') Lorem - td(class="footNotes", align="center") - a(href="#", title='Dolor') Lorem + // Social Media + table.socialMedia(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") + tr + td(class="whitespace", height="5") + p   + tr + td + table(width="120", cellpadding="0", cellspacing="0", summary="", border="0", align="center") + tr + - if (dataemail.urlinstagram) + td(width="32", align="center") + a(href=dataemail.urlinstagram, title='Instagram') + img(src=imginstagram, alt="Instagram", width="29") + - if (dataemail.urltwitter) + td(width="32", align="center") + a(href=dataemail.urltwitter, title='Twitter') + img(src=imgtwitter, alt="Twitter", width="29") + - if (dataemail.urlfb) + td(width="32", align="center") + a(href=dataemail.urlfb, title='Facebook') + img(src=imgfb, alt="Facebook", width="29") + - if (dataemail.urlyoutube) + td(width="32", align="center") + a(href=dataemail.urlyoutube, title='YouTube') + img(src=imgyoutube, alt="YouTube", width="29") - tr - td(class="whitespace", height="10") - p   + tr + td(class="whitespace", height="5") + p   + + // Footer + table.footer(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") + tr + td(class="whitespace", height="10") + p   + tr + td.firma + p!= dataemail.firma + + tr + td.disclaimer + p!= dataemail.disclaimer_out + + tr + td.bottom + p!= dataemail.disc_bottom_out + + tr + td(class="whitespace", height="10") + p   diff --git a/package.json b/package.json index ad3803c..1ceafa5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "express": "^4.17.1", "i18n": "^0.8.3", "jade": "^1.11.0", - "js-md5": "^0.7.3", "jsonwebtoken": "^7.1.9", "lodash": "^4.17.15", "mongodb": "^2.2.5", diff --git a/src/server/models/discipline.js b/src/server/models/discipline.js index 72a4884..0a54a20 100644 --- a/src/server/models/discipline.js +++ b/src/server/models/discipline.js @@ -51,7 +51,7 @@ const DisciplineSchema = new Schema({ type: Boolean, }, teachers: [{ - type: String, + type: String, }], }); @@ -71,6 +71,22 @@ DisciplineSchema.statics.findAllIdApp = function (idapp) { }; +DisciplineSchema.statics.getDisciplineforNewsletter = function (idapp) { + const Discipline = this; + + const query = [ + { $match: { $and: [{ idapp }, { showinnewsletter: true }] } }, + { $sort: { order: 1 } } + ]; + + return Discipline + .aggregate(query) + .then((arrrec) => { + return arrrec + }) + +}; + DisciplineSchema.statics.getFieldsForSearch = function () { return ['label', 'description'] diff --git a/src/server/models/mailinglist.js b/src/server/models/mailinglist.js index bf64c9b..f68a2f5 100644 --- a/src/server/models/mailinglist.js +++ b/src/server/models/mailinglist.js @@ -20,6 +20,9 @@ const MailingListSchema = new Schema({ type: String, trim: true, }, + hash: { + type: String, + }, name: { type: String, trim: true, @@ -28,6 +31,10 @@ const MailingListSchema = new Schema({ type: String, trim: true, }, + statesub: { + type: Boolean, + default: true + }, lastid_newstosent: { type: String } @@ -42,10 +49,10 @@ MailingListSchema.statics.executeQueryTable = function (idapp, params) { return tools.executeQueryTable(this, idapp, params); }; -MailingListSchema.statics.findAllIdApp = function (idapp) { +MailingListSchema.statics.findAllIdAppSubscribed = function (idapp) { const MailingList = this; - const myfind = { idapp }; + const myfind = { idapp, statesub: true }; // Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit. @@ -54,6 +61,38 @@ MailingListSchema.statics.findAllIdApp = function (idapp) { }); }; +MailingListSchema.statics.findAllIdApp = async function (idapp) { + const MailingList = this; + + const myfind = { idapp }; + + return await MailingList.find(myfind, (err, arrrec) => { + return arrrec + }); +}; + +MailingListSchema.statics.isUnsubscribed = async function (idapp, hash) { + const MailingList = this; + + let myperson = await MailingList.findOne({ idapp, hash }); + console.log('myperson', myperson); + if (!!myperson) { + return (!myperson.statesub) + } +}; + +MailingListSchema.statics.findByHash = function (idapp, hash) { + const MailingList = this; + + const myfind = { idapp, hash }; + + // Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit. + + return MailingList.findOne(myfind, (err, rec) => { + return rec + }); +}; + const MailingList = mongoose.model('MailingList', MailingListSchema); module.exports = { MailingList }; diff --git a/src/server/models/myevent.js b/src/server/models/myevent.js index 95e1de1..6b19b08 100644 --- a/src/server/models/myevent.js +++ b/src/server/models/myevent.js @@ -120,12 +120,38 @@ MyEventSchema.statics.getLastEvents = function (idapp) { const query = [ { $match: { idapp } }, + { + $lookup: { + from: 'operators', + localField: 'teacher', + foreignField: 'username', + as: 'op1' + } + }, + { + $lookup: { + from: 'operators', + localField: 'teacher2', + foreignField: 'username', + as: 'op2' + } + }, + { "$addFields": { "contribtype": { "$toObjectId": "$contribtype" } } }, + { + $lookup: { + from: 'contribtypes', + localField: 'contribtype', + foreignField: '_id', + as: 'contrib' + } + }, { $sort: { dateTimeStart: 1 } } ]; return Event .aggregate(query) .then((arrrec) => { + // console.table(arrrec); return arrrec.slice(-lastn) }) diff --git a/src/server/models/newstosent.js b/src/server/models/newstosent.js index f09579a..77d1a31 100644 --- a/src/server/models/newstosent.js +++ b/src/server/models/newstosent.js @@ -69,30 +69,32 @@ NewstosentSchema.statics.findNewsletter_To_Send = function (idapp) { const Newstosent = this; return Newstosent.findOne({ + // datetoSent: { $gte: tools.IncDateNow(-1000 * 60 * 60) }, datetoSent: { $gte: tools.IncDateNow(-1000 * 60 * 60) }, activate: true, starting_job: false, finish_job: false, idapp - }).then((rec) => { - return (rec) ? rec._doc : null; - }); + }) + .sort({ datetoSent: 1 }) + .then((rec) => { + return (rec) ? rec._doc : null; + }); }; NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) { const Newstosent = this; - // Resend the Email after N hours no other email sent. - const numhours = 8; return Newstosent.findOne({ datestartJob: { $lt: tools.IncDateNow(0) }, activate: true, starting_job: true, finish_job: false, - lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * numhours) }, + lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 8) }, idapp }).then((rec) => { + // console.log('findNewsletterPending_To_Send', rec); return (rec) ? rec._doc : null; }); }; @@ -109,6 +111,30 @@ NewstosentSchema.statics.findAllIdApp = function (idapp) { }); }; +NewstosentSchema.statics.getlast = async function (idapp) { + const Newstosent = this; + + try { + const mydoc = await Newstosent.find({ idapp }).sort({ datestartJob: -1 }).limit(1); + return mydoc[0]._doc; + } catch (e) { + return null + } +}; + +NewstosentSchema.statics.isActivated = async function (_id) { + const Newstosent = this; + + try { + const mydoc = await Newstosent.findOne({ _id }); + return (mydoc._doc.activate); + } catch (e) { + return false + } +}; + + + const Newstosent = mongoose.model('Newstosent', NewstosentSchema); module.exports = { Newstosent }; diff --git a/src/server/models/opzemail.js b/src/server/models/opzemail.js new file mode 100644 index 0000000..babbcab --- /dev/null +++ b/src/server/models/opzemail.js @@ -0,0 +1,47 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const tools = require('../tools/general'); + +mongoose.Promise = global.Promise; +mongoose.level = "F"; + + +// Resolving error Unknown modifier: $pushAll +mongoose.plugin(schema => { + schema.options.usePushEach = true +}); + +const OpzEmailSchema = new Schema({ + key: { + type: String, + default: '' + }, + label_it: { + type: String, + } +}); + + +OpzEmailSchema.statics.getFieldsForSearch = function () { + return ['label_it'] +}; + +OpzEmailSchema.statics.executeQueryTable = function (idapp, params) { + params.fieldsearch = this.getFieldsForSearch(); + return tools.executeQueryTable(this, 0, params); +}; + + +OpzEmailSchema.statics.findAllIdApp = async function (idapp) { + const OpzEmail = this; + + return await OpzEmail.find({}, (err, arrrec) => { + return arrrec + }); +}; + + +const OpzEmail = mongoose.model('OpzEmail', OpzEmailSchema); + +module.exports = { OpzEmail }; diff --git a/src/server/models/settings.js b/src/server/models/settings.js index 6991d6a..749df7d 100644 --- a/src/server/models/settings.js +++ b/src/server/models/settings.js @@ -30,6 +30,13 @@ const SettingsSchema = new Schema({ }, value_num: { type: Number, + }, + value_bool: { + type: Boolean, + }, + serv: { + type: Boolean, + default: false } }); @@ -45,12 +52,14 @@ SettingsSchema.statics.executeQueryTable = function (idapp, params) { SettingsSchema.statics.getValDbSettings = function (idapp, key) { return Settings.findOne({ idapp, key }) .then((myrec) => { - console.log('getValDbSettings', myrec, 'idapp', idapp); + // console.log('getValDbSettings', myrec, 'idapp', idapp); if (myrec) { if (myrec.type === tools.FieldType.date) return myrec.value_date; - if (myrec.type === tools.FieldType.number) + else if (myrec.type === tools.FieldType.number) return myrec.value_num; + else if (myrec.type === tools.FieldType.boolean) + return myrec.value_bool; else return myrec.value_str; } else { @@ -64,10 +73,10 @@ SettingsSchema.statics.getValDbSettings = function (idapp, key) { }; -SettingsSchema.statics.findAllIdApp = function (idapp) { +SettingsSchema.statics.findAllIdApp = function (idapp, serv) { const Settings = this; - const myfind = { idapp }; + const myfind = { idapp, serv }; return Settings.find(myfind, (err, arrrec) => { return arrrec diff --git a/src/server/models/templemail.js b/src/server/models/templemail.js new file mode 100644 index 0000000..4120891 --- /dev/null +++ b/src/server/models/templemail.js @@ -0,0 +1,66 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const tools = require('../tools/general'); + +mongoose.Promise = global.Promise; +mongoose.level = "F"; + + +// Resolving error Unknown modifier: $pushAll +mongoose.plugin(schema => { + schema.options.usePushEach = true +}); + +const TemplEmailSchema = new Schema({ + idapp: { + type: String, + }, + subject: { + type: String, + }, + testoheadermail: { + type: String, + }, + content: { + type: String, + }, + img: { + type: String, + }, + content2: { + type: String, + }, + img2: { + type: String, + }, + + options: [{ + type: String, + }] +}); + +TemplEmailSchema.statics.getFieldsForSearch = function () { + return [''] +}; + +TemplEmailSchema.statics.executeQueryTable = function (idapp, params) { + params.fieldsearch = this.getFieldsForSearch(); + return tools.executeQueryTable(this, idapp, params); +}; + + +TemplEmailSchema.statics.findAllIdApp = async function (idapp) { + const TemplEmail = this; + + const myfind = { idapp }; + + return await TemplEmail.find(myfind, (err, arrrec) => { + return arrrec + }); +}; + + +const TemplEmail = mongoose.model('TemplEmail', TemplEmailSchema); + +module.exports = { TemplEmail }; diff --git a/src/server/router/booking_router.js b/src/server/router/booking_router.js index 9737fa6..3e00071 100644 --- a/src/server/router/booking_router.js +++ b/src/server/router/booking_router.js @@ -14,15 +14,15 @@ const sendemail = require('../sendemail'); const _ = require('lodash'); -function sendNotif(res, idapp, user, recbooking) { +const sendNotif = async (res, idapp, user, recbooking) => { //++Todo: tools.sendNotificationToUser // Send Email if (recbooking.booked) - sendemail.sendEmail_Booking(res, user.lang, user.email, user, idapp, recbooking); + return await sendemail.sendEmail_Booking(res, user.lang, user.email, user, idapp, recbooking); else - sendemail.sendEmail_CancelBooking(res, user.lang, user.email, user, idapp, recbooking); -} + return await sendemail.sendEmail_CancelBooking(res, user.lang, user.email, user, idapp, recbooking); +}; router.post('/', authenticate, (req, res) => { // tools.mylog('INIZIO - booking'); diff --git a/src/server/router/index_router.js b/src/server/router/index_router.js index 0e07e56..51729fe 100644 --- a/src/server/router/index_router.js +++ b/src/server/router/index_router.js @@ -18,6 +18,8 @@ const { MyEvent } = require('../models/myevent'); const { Contribtype } = require('../models/contribtype'); const { Discipline } = require('../models/discipline'); const { Newstosent } = require('../models/newstosent'); +const { TemplEmail } = require('../models/templemail'); +const { OpzEmail } = require('../models/opzemail'); const { MailingList } = require('../models/mailinglist'); const { Settings } = require('../models/settings'); const { SendMsg } = require('../models/sendmsg'); @@ -80,8 +82,8 @@ router.post(process.env.LINK_REQUEST_NEWPASSWORD, (req, res) => { user.tokenforgot = jwt.sign(user._id.toHexString(), process.env.SIGNCODE).toString(); user.date_tokenforgot = new Date(); user.lasttimeonline = new Date(); - user.save().then(() => { - sendemail.sendEmail_RequestNewPassword(res.locale, user.email, user.idapp, user.tokenforgot); + user.save().then( async () => { + await sendemail.sendEmail_RequestNewPassword(res.locale, user.email, user.idapp, user.tokenforgot); res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); }); } @@ -150,6 +152,10 @@ function getTableByTableName(tablename) { mytable = Discipline; else if (tablename === 'newstosent') mytable = Newstosent; + else if (tablename === 'templemail') + mytable = TemplEmail; + else if (tablename === 'opzemail') + mytable = OpzEmail; else if (tablename === 'settings') mytable = Settings; else if (tablename === 'permissions') @@ -199,7 +205,8 @@ router.post('/gettable', authenticate, (req, res) => { const mytable = getTableByTableName(params.table); // console.log('mytable', mytable); if (!mytable) { - return res.status(400).send(e); + console.log(`Table ${params.table} not found`); + return res.status(400).send({}); } return mytable.executeQueryTable(req.user.idapp, params).then(ris => { @@ -349,14 +356,14 @@ router.get('/loadsite/:userId/:idapp/:sall', authenticate_noerror, (req, res) => const wheres = Where.findAllIdApp(idapp); const contribtype = Contribtype.findAllIdApp(idapp); const disciplines = Discipline.findAllIdApp(idapp); - const settings = Settings.findAllIdApp(idapp); + const settings = Settings.findAllIdApp(idapp, false); + const permissions = Permission.findAllIdApp(); let newstosent = Promise.resolve([]); let mailinglist = Promise.resolve([]); if (sall){ newstosent = Newstosent.findAllIdApp(idapp); - mailinglist = MailingList.findAllIdApp(idapp); } return Promise.all([bookedevent, eventlist, operators, wheres, contribtype, settings, permissions, disciplines, newstosent, mailinglist]) diff --git a/src/server/router/myevent_router.js b/src/server/router/myevent_router.js index 1957ead..59f550b 100644 --- a/src/server/router/myevent_router.js +++ b/src/server/router/myevent_router.js @@ -30,7 +30,7 @@ router.post('/', authenticate, (req, res) => { // Modify: return MyEvent.findOne({ id }) - .then(trovato => { + .then((trovato) => { // console.log('trovato', trovato); if (trovato) { return myevent.findOneAndUpdate({ id }, { $set: fieldtochange }, { @@ -40,6 +40,8 @@ router.post('/', authenticate, (req, res) => { // tools.mylog('myevent:', myevent); // tools.mylog('already exist'); sendNotif(res, myrec.idapp, req.user, recmyevent); + return res + }).then((res) => { res.send({ code: server_constants.RIS_CODE_OK, msg: '', id: recmyevent._id }); }); } else { diff --git a/src/server/router/newsletter_router.js b/src/server/router/newsletter_router.js index 4bcc408..940ff2d 100644 --- a/src/server/router/newsletter_router.js +++ b/src/server/router/newsletter_router.js @@ -7,6 +7,11 @@ const request = require('superagent'); const sendemail = require('../sendemail'); const { User } = require('../models/user'); +const { MailingList } = require('../models/mailinglist'); +const { Newstosent } = require('../models/newstosent'); +const { TemplEmail } = require('../models/templemail'); +const { OpzEmail } = require('../models/opzemail'); +const { Settings } = require('../models/settings'); const tools = require('../tools/general'); const { authenticate } = require('../middleware/authenticate'); @@ -45,9 +50,55 @@ const newsletter = [ ]; -router.post('/', (req, res) => { +async function AddMailingList(locale, idapp, user, settomailchimp, sendnews) { - idwebsite = req.body.idwebsite; + return await sendemail.Add_to_MailingList_AndSendEmailNotify(locale, user, idapp, sendnews).then((ris) => { + + if (settomailchimp) { + request + .post('https://' + newsletter[idapp].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idapp].listUniqueId + '/members/') + .set('Content-Type', 'application/json;charset=utf-8') + .set('Authorization', 'Basic ' + new Buffer('any:' + newsletter[idapp].mailchimpApiKey).toString('base64')) + .send({ + 'email_address': req.body.email, + 'status': server_constants.RIS_SUBSCRIBED_STR, + 'merge_fields': { + 'FNAME': user.name, + 'LNAME': user.surname + } + }) + .end(function (err, response) { + console.log("STAT", response.status); + + if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) { + if (response.status === 400 && response.body.title === "Member Exists") + return { + code: server_constants.RIS_SUBSCRIBED_ALREADYEXIST, + msg: server_constants.RIS_SUBSCRIBED_MSG_ALREADYEXIST[locale] + }; + else + return { + code: server_constants.RIS_SUBSCRIBED_OK, + msg: server_constants.RIS_SUBSCRIBED_MSG[locale] + }; + } else { + return { + code: server_constants.RIS_SUBSCRIBED_ERR, + msg: server_constants.RIS_SUBSCRIBED_MSG_FAILED[locale] + }; + } + }); + + } else { + return ris; + } + + }); +} + +router.post('/signup', (req, res) => { + + settomailchimp = req.body.settomailchimp; idapp = req.body.idapp; locale = req.body.locale; @@ -57,35 +108,228 @@ router.post('/', (req, res) => { surname: req.body.lastName, }; - sendemail.sendEmail_Notif_Added_to_Newsletter(locale, user, idapp); - - request - .post('https://' + newsletter[idwebsite].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idwebsite].listUniqueId + '/members/') - .set('Content-Type', 'application/json;charset=utf-8') - .set('Authorization', 'Basic ' + new Buffer('any:' + newsletter[idwebsite].mailchimpApiKey).toString('base64')) - .send({ - 'email_address': req.body.email, - 'status': server_constants.RIS_SUBSCRIBED_STR, - 'merge_fields': { - 'FNAME': req.body.firstName, - 'LNAME': req.body.lastName - } - }) - .end(function (err, response) { - console.log("STAT", response.status); - - if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) { - if (response.status === 400 && response.body.title === "Member Exists") - res.send({result: server_constants.RIS_SUBSCRIBED_ALREADYEXIST, msg: server_constants.RIS_SUBSCRIBED_MSG_ALREADYEXIST[locale]}); - else - res.send({result: server_constants.RIS_SUBSCRIBED_OK, msg: server_constants.RIS_SUBSCRIBED_MSG[locale]}); - } else { - res.send({result: server_constants.RIS_SUBSCRIBED_ERR, msg: server_constants.RIS_SUBSCRIBED_MSG_FAILED[locale]}); - } - }); + return AddMailingList(locale, idapp, user, settomailchimp, true).then((ris) => { + return res.send(ris); + }); }); +async function ImportData(locale, idapp, strdata, settomailchimp) { + + try { + let numadded = 0; + let numtot = 0; + let numalreadyexisted = 0; + + // Convert to array + let arrusers = strdata.split('\n'); + if (arrusers.length <= 0) + arrusers = strdata.split(','); + if (arrusers.length <= 0) + arrusers = strdata.split(';'); + if (arrusers.length <= 0) + arrusers = strdata.split('\t'); + + let sep = ''; + + // Controlla se ci sono spazi + const arrtab = arrusers[0].split('\t'); + const arrspace = arrusers[0].split(' '); + const arrcomma = arrusers[0].split(','); + if (arrtab.length > 1) { + sep = '\t'; + } + if (arrspace.length > 1) { + sep = ' ' + } + if (arrcomma.length > 1) { + sep = ',' + } + + console.log('arrtab', arrtab); + console.log('arrspace', arrspace); + console.log('arrcomma', arrcomma); + + console.log('sep', sep); + + + try { + for (const row of arrusers) { + if (sep !== '') { + let arrrow = row.split(sep); + if (arrrow.length === 1) { + user = { + name: '', + surname: '', + email: arrrow[0] + } + } else { + user = { + name: arrrow[0], + surname: arrrow[1], + email: arrrow[2], + } + } + } else { + user = { + name: '', + surname: '', + email: row + } + } + console.log('user', user); + if (user.email.indexOf('@') > -1) { + numtot++; + + await AddMailingList(locale, idapp, user, settomailchimp, false).then((ris) => { + console.log('Addmail user', user, 'ris', ris); + if (ris.code === server_constants.RIS_SUBSCRIBED_OK) + numadded++; + else if (ris.code === server_constants.RIS_SUBSCRIBED_ALREADYEXIST) + numalreadyexisted++; + }); + } + } + + } catch (e) { + + } + + ris = {numadded, numtot, numalreadyexisted}; + + console.log(ris); + return ris + + } catch (e) { + console.err(e); + } +} + +router.post('/import', async (req, res) => { + + settomailchimp = req.body.settomailchimp; + const strdata = req.body.strdataemail; + idapp = req.body.idapp; + locale = req.body.locale; + + const ris = await ImportData(locale, idapp, strdata, settomailchimp); + console.log('ris', ris); + + res.send(ris); +}); + +async function getDataNewsletter(lang, idapp) { + const arrml = await MailingList.findAllIdApp(idapp); + + const lastnewstosent = await Newstosent.getlast(idapp); + const nextnewstosent = await Newstosent.findNewsletter_To_Send(idapp); + const lastid = (lastnewstosent) ? lastnewstosent._id : 0; + + const data = { + lastnewstosent, + nextnewstosent, + totemail: 0, + totsubscribed: 0, + totunsubscribed: 0, + totsentlastid: 0, + }; + + for (const user of arrml) { + data.totemail++; + if (user.statesub) + data.totsubscribed++; + else + data.totunsubscribed++; + if (user.lastid_newstosent === lastid) { + data.totsentlastid++; + } + } + + // await tools.snooze(2000); + + return data; +} + +router.post('/load', authenticate, async (req, res) => { + + idapp = req.body.idapp; + locale = req.body.locale; + + const ris = { + newsstate: await getDataNewsletter(locale, idapp), + serv_settings: await Settings.findAllIdApp(idapp, true), + templemail: await TemplEmail.findAllIdApp(idapp, true), + opzemail: await OpzEmail.findAllIdApp(idapp) + }; + + return res.send(ris); +}); + +router.post('/setactivate', authenticate, async (req, res) => { + + idapp = req.body.idapp; + activate = req.body.activate; + id = req.body._id; + locale = req.body.locale; + + const rec = { + activate + }; + + return await Newstosent.findOneAndUpdate({ _id: id }, { $set: rec }, { new: false }).then((item) => { + const ris = getDataNewsletter(locale, idapp); + + return res.send(ris); + + }); + +}); + +router.post('/unsubscribe', (req, res) => { + + console.log('unsubscribe -> ', req.body); + + hashemail = req.body.em; + mailchimpactive = tools.StrToBool(req.body.mc); + idapp = req.body.idapp; + locale = req.body.locale; + + sendemail.Remove_from_MailingList(locale, hashemail, idapp).then((ris) => { + console.log('Remove_from_MailingList -> ', ris); + + if (!!ris.myperson && mailchimpactive) { + const subscriber_md5_email = tools.getmd5(ris.myperson.email); + request + .put('https://' + newsletter[idapp].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idapp].listUniqueId + '/members/' + subscriber_md5_email) + .set('Content-Type', 'application/json;charset=utf-8') + .set('Authorization', 'Basic ' + new Buffer('any:' + newsletter[idapp].mailchimpApiKey).toString('base64')) + .send({ + 'email_address': ris.myperson.email, + 'status': server_constants.RIS_UNSUBSCRIBED_STR + }) + .end(function (err, response) { + console.log("STAT", response.status); + + if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) { + res.send({ + code: server_constants.RIS_UNSUBSCRIBED_OK + }); + } else { + res.send({ + code: server_constants.RIS_SUBSCRIBED_ERR + }); + } + }); + + } else { + res.send({ code: ris.code, msg: ris.msg }); + } + + }); + +}); + + router.post('/testemail', authenticate, async (req, res) => { if (!User.isAdmin(req.user)) { @@ -95,8 +339,9 @@ router.post('/testemail', authenticate, async (req, res) => { idapp = req.body.idapp; lang = req.body.locale; + previewonly = req.body.previewonly; - const ris = await sendemail.testemail(idapp, lang); + const ris = await sendemail.testemail(idapp, lang, previewonly); if (ris) return res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); @@ -105,4 +350,4 @@ router.post('/testemail', authenticate, async (req, res) => { }); - module.exports = router; +module.exports = router; diff --git a/src/server/router/sendmsg_router.js b/src/server/router/sendmsg_router.js index bafa4ed..f90d3f3 100644 --- a/src/server/router/sendmsg_router.js +++ b/src/server/router/sendmsg_router.js @@ -68,11 +68,11 @@ router.post('/', authenticate, (req, res) => { myrecmsg._id = idobj; return SendMsg.findById(idobj) - .then((recmsg) => { + .then(async (recmsg) => { // Add this field because I don't want to add into the database recmsg.source.infoevent = body.source.infoevent; - return sendNotif(res, body.idapp, req.user, recmsg).then((ris) => { + return await sendNotif(res, body.idapp, req.user, recmsg).then((ris) => { return res.send({ code: server_constants.RIS_CODE_OK, msg: '', id: recmsg._id }); }) }); diff --git a/src/server/router/users_router.js b/src/server/router/users_router.js index 57ef5d4..2709ca2 100644 --- a/src/server/router/users_router.js +++ b/src/server/router/users_router.js @@ -66,7 +66,7 @@ router.post('/', (req, res) => { // tools.mylog('process.env.TESTING_ON', process.env.TESTING_ON); console.log('res.locale', res.locale); if (!tools.testing()) { - sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg); + return sendemail.sendEmail_Registration(user.lang, user.email, user, user.idapp, user.linkreg); } }); diff --git a/src/server/sendemail.js b/src/server/sendemail.js index e4f65dd..654f1c9 100644 --- a/src/server/sendemail.js +++ b/src/server/sendemail.js @@ -8,6 +8,8 @@ var i18n = require("i18n"); const { ObjectID } = require('mongodb'); const { Settings } = require('./models/settings'); +const { TemplEmail } = require('./models/templemail'); +const { Discipline } = require('./models/discipline'); const previewEmail = require('preview-email'); const nodemailer = require("nodemailer"); @@ -16,19 +18,12 @@ const { MyEvent } = require('./models/myevent'); const { MailingList } = require('./models/mailinglist'); const { Newstosent } = require('./models/newstosent'); +const server_constants = require('./tools/server_constants'); + const transport_preview = nodemailer.createTransport({ jsonTransport: true }); -// create reusable transport method (opens pool of SMTP connections) -var smtpTransport = nodemailer.createTransport({ - service: 'Gmail', - auth: { - user: process.env.EMAIL_FROM, - pass: process.env.EMAIL_PW - } -}); - function checkifSendEmail() { return process.env.SEND_EMAIL === "1"; //return false; @@ -36,30 +31,44 @@ function checkifSendEmail() { module.exports = { - sendEmail_base: function (template, to, mylocalsconf, replyTo) { + sendEmail_base: function (template, to, mylocalsconf, replyTo, transport, previewonly) { - console.log('mylocalsconf', mylocalsconf); + // console.log('mylocalsconf', mylocalsconf); // console.log("check EMAIL :" + checkifSendEmail()); - const email = new Email({ + const paramemail = { message: { - from: process.env.EMAIL_FROM, // sender address + from: mylocalsconf.dataemail.from, // sender address headers: { 'Reply-To': replyTo } }, - send: checkifSendEmail(), - preview: !checkifSendEmail(), - transport: { - service: 'Gmail', + }; + + if (previewonly === undefined) { + paramemail.preview = !checkifSendEmail(); + paramemail.send = checkifSendEmail(); + } else { + paramemail.preview = previewonly; + paramemail.send = !previewonly; + } + + if (transport) { + paramemail.transport = transport; + } else { + paramemail.transport = { + service: 'gmail', auth: { user: process.env.EMAIL_FROM, pass: process.env.EMAIL_PW } - }, - // htmlToText: false - }); + } + } + + console.log('paramemail', paramemail); + + const email = new Email(paramemail); return email .send({ @@ -126,11 +135,12 @@ module.exports = { strlinkreg = tools.getHostByIdApp(idapp) + "/#" + process.env.LINK_REQUEST_NEWPASSWORD + `?idapp=${idapp}&username=${user}&=tokenforgot=${tokenforgot}`; return strlinkreg; }, - sendEmail_Registration: function (lang, emailto, user, idapp, idreg) { + sendEmail_Registration: async function (lang, emailto, user, idapp, idreg) { console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp)); mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), strlinkreg: this.getlinkReg(idapp, idreg), @@ -150,9 +160,10 @@ module.exports = { this.sendEmail_base('admin/registration/' + lang, tools.getManagerEmailByIdApp(idapp), mylocalsconf, ''); } }, - sendEmail_RequestNewPassword: function (lang, emailto, idapp, tokenforgot) { + sendEmail_RequestNewPassword: async function (lang, emailto, idapp, tokenforgot) { mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), user: user, @@ -163,12 +174,13 @@ module.exports = { this.sendEmail_base('resetpwd/' + lang, emailto, mylocalsconf, ''); }, - sendEmail_Booking: function (res, lang, emailto, user, idapp, recbooking) { + sendEmail_Booking: async function (res, lang, emailto, user, idapp, recbooking) { tools.mylog('sendEmail_Booking'); tools.mylog('tools.getNomeAppByIdApp(idapp)', tools.getNomeAppByIdApp(idapp), idapp); mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), name: user.name, @@ -206,11 +218,12 @@ module.exports = { }, - sendEmail_CancelBooking: function (res, lang, emailto, user, idapp, recbooking) { + sendEmail_CancelBooking: async function (res, lang, emailto, user, idapp, recbooking) { tools.mylog('sendEmail_CancelBooking'); mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), name: user.name, @@ -234,12 +247,13 @@ module.exports = { } }, - sendEmail_Msg: function (res, lang, emailto, user, idapp, recmsg) { + sendEmail_Msg: async function (res, lang, emailto, user, idapp, recmsg) { tools.mylog('sendEmail_Msg'); tools.mylog('tools.getNomeAppByIdApp(idapp)', tools.getNomeAppByIdApp(idapp), idapp); mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), name: user.name, @@ -262,35 +276,184 @@ module.exports = { // Send Email also to the Admin // this.sendEmail_base('admin/sendmsg/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf); }, - sendEmail_Notif_Added_to_Newsletter: function (lang, user, idapp) { + Add_to_MailingList_AndSendEmailNotify: async function (lang, user, idapp, sendnews) { console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp)); mylocalsconf = { + dataemail: await this.getdataemail(idapp), locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), name: user.name, surname: user.surname, emailto: user.email, + idapp }; - // Add to the database + const hash = tools.getHash(mylocalsconf.emailto); - myperson = new MailingList({ name: mylocalsconf.name, surname: mylocalsconf.surname, email: mylocalsconf.emailto }); - myperson._id = new ObjectID(); - myperson.idapp = idapp; - - // Add new record to the DB MailingList - return myperson.save().then((res) => { - - // Send to the Admin an Email - this.sendEmail_base('admin/added_to_newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, ''); - - if (tools.isManagAndAdminDifferent(idapp)) { - this.sendEmail_base('admin/added_to_newsletter/' + lang, tools.getManagerEmailByIdApp(idapp), mylocalsconf, ''); + // Check if exist to the Mailing List + let myperson = await MailingList.findByHash(idapp, hash); + if (!myperson || !myperson.statesub) { + if (!myperson) { + myperson = new MailingList({ + name: mylocalsconf.name, + surname: mylocalsconf.surname, + email: mylocalsconf.emailto, + hash + }); + myperson._id = new ObjectID(); + } else { + myperson.name = mylocalsconf.name; + myperson.surname = mylocalsconf.surname; + //myperson.email = mylocalsconf.emailto; + //myperson.hash = hash; } - }); + myperson.idapp = idapp; + myperson.statesub = true; // subscription + + // Add/save new record to the DB MailingList + const res = await myperson.save(); + + if (sendnews) { + // Send to the Admin an Email + this.sendEmail_base('admin/added_to_newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, ''); + + if (tools.isManagAndAdminDifferent(idapp)) { + this.sendEmail_base('admin/added_to_newsletter/' + lang, tools.getManagerEmailByIdApp(idapp), mylocalsconf, ''); + } + } + + return { code: server_constants.RIS_SUBSCRIBED_OK, msg: server_constants.RIS_SUBSCRIBED_MSG[lang] } + } else { + // Already Esist + return { + code: server_constants.RIS_SUBSCRIBED_ALREADYEXIST, + msg: server_constants.RIS_SUBSCRIBED_MSG_ALREADYEXIST[lang] + } + } + + }, + + Remove_from_MailingList: async function (lang, hashemail, idapp) { + + // console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp)); + + // Check if exist to the Mailing List + if (await MailingList.isUnsubscribed(idapp, hashemail)) { + return { + myperson: null, + code: server_constants.RIS_UNSUBSCRIBED_ALREADY_DONE, + msg: server_constants.RIS_UNSUBSCRIBED_MSG_ALREADY_DONE[lang] + } + } + + const fields_to_update = { + statesub: false + }; + let myperson = await MailingList.findOneAndUpdate({ + idapp, + hash: hashemail + }, { $set: fields_to_update }, { new: false }); + if (myperson) { + return { myperson, code: server_constants.RIS_UNSUBSCRIBED_OK, msg: '' } + + } else { + // Not found ! + return { + myperson: null, + code: server_constants.RIS_UNSUBSCRIBED_NOT_EXIST, + msg: server_constants.RIS_UNSUBSTR_NOT_EXIST[lang] + } + } + + }, + + fieldsloop: function (myvar) { + const baseurl = tools.getHostByIdApp(mylocalsconf.idapp); + const urlunsibscribe = baseurl + '/unsubscribe?em=' + mylocalsconf.hashemail + '&mc=' + mylocalsconf.dataemail.mailchimpactive + '&email=' + mylocalsconf.emailto; + + out = myvar.replace('{urlunsubscribe}', urlunsibscribe); + out = out.replace('{email}', mylocalsconf.emailto); + out = out.replace('{name}', mylocalsconf.name); + out = out.replace('{surname}', mylocalsconf.surname); + + return out + }, + + replacefields: function (mylocalsconf) { + + mylocalsconf.dataemail.disclaimer_out = this.fieldsloop(mylocalsconf.dataemail.disclaimer); + mylocalsconf.dataemail.disc_bottom_out = this.fieldsloop(mylocalsconf.dataemail.disc_bottom); + mylocalsconf.dataemail.templ.testoheadermail = this.fieldsloop(mylocalsconf.dataemail.templ.testoheadermail); + + }, + + getdataemail: async (idapp) => { + console.log('getdataemail'); + const mydata = { + testomail: await Settings.getValDbSettings(idapp, 'EMAIL_TEXT'), + content_after_events: await Settings.getValDbSettings(idapp, 'TEXT_AFTER_EV'), + mailchimpactive: tools.BoolToInt(await Settings.getValDbSettings(idapp, 'MAILCHIMP_ON')), + urltwitter: await Settings.getValDbSettings(idapp, 'URL_TWITTER'), + urlfb: await Settings.getValDbSettings(idapp, 'URL_FACEBOOK'), + urlyoutube: await Settings.getValDbSettings(idapp, 'URL_YOUTUBE'), + urlinstagram: await Settings.getValDbSettings(idapp, 'URL_INSTAGRAM'), + textpromo: await Settings.getValDbSettings(idapp, 'TEXT_PROMO'), + disclaimer: await Settings.getValDbSettings(idapp, 'TEXT_DISCLAIMER'), + disc_bottom: await Settings.getValDbSettings(idapp, 'TEXT_DISC_BOTTOM'), + firma: await Settings.getValDbSettings(idapp, 'TEXT_SIGN'), + + arrdiscipline: await Discipline.getDisciplineforNewsletter(idapp), + disc_title: await Settings.getValDbSettings(idapp, 'DISC_TITLE'), + height_logo: await Settings.getValDbSettings(idapp, 'HEIGHT_LOGO'), + from: await Settings.getValDbSettings(idapp, 'EMAIL_FROM'), + pwd_from: await Settings.getValDbSettings(idapp, 'PWD_FROM'), + email_service: await Settings.getValDbSettings(idapp, 'EMAIL_SERVICE_SEND'), + email_port: await Settings.getValDbSettings(idapp, 'EMAIL_PORT'), + templemail_id: await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_ID'), + }; + + console.log(mydata.templemail_id); + mydata.templ = await TemplEmail.findOne({_id: mydata.templemail_id }); + console.log(mydata.templ); + + return mydata + }, + + getTransport: () => { + // Create Transport + let smtpTransport = null; + + if (mylocalsconf.dataemail.email_service !== 'gmail') { + smtpTransport = nodemailer.createTransport({ + host: mylocalsconf.dataemail.email_service, + port: mylocalsconf.dataemail.email_port, + auth: { + user: process.env.EMAIL_FROM, + pass: process.env.EMAIL_PW + } + }); + } else if (mylocalsconf.dataemail.email_service === 'gmail') { + smtpTransport = { + service: 'gmail', //'Gmail', + auth: { + user: mylocalsconf.dataemail.from, + pass: mylocalsconf.dataemail.pwd_from + } + }; + } else { + smtpTransport = { + service: 'gmail', + auth: { + user: process.env.EMAIL_FROM, + pass: process.env.EMAIL_PW + } + }; + } + + return smtpTransport; }, sendEmail_Newsletter_Events: async function (lang, idapp, id_newstosent) { @@ -298,30 +461,54 @@ module.exports = { console.log('INIZIO - sendEmail_Newsletter_Events', tools.getNomeAppByIdApp(idapp)); //++Todo Extract List Email to send - const userstosend = await MailingList.findAllIdApp(idapp); + const userstosend = await MailingList.findAllIdAppSubscribed(idapp); const myarrevents = await MyEvent.getLastEvents(idapp); + mylocalsconf = { locale: lang, + idapp, nomeapp: tools.getNomeAppByIdApp(idapp), - arrevents: myarrevents + arrevents: myarrevents, + baseurl: tools.getHostByIdApp(idapp), + dataemail: await this.getdataemail(idapp) }; + const mynewsrec = await Newstosent.findOne({ _id: id_newstosent }); mynewsrec.numemail_tot = userstosend.length; + const smtpTransport = this.getTransport(); + + // LOOP USERS EMAIL for (const user of userstosend) { + if (process.env.DEBUG) + await tools.snooze(10000); + + activate = await Newstosent.isActivated(id_newstosent); + + if (!activate) { + // Invio Newsletter Abortito! + mynewsrec.error_job = 'Invio Newsletter abortito alle ore ' + new Date().toDateString(); + await mynewsrec.save(); + console.log('*** L\'Invio della Newsletter è stato fermato ! '); + return false + } + mylocalsconf.name = user.name; mylocalsconf.surname = user.surname; mylocalsconf.emailto = user.email; + mylocalsconf.hashemail = tools.getHash(user.email); + + await replacefields(mylocalsconf); // If has already sent, don't send it again! if (user.lastid_newstosent !== id_newstosent.toString()) { // Send Email to the User console.log('-> Invio Email (', mynewsrec.numemail_sent, '/', mynewsrec.numemail_tot, ')'); - const esito = this.sendEmail_base('newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, ''); + const esito = this.sendEmail_base('newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '', smtpTransport); //Put the result in the database, to check if is sent or not. const updateml = await MailingList.findOneAndUpdate({ @@ -330,14 +517,15 @@ module.exports = { }, { $set: { lastid_newstosent: ObjectID(id_newstosent) } }, { new: false }); + //Delay for send email... + await tools.snooze(process.env.DELAY_SENDEMAIL); + + mynewsrec.lastemailsent_Job = new Date(); mynewsrec.numemail_sent += 1; const recsaved = await mynewsrec.save(); - //Delay for send email... - await tools.snooze(process.env.DELAY_SENDEMAIL); - if (mynewsrec.numemail_sent === mynewsrec.numemail_tot) { mynewsrec.datefinishJob = new Date(); mynewsrec.finish_job = true; @@ -374,42 +562,52 @@ module.exports = { }, sendNewsletter: async function (rec) { + if (rec) { + // Start the job + myjobnews = await Newstosent.findOne({ _id: rec._id }); + if (!!myjobnews) { + myjobnews.starting_job = true; + myjobnews.datestartJob = new Date(); - // Start the job - myjobnews = await Newstosent.findOne({ _id: rec._id }); - if (!!myjobnews) { - myjobnews.starting_job = true; - myjobnews.datestartJob = new Date(); + myjobnews.save() + .then((ris) => { - myjobnews.save() - .then((ris) => { - - this.sendEmail_Newsletter_Events("it", '2', rec._id); - }) - .catch((e) => { - console.error(e); - }); + this.sendEmail_Newsletter_Events("it", '2', rec._id); + }) + .catch((e) => { + console.error(e); + }); + } } }, - testemail: async function (idapp, lang) { + testemail: async function (idapp, lang, previewonly) { const myarrevents = await MyEvent.getLastEvents(idapp); + const myemail = await Settings.getValDbSettings(idapp, 'EMAIL_TEST'); mylocalsconf = { locale: lang, nomeapp: tools.getNomeAppByIdApp(idapp), arrevents: myarrevents, - name: 'Paolo', - surname: 'Arena', - emailto: "pa.oloarena77@gmail.com", + name: 'TestNome', + surname: 'TestCognome', + emailto: myemail, + idapp, + baseurl: tools.getHostByIdApp(idapp), + hashemail: tools.getHash(myemail), }; - console.log('-> Invio Email TEST a', mylocalsconf.emailto); - return this.sendEmail_base('newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, ''); + mylocalsconf.dataemail = await this.getdataemail(idapp); + + this.replacefields(mylocalsconf); + + const smtpTransport = this.getTransport(); + + console.log('-> Invio Email TEST a', mylocalsconf.emailto, 'previewonly', previewonly); + return this.sendEmail_base('newsletter/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '', smtpTransport, previewonly); } - } ; diff --git a/src/server/server.js b/src/server/server.js index d344cf0..7304799 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -100,7 +100,7 @@ app.use('/', index_router); app.use('/subscribe', subscribe_router); app.use('/sendmsg', sendmsg_router); app.use('/push', push_router); -app.use('/signup_news', newsletter_router); +app.use('/news', newsletter_router); app.use('/booking', booking_router); app.use('/event', myevent_router); app.use('/email', email_router); @@ -155,6 +155,8 @@ if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test') if (process.env.PROD !== 1) { // testmsgwebpush(); // sendemail.testemail('2', 'it'); + + mycron(); } // ----------------- MAILCHIMP ----- @@ -226,7 +228,6 @@ function testmsgwebpush() { } }); - } // Cron every 5 minutes diff --git a/src/server/tools/general.js b/src/server/tools/general.js index 8c25179..e5bb37a 100644 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -4,6 +4,8 @@ require('../config/config'); require('../models/subscribers'); +const CryptoJS = require('crypto-js'); + var Url = require('url-parse'); const { ObjectID } = require('mongodb'); @@ -43,6 +45,7 @@ module.exports = { number: 64, typeinrec: 128, multiselect: 256, + password: 512, }, MAX_PHASES: 5, @@ -488,6 +491,33 @@ module.exports = { let mydate = new Date(new Date().getTime() + secs); // console.log('mydate', mydate); return mydate + }, + + getmd5(mystr) { + return CryptoJS.MD5(mystr.toLowerCase()).toString(); + }, + + getHash(mystr) { + return CryptoJS.SHA512(mystr, { outputLength: 256 }).toString(); + }, + + cryptdata(mydata) { + // Encrypt + return CryptoJS.AES.encrypt(JSON.stringify(data), process.env.SECRK); + }, + + decryptdata(mydatacrypted) { + // Decrypt + const bytes = CryptoJS.AES.decrypt(mydatacrypted.toString(), process.env.SECRK); + return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); + }, + + BoolToInt(mybool) { + return (mybool) ? -1 : 0 + }, + + StrToBool(mystr) { + return (mystr === '-1') ? true : false } }; diff --git a/src/server/tools/server_constants.js b/src/server/tools/server_constants.js index 3c0e90d..0c054ca 100644 --- a/src/server/tools/server_constants.js +++ b/src/server/tools/server_constants.js @@ -21,6 +21,11 @@ module.exports = Object.freeze({ RIS_SUBSCRIBED_ERR: -1, RIS_SUBSCRIBED_STR: 'subscribed', + RIS_UNSUBSCRIBED_OK: 5, + RIS_UNSUBSCRIBED_STR: 'unsubscribed', + RIS_UNSUBSCRIBED_NOT_EXIST: -5, + RIS_UNSUBSCRIBED_ALREADY_DONE: -10, + MenuAction: { DELETE: 100, }, @@ -47,6 +52,30 @@ module.exports = Object.freeze({ de: 'Abonnement des fehlgeschlagenen Newsletters', } , + RIS_UNSUBSTR_NOT_EXIST: { + enUs: 'Subscription email not found!', + es: 'Suscripción email no encontrada!', + it: 'Sottoscrizione Email non trovata!', + fr: 'Abonnement courriel introuvable!', + de: 'E-Mail-Abonnement nicht gefunden!' + } , + + RIS_UNSUB_ERROR_FAILED: { + enUs: 'Unsubscribed Failed :(', + es: 'Desuscripción al boletín fallido', + it: 'Desottoscrizione alla Newsletter Fallita', + fr: 'Désabonnement à la newsletter en échec', + de: 'Abmeldung des fehlgeschlagenen Newsletters', + } , + + RIS_UNSUBSCRIBED_MSG_ALREADY_DONE: { + enUs: 'Unsubscription already made!', + es: 'Unsuscripción ya realizada!', + it: 'Desottoscrizione già effettuata!', + fr: 'Désabonnement déjà fait!', + de: 'Abmeldung bereits gemacht!' + } , + LIST_END: '10000000', LIST_START: null,