diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 6114fe32e..ca3aabb5d 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -61,6 +61,7 @@ INSTALLED_APPS = [ 'manageServices', 'pluginHolder', 'emailPremium', + 'emailMarketing', ] MIDDLEWARE = [ diff --git a/CyberCP/urls.py b/CyberCP/urls.py index b6d2dc005..eb30b90d0 100644 --- a/CyberCP/urls.py +++ b/CyberCP/urls.py @@ -38,4 +38,5 @@ urlpatterns = [ url(r'^emailPremium/',include('emailPremium.urls')), url(r'^manageservices/',include('manageServices.urls')), url(r'^plugins/',include('pluginHolder.urls')), + url(r'^emailMarketing/', include('emailMarketing.urls')), ] diff --git a/baseTemplate/templates/baseTemplate/index.html b/baseTemplate/templates/baseTemplate/index.html index 0a5ebaa97..a46330835 100755 --- a/baseTemplate/templates/baseTemplate/index.html +++ b/baseTemplate/templates/baseTemplate/index.html @@ -624,6 +624,7 @@ + diff --git a/emailMarketing/__init__.py b/emailMarketing/__init__.py new file mode 100644 index 000000000..d33aad86a --- /dev/null +++ b/emailMarketing/__init__.py @@ -0,0 +1 @@ +default_app_config = 'emailMarketing.apps.EmailmarketingConfig' \ No newline at end of file diff --git a/emailMarketing/admin.py b/emailMarketing/admin.py new file mode 100644 index 000000000..13be29d96 --- /dev/null +++ b/emailMarketing/admin.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +# Register your models here. diff --git a/emailMarketing/apps.py b/emailMarketing/apps.py new file mode 100644 index 000000000..dafe02fc4 --- /dev/null +++ b/emailMarketing/apps.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class EmailmarketingConfig(AppConfig): + name = 'emailMarketing' + def ready(self): + import signals diff --git a/emailMarketing/emACL.py b/emailMarketing/emACL.py new file mode 100644 index 000000000..e68571c8f --- /dev/null +++ b/emailMarketing/emACL.py @@ -0,0 +1,66 @@ +from .models import EmailMarketing, EmailTemplate, SMTPHosts, EmailLists, EmailJobs +from websiteFunctions.models import Websites + +class emACL: + + @staticmethod + def checkIfEMEnabled(userName): + try: + user = EmailMarketing.objects.get(userName=userName) + return 0 + except: + return 1 + + @staticmethod + def getEmailsLists(domain): + website = Websites.objects.get(domain=domain) + emailLists = website.emaillists_set.all() + listNames = [] + + for items in emailLists: + listNames.append(items.listName) + + return listNames + + @staticmethod + def allTemplates(currentACL, admin): + if currentACL['admin'] == 1: + allTemplates = EmailTemplate.objects.all() + else: + allTemplates = admin.emailtemplate_set.all() + + templateNames = [] + for items in allTemplates: + templateNames.append(items.name) + return templateNames + + @staticmethod + def allSMTPHosts(currentACL, admin): + if currentACL['admin'] == 1: + allHosts = SMTPHosts.objects.all() + else: + allHosts = admin.smtphosts_set.all() + hostNames = [] + + for items in allHosts: + hostNames.append(items.host) + + return hostNames + + @staticmethod + def allEmailsLists(currentACL, admin): + listNames = [] + emailLists = EmailLists.objects.all() + + if currentACL['admin'] == 1: + for items in emailLists: + listNames.append(items.listName) + else: + for items in emailLists: + if items.owner.admin == admin: + listNames.append(items.listName) + + return listNames + + + diff --git a/emailMarketing/emailMarketing.py b/emailMarketing/emailMarketing.py new file mode 100644 index 000000000..ff6485d06 --- /dev/null +++ b/emailMarketing/emailMarketing.py @@ -0,0 +1,212 @@ +#!/usr/local/CyberCP/bin/python2 +from __future__ import absolute_import +import os +import time +import csv +import re +import plogical.CyberCPLogFileWriter as logging +from emailMarketing.models import EmailMarketing, EmailLists, EmailsInList, EmailTemplate, EmailJobs, SMTPHosts +from websiteFunctions.models import Websites +import threading as multi +import socket, smtplib +import DNS + +class emailMarketing(multi.Thread): + def __init__(self, function, extraArgs): + multi.Thread.__init__(self) + self.function = function + self.extraArgs = extraArgs + + def run(self): + try: + if self.function == 'createEmailList': + self.createEmailList() + elif self.function == 'verificationJob': + self.verificationJob() + elif self.function == 'startEmailJob': + self.startEmailJob() + except BaseException, msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg) + ' [emailMarketing.run]') + + def createEmailList(self): + try: + website = Websites.objects.get(domain=self.extraArgs['domain']) + try: + newList = EmailLists(owner=website, listName=self.extraArgs['listName'], dateCreated=time.strftime("%I-%M-%S-%a-%b-%Y")) + newList.save() + except: + newList = EmailLists.objects.get(listName=self.extraArgs['listName']) + + counter = 0 + + if self.extraArgs['path'].endswith('.csv'): + with open(self.extraArgs['path'], 'r') as emailsList: + data = csv.reader(emailsList, delimiter=',') + for items in data: + for value in items: + if re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', value) != None: + try: + getEmail = EmailsInList.objects.get(owner=newList, email=value) + except: + newEmail = EmailsInList(owner=newList, email=value, + verificationStatus='NOT CHECKED', + dateCreated=time.strftime("%I-%M-%S-%a-%b-%Y")) + newEmail.save() + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], str(counter) + ' emails read.') + counter = counter + 1 + elif self.extraArgs['path'].endswith('.txt'): + with open(self.extraArgs['path'], 'r') as emailsList: + emails = emailsList.readline() + while emails: + email = emails.strip('\n') + if re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email) != None: + try: + getEmail = EmailsInList.objects.get(owner=newList, email=email) + except BaseException, msg: + newEmail = EmailsInList(owner=newList, email=email, verificationStatus='NOT CHECKED', + dateCreated=time.strftime("%I-%M-%S-%a-%b-%Y")) + newEmail.save() + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],str(counter) + ' emails read.') + counter = counter + 1 + emails = emailsList.readline() + + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], str(counter) + 'Successfully read all emails. [200]') + except BaseException, msg: + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], str(msg) +'. [404]') + return 0 + + def verificationJob(self): + try: + + verificationList = EmailLists.objects.get(listName=self.extraArgs['listName']) + domain = verificationList.owner.domain + + + if not os.path.exists('/home/cyberpanel/' + domain): + os.mkdir('/home/cyberpanel/' + domain) + + tempStatusPath = '/home/cyberpanel/' + domain + "/" + self.extraArgs['listName'] + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Starting verification job..') + + counter = 1 + allEmailsInList = verificationList.emailsinlist_set.all() + + + for items in allEmailsInList: + if items.verificationStatus != 'Verified': + try: + email = items.email + domainName = email.split('@')[1] + records = DNS.dnslookup(domainName, 'MX') + + for mxRecord in records: + # Get local server hostname + host = socket.gethostname() + + server = smtplib.SMTP() + server.set_debuglevel(0) + + # SMTP Conversation + server.connect(mxRecord[1]) + server.helo(host) + server.mail('host' + "@" + host) + code, message = server.rcpt(str(email)) + server.quit() + + # Assume 250 as Success + if code == 250: + items.verificationStatus = 'Verified' + items.save() + break + else: + items.verificationStatus = 'Verification Failed' + logging.CyberCPLogFileWriter.writeToFile(email + " verification failed with error: " + message) + items.save() + + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(counter) + ' emails verified so far..') + counter = counter + 1 + except BaseException, msg: + items.verificationStatus = 'Verification Failed' + items.save() + counter = counter + 1 + logging.CyberCPLogFileWriter.writeToFile(str(msg)) + + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(counter) + ' emails successfully verified. [200]') + except BaseException, msg: + verificationList = EmailLists.objects.get(listName=self.extraArgs['listName']) + domain = verificationList.owner.domain + tempStatusPath = '/home/cyberpanel/' + domain + "/" + self.extraArgs['listName'] + logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, str(msg) +'. [404]') + return 0 + + def startEmailJob(self): + try: + try: + if self.extraArgs['host'] == 'localhost': + smtpServer = smtplib.SMTP(self.extraArgs['host']) + else: + verifyHost = SMTPHosts.objects.get(host=self.extraArgs['host']) + smtpServer = smtplib.SMTP(verifyHost.host, int(verifyHost.port)) + smtpServer.login(verifyHost.userName, verifyHost.password) + except smtplib.SMTPHeloError: + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], + 'The server didnt reply properly to the HELO greeting.') + return + except smtplib.SMTPAuthenticationError: + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], + 'Username and password combination not accepted.') + return + except smtplib.SMTPException: + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], + 'No suitable authentication method was found.') + return + + emailList = EmailLists.objects.get(listName=self.extraArgs['listName']) + allEmails = emailList.emailsinlist_set.all() + emailMessage = EmailTemplate.objects.get(name=self.extraArgs['selectedTemplate']) + + totalEmails = allEmails.count() + sent = 0 + failed = 0 + + ## Compose Message + from email.mime.multipart import MIMEMultipart + from email.mime.text import MIMEText + import re + + message = MIMEMultipart('alternative') + message['Subject'] = emailMessage.subject + message['From'] = emailMessage.fromEmail + + if re.search('', emailMessage.emailMessage, re.IGNORECASE): + html = MIMEText(emailMessage.emailMessage, 'html') + message.attach(html) + else: + html = MIMEText(emailMessage.emailMessage, 'plain') + message.attach(html) + + for items in allEmails: + if items.verificationStatus == 'Verified' or self.extraArgs['verificationCheck']: + try: + + smtpServer.sendmail(message['From'], items.email, message.as_string()) + sent = sent + 1 + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], + 'Successfully sent: ' + str(sent) + ' Failed: ' + str(failed)) + except BaseException, msg: + failed = failed + 1 + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], + 'Successfully sent: ' + str( + sent) + ', Failed: ' + str(failed)) + + + emailJob = EmailJobs(owner=emailMessage, date=time.strftime("%I-%M-%S-%a-%b-%Y"), + host=self.extraArgs['host'], totalEmails=totalEmails, + sent=sent, failed=failed + ) + emailJob.save() + + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],'Email job completed. [200]') + except BaseException, msg: + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], str(msg) +'. [404]') + return 0 \ No newline at end of file diff --git a/emailMarketing/emailMarketingManager.py b/emailMarketing/emailMarketingManager.py new file mode 100644 index 000000000..9acfb2a68 --- /dev/null +++ b/emailMarketing/emailMarketingManager.py @@ -0,0 +1,733 @@ +from django.shortcuts import render, HttpResponse, redirect +from plogical.acl import ACLManager +from loginSystem.views import loadLoginPage +import json +from random import randint +import time +from .models import EmailMarketing, EmailLists, EmailsInList, EmailJobs +from websiteFunctions.models import Websites +from emailMarketing import emailMarketing as EM +from math import ceil +import smtplib +from .models import SMTPHosts, EmailTemplate +from loginSystem.models import Administrator +from emACL import emACL + +class EmailMarketingManager: + + def __init__(self, request = None, domain = None): + self.request = request + self.domain = domain + + def emailMarketing(self): + try: + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + else: + return ACLManager.loadError() + + return render(self.request, 'emailMarketing/emailMarketing.html') + except KeyError, msg: + return redirect(loadLoginPage) + + def fetchUsers(self): + try: + + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + else: + return ACLManager.loadError() + + allUsers = ACLManager.findAllUsers() + disabledUsers = EmailMarketing.objects.all() + disabled = [] + for items in disabledUsers: + disabled.append(items.userName) + + json_data = "[" + checker = 0 + counter = 1 + + for items in allUsers: + if items in disabled: + status = 0 + else: + status = 1 + + dic = {'id': counter, 'userName': items, 'status': status} + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + counter = counter + 1 + + json_data = json_data + ']' + data_ret = {"status": 1, 'data': json_data} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def enableDisableMarketing(self): + try: + + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + else: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + userName = data['userName'] + + try: + disableMarketing = EmailMarketing.objects.get(userName=userName) + disableMarketing.delete() + except: + enableMarketing = EmailMarketing(userName=userName) + enableMarketing.save() + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def createEmailList(self): + try: + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + admin = Administrator.objects.get(pk=userID) + + if ACLManager.checkOwnership(self.domain, admin, currentACL) == 1: + pass + else: + return ACLManager.loadError() + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadError() + + return render(self.request, 'emailMarketing/createEmailList.html', {'domain': self.domain}) + except KeyError, msg: + return redirect(loadLoginPage) + + def submitEmailList(self): + try: + + data = json.loads(self.request.body) + + extraArgs = {} + extraArgs['domain'] = data['domain'] + extraArgs['path'] = data['path'] + extraArgs['listName'] = data['listName'] + extraArgs['tempStatusPath'] = "/home/cyberpanel/" + str(randint(1000, 9999)) + + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + admin = Administrator.objects.get(pk=userID) + + if ACLManager.checkOwnership(data['domain'], admin, currentACL) == 1: + pass + else: + return ACLManager.loadErrorJson() + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + em = EM('createEmailList', extraArgs) + em.start() + + time.sleep(2) + + data_ret = {"status": 1, 'tempStatusPath': extraArgs['tempStatusPath']} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def manageLists(self): + try: + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + admin = Administrator.objects.get(pk=userID) + if ACLManager.checkOwnership(self.domain, admin, currentACL) == 1: + pass + else: + return ACLManager.loadError() + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadError() + + listNames = emACL.getEmailsLists(self.domain) + + return render(self.request, 'emailMarketing/manageLists.html', {'listNames': listNames, 'domain': self.domain}) + except KeyError, msg: + return redirect(loadLoginPage) + + def fetchEmails(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + + listName = data['listName'] + recordstoShow = int(data['recordstoShow']) + page = int(data['page']) + + finalPageNumber = ((page * recordstoShow)) - recordstoShow + endPageNumber = finalPageNumber + recordstoShow + + emailList = EmailLists.objects.get(listName=listName) + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + elif emailList.owner.id != userID: + ACLManager.loadErrorJson() + + emails = emailList.emailsinlist_set.all() + + ## Pagination value + + pages = float(len(emails)) / float(recordstoShow) + pagination = [] + counter = 1 + + if pages <= 1.0: + pages = 1 + pagination.append(counter) + else: + pages = ceil(pages) + finalPages = int(pages) + 1 + + for i in range(1, finalPages): + pagination.append(counter) + counter = counter + 1 + + ## Pagination value + + emails = emails[finalPageNumber:endPageNumber] + + json_data = "[" + checker = 0 + counter = 1 + + for items in emails: + + dic = {'id': items.id, 'email': items.email, 'verificationStatus': items.verificationStatus, + 'dateCreated': items.dateCreated} + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + counter = counter + 1 + + json_data = json_data + ']' + data_ret = {"status": 1, 'data': json_data, 'pagination': pagination} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def deleteList(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + + listName = data['listName'] + + delList = EmailLists.objects.get(listName=listName) + currentACL = ACLManager.loadedACL(userID) + if currentACL['admin'] == 1: + pass + elif delList.owner.id != userID: + ACLManager.loadErrorJson() + + delList.delete() + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def emailVerificationJob(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + extraArgs = {} + extraArgs['listName'] = data['listName'] + + delList = EmailLists.objects.get(listName=extraArgs['listName']) + currentACL = ACLManager.loadedACL(userID) + if currentACL['admin'] == 1: + pass + elif delList.owner.id != userID: + ACLManager.loadErrorJson() + + em = EM('verificationJob', extraArgs) + em.start() + + time.sleep(2) + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def deleteEmail(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + + id = data['id'] + + delEmail = EmailsInList.objects.get(id=id) + + currentACL = ACLManager.loadedACL(userID) + if currentACL['admin'] == 1: + pass + elif delEmail.owner.owner.id != userID: + ACLManager.loadErrorJson() + + delEmail.delete() + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def manageSMTP(self): + try: + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + admin = Administrator.objects.get(pk=userID) + + if ACLManager.checkOwnership(self.domain, admin, currentACL) == 1: + pass + else: + return ACLManager.loadError() + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadError() + + website = Websites.objects.get(domain=self.domain) + emailLists = website.emaillists_set.all() + listNames = [] + + for items in emailLists: + listNames.append(items.listName) + return render(self.request, 'emailMarketing/manageSMTPHosts.html', {'listNames': listNames, 'domain': self.domain}) + except KeyError, msg: + return redirect(loadLoginPage) + + def saveSMTPHost(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + + data = json.loads(self.request.body) + + smtpHost = data['smtpHost'] + smtpPort = data['smtpPort'] + smtpUserName = data['smtpUserName'] + smtpPassword = data['smtpPassword'] + + if SMTPHosts.objects.count() == 0: + admin = Administrator.objects.get(pk=1) + defaultHost = SMTPHosts(owner=admin, host='localhost', port=25, userName='None', password='None') + defaultHost.save() + + try: + verifyLogin = smtplib.SMTP(smtpHost, int(smtpPort)) + verifyLogin.login(smtpUserName, smtpPassword) + + admin = Administrator.objects.get(pk=userID) + + newHost = SMTPHosts(owner=admin, host=smtpHost, port=smtpPort, userName=smtpUserName, + password=smtpPassword) + newHost.save() + + except smtplib.SMTPHeloError: + data_ret = {"status": 0, 'error_message': 'The server did not reply properly to the HELO greeting.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except smtplib.SMTPAuthenticationError: + data_ret = {"status": 0, 'error_message': 'Username and password combination not accepted.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except smtplib.SMTPException: + data_ret = {"status": 0, 'error_message': 'No suitable authentication method was found.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def fetchSMTPHosts(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + allHosts = SMTPHosts.objects.all() + else: + admin = Administrator.objects.get(pk=userID) + allHosts = admin.smtphosts_set.all() + + json_data = "[" + checker = 0 + counter = 1 + + for items in allHosts: + + dic = {'id': items.id, 'owner': items.owner.userName, 'host': items.host, 'port': items.port, + 'userName': items.userName} + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + counter = counter + 1 + + json_data = json_data + ']' + data_ret = {"status": 1, 'data': json_data} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def smtpHostOperations(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + + id = data['id'] + operation = data['operation'] + + if operation == 'delete': + delHost = SMTPHosts.objects.get(id=id) + currentACL = ACLManager.loadedACL(userID) + if currentACL['admin'] == 1: + pass + elif delHost.owner.id != userID: + ACLManager.loadErrorJson() + delHost.delete() + data_ret = {"status": 1, 'message': 'Successfully deleted.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + else: + try: + verifyHost = SMTPHosts.objects.get(id=id) + verifyLogin = smtplib.SMTP(verifyHost.host, int(verifyHost.port)) + verifyLogin.login(verifyHost.userName, verifyHost.password) + + data_ret = {"status": 1, 'message': 'Login successful.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except smtplib.SMTPHeloError: + data_ret = {"status": 0, 'error_message': 'The server did not reply properly to the HELO greeting.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except smtplib.SMTPAuthenticationError: + data_ret = {"status": 0, 'error_message': 'Username and password combination not accepted.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except smtplib.SMTPException: + data_ret = {"status": 0, 'error_message': 'No suitable authentication method was found.'} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def composeEmailMessage(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + return render(self.request, 'emailMarketing/composeMessages.html') + except KeyError, msg: + return redirect(loadLoginPage) + + def saveEmailTemplate(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + + name = data['name'] + subject = data['subject'] + fromName = data['fromName'] + fromEmail = data['fromEmail'] + replyTo = data['replyTo'] + emailMessage = data['emailMessage'] + + admin = Administrator.objects.get(pk=userID) + newTemplate = EmailTemplate(owner=admin, name=name, subject=subject, fromName=fromName, fromEmail=fromEmail, + replyTo=replyTo, emailMessage=emailMessage) + newTemplate.save() + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def sendEmails(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + currentACL = ACLManager.loadedACL(userID) + templateNames = emACL.allTemplates(currentACL, admin) + hostNames = emACL.allSMTPHosts(currentACL, admin) + listNames = emACL.allEmailsLists(currentACL, admin) + + + Data = {} + Data['templateNames'] = templateNames + Data['hostNames'] = hostNames + Data['listNames'] = listNames + return render(self.request, 'emailMarketing/sendEmails.html', Data) + except KeyError, msg: + return redirect(loadLoginPage) + + def templatePreview(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + template = EmailTemplate.objects.get(name=self.domain) + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + elif template.owner != admin: + return ACLManager.loadError() + + return HttpResponse(template.emailMessage) + except KeyError, msg: + return redirect(loadLoginPage) + + def fetchJobs(self): + try: + + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + selectedTemplate = data['selectedTemplate'] + + template = EmailTemplate.objects.get(name=selectedTemplate) + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + elif template.owner != admin: + return ACLManager.loadErrorJson() + + allJobs = EmailJobs.objects.filter(owner=template) + + json_data = "[" + checker = 0 + counter = 1 + + for items in allJobs: + + dic = {'id': items.id, + 'date': items.date, + 'host': items.host, + 'totalEmails': items.totalEmails, + 'sent': items.sent, + 'failed': items.failed} + + if checker == 0: + json_data = json_data + json.dumps(dic) + checker = 1 + else: + json_data = json_data + ',' + json.dumps(dic) + + counter = counter + 1 + + json_data = json_data + ']' + data_ret = {"status": 1, 'data': json_data} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def startEmailJob(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + data = json.loads(self.request.body) + + extraArgs = {} + extraArgs['selectedTemplate'] = data['selectedTemplate'] + extraArgs['listName'] = data['listName'] + extraArgs['host'] = data['host'] + extraArgs['verificationCheck'] = data['verificationCheck'] + extraArgs['unsubscribeCheck'] = data['unsubscribeCheck'] + extraArgs['tempStatusPath'] = "/home/cyberpanel/" + data['selectedTemplate'] + '_pendingJob' + + currentACL = ACLManager.loadedACL(userID) + template = EmailTemplate.objects.get(name=extraArgs['selectedTemplate']) + + if currentACL['admin'] == 1: + pass + elif template.owner != admin: + return ACLManager.loadErrorJson() + + em = EM('startEmailJob', extraArgs) + em.start() + + time.sleep(2) + + data_ret = {"status": 1, 'tempStatusPath': extraArgs['tempStatusPath']} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def deleteTemplate(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + data = json.loads(self.request.body) + + selectedTemplate = data['selectedTemplate'] + + delTemplate = EmailTemplate.objects.get(name=selectedTemplate) + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + elif delTemplate.owner != admin: + return ACLManager.loadErrorJson() + delTemplate.delete() + + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + def deleteJob(self): + try: + userID = self.request.session['userID'] + admin = Administrator.objects.get(pk=userID) + + if emACL.checkIfEMEnabled(admin.userName) == 0: + return ACLManager.loadErrorJson() + + data = json.loads(self.request.body) + id = data['id'] + delJob = EmailJobs(id=id) + delJob.delete() + data_ret = {"status": 1} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + except BaseException, msg: + final_dic = {'status': 0, 'error_message': str(msg)} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) \ No newline at end of file diff --git a/emailMarketing/meta.xml b/emailMarketing/meta.xml new file mode 100644 index 000000000..c2abe51a7 --- /dev/null +++ b/emailMarketing/meta.xml @@ -0,0 +1,7 @@ + + + Email Marketing + plugin + Email Marketing plugin for CyberPanel. + 1.0 + \ No newline at end of file diff --git a/emailMarketing/migrations/__init__.py b/emailMarketing/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/emailMarketing/models.py b/emailMarketing/models.py new file mode 100644 index 000000000..af2db0124 --- /dev/null +++ b/emailMarketing/models.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from websiteFunctions.models import Websites +from loginSystem.models import Administrator + +# Create your models here. + +class EmailMarketing(models.Model): + userName = models.CharField(max_length=50, unique=True) + +class EmailLists(models.Model): + owner = models.ForeignKey(Websites, on_delete=models.PROTECT) + listName = models.CharField(max_length=50, unique=True) + dateCreated = models.CharField(max_length=200) + + +class EmailsInList(models.Model): + owner = models.ForeignKey(EmailLists, on_delete=models.CASCADE) + email = models.CharField(max_length=50) + firstName = models.CharField(max_length=20, default='') + lastName = models.CharField(max_length=20, default='') + verificationStatus = models.CharField(max_length=100) + dateCreated = models.CharField(max_length=200) + +class SMTPHosts(models.Model): + owner = models.ForeignKey(Administrator, on_delete=models.CASCADE) + host = models.CharField(max_length=150, unique= True) + port = models.CharField(max_length=10) + userName = models.CharField(max_length=50) + password = models.CharField(max_length=50) + + +class EmailTemplate(models.Model): + owner = models.ForeignKey(Administrator, on_delete=models.CASCADE) + name = models.CharField(unique=True, max_length=100) + subject = models.CharField(max_length=1000) + fromName = models.CharField(max_length=100) + fromEmail = models.CharField(max_length=150) + replyTo = models.CharField(max_length=150) + emailMessage = models.CharField(max_length=30000) + +class EmailJobs(models.Model): + owner = models.ForeignKey(EmailTemplate, on_delete=models.CASCADE) + date = models.CharField(max_length=200) + host = models.CharField(max_length=1000) + totalEmails = models.IntegerField() + sent = models.IntegerField() + failed = models.IntegerField() + diff --git a/emailMarketing/signals.py b/emailMarketing/signals.py new file mode 100644 index 000000000..a492b6449 --- /dev/null +++ b/emailMarketing/signals.py @@ -0,0 +1,79 @@ +from django.dispatch import receiver +from django.shortcuts import render +from websiteFunctions.signals import preDomain +from emACL import emACL + + + +@receiver(preDomain) +def loadDomainHome(sender, **kwargs): + from websiteFunctions.models import Websites + from loginSystem.models import Administrator + from plogical.virtualHostUtilities import virtualHostUtilities + import subprocess, shlex + import plogical.CyberCPLogFileWriter as logging + from plogical.acl import ACLManager + + request = kwargs['request'] + domain = request.GET['domain'] + userID = request.session['userID'] + + if Websites.objects.filter(domain=domain).exists(): + + currentACL = ACLManager.loadedACL(userID) + website = Websites.objects.get(domain=domain) + admin = Administrator.objects.get(pk=userID) + + if ACLManager.checkOwnership(domain, admin, currentACL) == 1: + pass + else: + return ACLManager.loadError() + + marketingStatus = emACL.checkIfEMEnabled(admin.userName) + + Data = {} + + Data['ftpTotal'] = website.package.ftpAccounts + Data['ftpUsed'] = website.users_set.all().count() + + Data['databasesUsed'] = website.databases_set.all().count() + Data['databasesTotal'] = website.package.dataBases + Data['marketingStatus'] = marketingStatus + + Data['domain'] = domain + + diskUsageDetails = virtualHostUtilities.getDiskUsage("/home/" + domain, website.package.diskSpace) + + try: + execPath = "sudo python " + virtualHostUtilities.cyberPanel + "/plogical/virtualHostUtilities.py" + execPath = execPath + " findDomainBW --virtualHostName " + domain + " --bandwidth " + str( + website.package.bandwidth) + + output = subprocess.check_output(shlex.split(execPath)) + bwData = output.split(",") + except BaseException, msg: + logging.CyberCPLogFileWriter.writeToFile(str(msg)) + bwData = [0, 0] + + ## bw usage calculations + + Data['bwInMBTotal'] = website.package.bandwidth + Data['bwInMB'] = bwData[0] + Data['bwUsage'] = bwData[1] + + if diskUsageDetails != None: + if diskUsageDetails[1] > 100: + diskUsageDetails[1] = 100 + + Data['diskUsage'] = diskUsageDetails[1] + Data['diskInMB'] = diskUsageDetails[0] + Data['diskInMBTotal'] = website.package.diskSpace + else: + Data['diskUsage'] = 0 + Data['diskInMB'] = 0 + Data['diskInMBTotal'] = website.package.diskSpace + + return render(request, 'emailMarketing/website.html', Data) + else: + return render(request, 'emailMarketing/website.html', + {"error": 1, "domain": "This domain does not exists."}) \ No newline at end of file diff --git a/emailMarketing/static/emailMarketing/checklist.png b/emailMarketing/static/emailMarketing/checklist.png new file mode 100644 index 000000000..bb709fb21 Binary files /dev/null and b/emailMarketing/static/emailMarketing/checklist.png differ diff --git a/emailMarketing/static/emailMarketing/compose.png b/emailMarketing/static/emailMarketing/compose.png new file mode 100644 index 000000000..eaf70c277 Binary files /dev/null and b/emailMarketing/static/emailMarketing/compose.png differ diff --git a/emailMarketing/static/emailMarketing/emailMarketing.js b/emailMarketing/static/emailMarketing/emailMarketing.js new file mode 100644 index 000000000..2e32e0a98 --- /dev/null +++ b/emailMarketing/static/emailMarketing/emailMarketing.js @@ -0,0 +1,1323 @@ +/** + * Created by usman on 8/1/17. + */ + +var emailListURL = "/emailMarketing/"+ $("#domainNamePage").text() + "/emailLists"; +$("#emailLists").attr("href", emailListURL); +$("#emailListsChild").attr("href", emailListURL); + +var manageListsURL = "/emailMarketing/"+ $("#domainNamePage").text() + "/manageLists"; +$("#manageLists").attr("href", manageListsURL); +$("#manageListsChild").attr("href", manageListsURL); + +var sendEmailsURL = "/emailMarketing/sendEmails"; +$("#sendEmailsPage").attr("href", sendEmailsURL); +$("#sendEmailsPageChild").attr("href", sendEmailsURL); + +var composeEmailURL = "/emailMarketing/composeEmailMessage"; +$("#composeEmails").attr("href", composeEmailURL); +$("#composeEmailsChild").attr("href", composeEmailURL); + +var smtpHostsURL = "/emailMarketing/"+ $("#domainNamePage").text() + "/manageSMTP"; +$("#manageSMTPHosts").attr("href", smtpHostsURL); +$("#manageSMTPHostsChild").attr("href", smtpHostsURL); + + +app.controller('emailMarketing', function($scope,$http) { + + $scope.cyberPanelLoading = true; + $scope.fetchUsers = function(){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/fetchUsers"; + + var data = {}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.users = JSON.parse(response.data.data); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + $scope.fetchUsers(); + $scope.enableDisableMarketing = function(status, userName){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/enableDisableMarketing"; + + var data = {userName: userName}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + $scope.fetchUsers(); + + if(response.data.status === 1){ + new PNotify({ + title: 'Success!', + text: 'Changes successfully saved.', + type:'success' + }); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; +}); + +app.controller('createEmailList', function($scope, $http, $timeout) { + + $scope.installationDetailsForm = false; + $scope.installationProgress = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = true; + + var statusFile; + var path; + + + $scope.goBack = function () { + $scope.installationDetailsForm = false; + $scope.installationProgress = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = true; + $("#installProgress").css("width", "0%"); + }; + + $scope.createEmailList = function(){ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = false; + $scope.goBackDisable = true; + $scope.currentStatus = "Starting to load email addresses.."; + + + url = "/emailMarketing/submitEmailList"; + + var data = { + domain: $("#domainNamePage").text(), + path:$scope.path, + listName: $scope.listName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.status === 1) + { + statusFile = response.data.tempStatusPath; + getInstallStatus(); + } + else{ + + $scope.installationDetailsForm = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + function getInstallStatus(){ + + url = "/websites/installWordpressStatus"; + + var data = { + statusFile: statusFile, + domainName: $("#domainNamePage").text() + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + + if(response.data.abort === 1){ + + if(response.data.installStatus === 1){ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + $scope.currentStatus = 'Emails successfully loaded.'; + $timeout.cancel(); + + } + else{ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + $scope.currentStatus = response.data.error_message; + + + } + + } + else{ + $scope.installPercentage = response.data.installationProgress; + $scope.currentStatus = response.data.currentStatus; + + $timeout(getInstallStatus,1000); + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + + } + + + } + + $scope.fetchEmails = function(){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/fetchEmails"; + + var data = {'listName': $scope.listName}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.records = JSON.parse(response.data.data); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + +}); + +app.controller('manageEmailLists', function($scope, $http, $timeout) { + + $scope.installationDetailsForm = true; + $scope.installationProgress = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = true; + $scope.verificationStatus = true; + + var statusFile; + var path; + + + $scope.goBack = function () { + $scope.installationDetailsForm = false; + $scope.installationProgress = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = true; + $("#installProgress").css("width", "0%"); + }; + + $scope.createEmailList = function(){ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = false; + $scope.goBackDisable = true; + $scope.currentStatus = "Starting to load email addresses.."; + + + url = "/emailMarketing/submitEmailList"; + + var data = { + domain: $("#domainNamePage").text(), + path:$scope.path, + listName: $scope.listName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.status === 1) + { + statusFile = response.data.tempStatusPath; + getInstallStatus(); + } + else{ + + $scope.installationDetailsForm = true; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + function getInstallStatus(){ + + url = "/websites/installWordpressStatus"; + + var data = { + statusFile: statusFile, + domainName: $("#domainNamePage").text() + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + + if(response.data.abort === 1){ + + if(response.data.installStatus === 1){ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + $scope.currentStatus = 'Emails successfully loaded.'; + $timeout.cancel(); + + } + else{ + + $scope.installationDetailsForm = true; + $scope.installationProgress = false; + $scope.cyberPanelLoading = true; + $scope.goBackDisable = false; + $scope.currentStatus = response.data.error_message; + + + } + + } + else{ + $scope.installPercentage = response.data.installationProgress; + $scope.currentStatus = response.data.currentStatus; + + $timeout(getInstallStatus,1000); + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + + } + + + } + + + /// + + $scope.currentRecords = true; + + $scope.recordstoShow = 50; + var globalPage; + + $scope.fetchRecords = function () { + $scope.fetchEmails(globalPage); + }; + + $scope.fetchEmails = function(page){ + globalPage = page; + listVerificationStatus(); + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/fetchEmails"; + + var data = { + 'listName': $scope.listName, + 'recordstoShow': $scope.recordstoShow, + 'page': page + + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.currentRecords = false; + $scope.records = JSON.parse(response.data.data); + $scope.pagination = response.data.pagination; + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + $scope.deleteList = function () { + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/deleteList"; + + var data = { + listName: $scope.listName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + if (response.data.status === 1) + { + new PNotify({ + title: 'Success!', + text: 'Emails Successfully Deleted.', + type:'success' + }); + } + else{ + + $scope.cyberPanelLoading = false; + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + $scope.showAddEmails = function () { + $scope.installationDetailsForm = false; + $scope.verificationStatus = true; + }; + + // List Verification + + $scope.startVerification = function () { + + $scope.currentStatusVerification = 'Email verification job started..'; + $scope.installationDetailsForm = true; + $scope.verificationStatus = false; + $scope.verificationButton = true; + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/emailVerificationJob"; + + var data = { + listName: $scope.listName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + if (response.data.status === 1) + { + listVerificationStatus(); + $scope.verificationButton = true; + } + else{ + + $scope.cyberPanelLoading = true; + $scope.verificationButton = false; + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + $scope.verificationButton = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + + }; + + var globalCounter = 0; + + function listVerificationStatus(){ + + $scope.verificationButton = true; + $scope.cyberPanelLoading = false; + + url = "/websites/installWordpressStatus"; + + var data = { + domain: $("#domainNamePage").text(), + statusFile: "/home/cyberpanel/" + $("#domainNamePage").text() + "/" + $scope.listName + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + + if(response.data.abort === 1){ + + if(response.data.installStatus === 1){ + $scope.cyberPanelLoading = true; + $scope.verificationButton = false; + $scope.currentStatusVerification = 'Emails successfully verified.'; + $timeout.cancel(); + + } + else{ + + if(response.data.error_message.search('No such file') > -1){ + $scope.verificationButton = false; + return; + } + $scope.verificationButton = true; + $scope.cyberPanelLoading = false; + $scope.verificationStatus = false; + $scope.currentStatusVerification = response.data.error_message; + + } + + } + else{ + $scope.currentStatusVerification = response.data.currentStatus; + $timeout(listVerificationStatus,1000); + $scope.verificationStatus = false; + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + + } + + + } + + // Delete Email from list + + $scope.deleteEmail = function(id){ + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/deleteEmail"; + + var data = { + id: id + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + $scope.fetchEmails(globalPage); + + if (response.data.status === 1) + { + $scope.fetchEmails(globalPage); + new PNotify({ + title: 'Success.', + text: 'Email Successfully deleted.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + +}); + +app.controller('manageSMTPHostsCTRL', function($scope, $http) { + + $scope.cyberPanelLoading = true; + $scope.fetchSMTPHosts = function(){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/fetchSMTPHosts"; + + var data = {}; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.records = JSON.parse(response.data.data); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + $scope.fetchSMTPHosts(); + $scope.saveSMTPHost = function(status, userName){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/saveSMTPHost"; + + var data = { + smtpHost: $scope.smtpHost, + smtpPort: $scope.smtpPort, + smtpUserName: $scope.smtpUserName, + smtpPassword: $scope.smtpPassword + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.fetchSMTPHosts(); + new PNotify({ + title: 'Success!', + text: 'Successfully saved new SMTP host.', + type:'success' + }); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + $scope.smtpHostOperations = function(operation, id){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/smtpHostOperations"; + + var data = { + id: id, + operation: operation + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + $scope.fetchSMTPHosts(); + + if(response.data.status === 1){ + new PNotify({ + title: 'Success!', + text: response.data.message, + type:'success' + }); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; +}); + +app.controller('composeMessageCTRL', function($scope, $http) { + + $scope.cyberPanelLoading = true; + $scope.saveTemplate = function(status, userName){ + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/saveEmailTemplate"; + + var data = { + name: $scope.name, + subject: $scope.subject, + fromName: $scope.fromName, + fromEmail: $scope.fromEmail, + replyTo: $scope.replyTo, + emailMessage: $scope.emailMessage + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + new PNotify({ + title: 'Success!', + text: 'Template successfully saved.', + type:'success' + }); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; +}); + +app.controller('sendEmailsCTRL', function($scope, $http, $timeout) { + + $scope.cyberPanelLoading = true; + $scope.availableFunctions = true; + $scope.sendEmailsView = true; + $scope.jobStatus = true; + + // Button + + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + + $scope.templateSelected = function () { + $scope.availableFunctions = false; + $scope.sendEmailsView = true; + $scope.previewLink = '/emailMarketing/preview/' + $scope.selectedTemplate; + $scope.jobStatus = true; + emailJobStatus(); + + }; + + $scope.sendEmails = function () { + $scope.sendEmailsView = false; + $scope.fetchJobs(); + }; + + $scope.fetchJobs = function(){ + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/fetchJobs"; + + var data = { + 'selectedTemplate': $scope.selectedTemplate + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + $scope.currentRecords = false; + $scope.records = JSON.parse(response.data.data); + } + else{ + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + + $scope.startEmailJob = function () { + $scope.cyberPanelLoading = false; + $scope.deleteTemplateBTN = true; + $scope.sendEmailBTN = true; + $scope.sendEmailsView = true; + $scope.goBackDisable = true; + + url = "/emailMarketing/startEmailJob"; + + + var data = { + 'selectedTemplate': $scope.selectedTemplate, + 'listName': $scope.listName, + 'host': $scope.host, + 'verificationCheck': $scope.verificationCheck, + 'unsubscribeCheck': $scope.unsubscribeCheck + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if(response.data.status === 1){ + emailJobStatus(); + } + else{ + $scope.cyberPanelLoading = true; + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + $scope.sendEmailsView = false; + $scope.jobStatus = true; + $scope.goBackDisable = false; + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + } + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = false; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + + }; + + function emailJobStatus(){ + + $scope.cyberPanelLoading = false; + $scope.deleteTemplateBTN = true; + $scope.sendEmailBTN = true; + $scope.sendEmailsView = true; + $scope.jobStatus = false; + $scope.goBackDisable = true; + + url = "/websites/installWordpressStatus"; + + var data = { + domain: 'example.com', + statusFile: "/home/cyberpanel/" + $scope.selectedTemplate + "_pendingJob" + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + + + if(response.data.abort === 1){ + + if(response.data.installStatus === 1){ + $scope.cyberPanelLoading = true; + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + $scope.sendEmailsView = true; + $scope.jobStatus = false; + $scope.goBackDisable = false; + $scope.currentStatus = 'Emails successfully sent.'; + $scope.fetchJobs(); + $timeout.cancel(); + + } + else{ + + if(response.data.error_message.search('No such file') > -1){ + $scope.cyberPanelLoading = true; + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + $scope.sendEmailsView = true; + $scope.jobStatus = true; + $scope.goBackDisable = false; + return; + } + $scope.cyberPanelLoading = true; + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + $scope.sendEmailsView = true; + $scope.jobStatus = false; + $scope.goBackDisable = false; + $scope.currentStatus = response.data.error_message; + + } + + } + else{ + $scope.currentStatus = response.data.currentStatus; + $timeout(emailJobStatus,1000); + $scope.cyberPanelLoading = false; + $scope.deleteTemplateBTN = true; + $scope.sendEmailBTN = true; + $scope.sendEmailsView = true; + $scope.jobStatus = false; + $scope.goBackDisable = true; + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page.', + type:'error' + }); + + + } + + + } + + $scope.goBack = function () { + $scope.cyberPanelLoading = true; + $scope.deleteTemplateBTN = false; + $scope.sendEmailBTN = false; + $scope.sendEmailsView = false; + $scope.jobStatus = true; + + }; + + $scope.deleteTemplate = function(){ + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/deleteTemplate"; + + var data = { + selectedTemplate: $scope.selectedTemplate + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + + if (response.data.status === 1) + { + new PNotify({ + title: 'Success.', + text: 'Template Successfully deleted.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; + $scope.deleteJob = function(id){ + + $scope.cyberPanelLoading = false; + + url = "/emailMarketing/deleteJob"; + + var data = { + id: id + }; + + var config = { + headers : { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data,config).then(ListInitialDatas, cantLoadInitialDatas); + + + function ListInitialDatas(response) { + $scope.cyberPanelLoading = true; + $scope.fetchJobs(); + + if (response.data.status === 1) + { + new PNotify({ + title: 'Success.', + text: 'Template Successfully deleted.', + type:'success' + }); + + } + else{ + + new PNotify({ + title: 'Operation Failed!', + text: response.data.error_message, + type:'error' + }); + + } + + } + function cantLoadInitialDatas(response) { + $scope.cyberPanelLoading = true; + new PNotify({ + title: 'Operation Failed!', + text: 'Could not connect to server, please refresh this page', + type:'error' + }); + + } + + }; +}); + + diff --git a/emailMarketing/static/emailMarketing/mailing.png b/emailMarketing/static/emailMarketing/mailing.png new file mode 100644 index 000000000..b8586aea2 Binary files /dev/null and b/emailMarketing/static/emailMarketing/mailing.png differ diff --git a/emailMarketing/static/emailMarketing/paper-plane.png b/emailMarketing/static/emailMarketing/paper-plane.png new file mode 100644 index 000000000..8135fdfb1 Binary files /dev/null and b/emailMarketing/static/emailMarketing/paper-plane.png differ diff --git a/emailMarketing/static/emailMarketing/post-office.png b/emailMarketing/static/emailMarketing/post-office.png new file mode 100644 index 000000000..6cdfb54cc Binary files /dev/null and b/emailMarketing/static/emailMarketing/post-office.png differ diff --git a/emailMarketing/templates/emailMarketing/composeMessages.html b/emailMarketing/templates/emailMarketing/composeMessages.html new file mode 100644 index 000000000..4c4ec015d --- /dev/null +++ b/emailMarketing/templates/emailMarketing/composeMessages.html @@ -0,0 +1,90 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Compose Email Message - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Compose Email Message" %}

+

{% trans "On this page you can compose email message to be sent out later." %}

+
+
+
+

+ {% trans "Compose Email Message" %} +

+
+ + +
+ + + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ +
+ +
+ +
+
+ + + +
+ + + + +
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/templates/emailMarketing/createEmailList.html b/emailMarketing/templates/emailMarketing/createEmailList.html new file mode 100644 index 000000000..863afa4fe --- /dev/null +++ b/emailMarketing/templates/emailMarketing/createEmailList.html @@ -0,0 +1,75 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Create Email List - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Create Email List" %} - {{ domain }}

+

{% trans "Create email list, to send out news letters and marketing emails." %}

+
+
+
+

+ {% trans "Create Email List" %} +

+
+ + +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+
+

{$ currentStatus $}

+
+
+
+ +
+ +
+ +
+
+ +
+ + + + +
+
+
+ + +
+{% endblock %} + diff --git a/emailMarketing/templates/emailMarketing/emailMarketing.html b/emailMarketing/templates/emailMarketing/emailMarketing.html new file mode 100644 index 000000000..0e5d9a677 --- /dev/null +++ b/emailMarketing/templates/emailMarketing/emailMarketing.html @@ -0,0 +1,72 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Email Marketing - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+ +
+

{% trans "Email Marketing" %}

+

{% trans "Select users to Enable/Disable Email Marketing feature!" %}

+
+ +
+
+ +

+ {% trans "Email Marketing" %} +

+ + {% if installCheck == 0 %} + +
+
+

{% trans "Email Policy Server is not enabled " %} + +

+
+
+ {% else %} +
+ + + + + + + + + + + + + + + + + + +
{% trans 'ID' %}{% trans 'Username' %}{% trans 'Status' %}
+ + + + +
+ +
+ + {% endif %} +
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/templates/emailMarketing/manageLists.html b/emailMarketing/templates/emailMarketing/manageLists.html new file mode 100644 index 000000000..378649f87 --- /dev/null +++ b/emailMarketing/templates/emailMarketing/manageLists.html @@ -0,0 +1,190 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Manage Email Lists - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Manage Email Lists" %} - {{ domain }}

+

{% trans "On this page you can manage your email lists (Delete, Verify, Add More Emails)." %}

+
+
+
+

+ {% trans "Manage Email Lists" %} +

+
+ + +
+ + +
+ +
+ +
+
+ +
+ +
+ + + + +
+
+ +
+
+ +
+
+ + + + +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+
+

{$ currentStatus $}

+
+
+
+ +
+ +
+ +
+
+ + + + + +
+ +
+
+

{$ currentStatusVerification $}

+
+
+
+ + + + + + +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
{% trans "ID" %}{% trans "email" %}{% trans "Verification Status" %}{% trans "Date Created" %}{% trans "Actions" %}
+ +
+ +
+
+ + +
+
+
+
+ + + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/templates/emailMarketing/manageSMTPHosts.html b/emailMarketing/templates/emailMarketing/manageSMTPHosts.html new file mode 100644 index 000000000..c90d4ae04 --- /dev/null +++ b/emailMarketing/templates/emailMarketing/manageSMTPHosts.html @@ -0,0 +1,126 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Manage SMTP Hosts - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Manage SMTP Hosts" %}

+

{% trans "On this page you can manage STMP Host. (SMTP hosts are used to send emails)" %}

+
+
+
+

+ {% trans "Manage SMTP Hosts" %} +

+
+ + +
+ + + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
{% trans "ID" %}{% trans "Owner" %}{% trans "Host" %}{% trans "Port" %}{% trans "Username" %}{% trans "Actions" %}
+ + +
+ +
+
+ + +
+
+
+
+ + + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/templates/emailMarketing/sendEmails.html b/emailMarketing/templates/emailMarketing/sendEmails.html new file mode 100644 index 000000000..67d19cfff --- /dev/null +++ b/emailMarketing/templates/emailMarketing/sendEmails.html @@ -0,0 +1,204 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{% trans "Send Emails - CyberPanel" %}{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + + +
+
+

{% trans "Send Emails" %}

+

{% trans "On this page you can send emails to the lists you created using SMTP Hosts." %}

+
+
+
+

+ {% trans "Send Emails" %} +

+
+ + +
+ + +
+ +
+ +
+
+ +
+ +
+ + + + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+ + +
+
+ + + +
+ +
+
+

{$ currentStatus $}

+
+
+
+ +
+ +
+ +
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans "Job ID" %}{% trans "Date" %}{% trans "SMTP Host" %}{% trans "Total Emails" %}{% trans "Sent" %}{% trans "Failed" %}{% trans "Actions" %}
+ +
+ +
+
+ + +
+
+
+
+ + + +
+ + + + +
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/templates/emailMarketing/website.html b/emailMarketing/templates/emailMarketing/website.html new file mode 100644 index 000000000..46e2938b2 --- /dev/null +++ b/emailMarketing/templates/emailMarketing/website.html @@ -0,0 +1,1097 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}{{ domain }} - CyberPanel{% endblock %} +{% block content %} + +{% load static %} +{% get_current_language as LANGUAGE_CODE %} + + +
+ +
+

{{ domain }} - {% trans "Preview" %}

+

{% trans "All functions related to a particular site." %}

+
+ + {% if not error %} + + +
+ +
+ +

+ {% trans "Resource Usage" %} +

+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans "Resource" %}{% trans "Usage" %}{% trans "Allowed" %}
{% trans "FTP" %}{{ ftpUsed }}{{ ftpTotal }}
{% trans "Databases" %}{{ databasesUsed }}{{ databasesTotal }}
{% trans "Disk Usage" %}{{ diskInMB }} (MB){{ diskInMBTotal }} (MB)
{% trans "Bandwidth Usage" %}{{ bwInMB }} (MB){{ bwInMBTotal }} (MB)
+
+ +
+
+
+
+

+ {% trans "Disk Usage" %} +

+
+
+
+
{{ diskUsage }}%
+
+
+ + +

+ {% trans "Bandwidth Usage" %} +

+
+
+
+
{{ bwUsage }}%
+
+
+ + + +
+ +
+
+
+ +
+
+ + +
+
+ + +
+ +
+

+ {% trans "Logs" %} +

+ +
+
+ + + + + + + +
+ +
+ +
+

{% trans "Logs Fetched" %}

+
+ + +
+

{% trans "Could not fetch logs, see the logs file through command line. Error message:" %} {$ errorMessage $}

+
+ + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + + +
+ +
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
DomainIP AddressTimeResourceSize
+
+
+ + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+
+
+ + +
+
+ +

+ {% trans "Domains" %} +

+ +
+ +
+ + + + + + + + + + + + + + + +
+
+ + +
+ +
+ +
+
+ +
+
+ +
+ +
+ +
+
{% trans "Invalid Domain (Note: You don't need to add 'http' or 'https')" %}
+
+ + +
+ +
+ +
+
+ + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + +
+ +
+ + +
+
+ + + +
+ +
+ +
+

{$ currentStatus $}

+
+ +
+
+ 70% Complete +
+
+ +
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Website succesfully created." %}

+
+ + + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + +
+
+ +
+ +
+ +
+
+ + +
+
+ + + + + +
+ +
+ + + +
+

{% trans "PHP Version Changed to:" %} {$ changedPHPVersion $}

+
+ +
+

{% trans "Deleted:" %} {$ deletedDomain $}

+
+ +
+

{% trans "SSL Issued:" %} {$ sslDomainIssued $}

+
+ +
+

{% trans "Changes applied successfully." %}

+
+ + +
+

{$ errorMessage $}

+
+ + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + + + +
+ +
+ +
+ +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + +
DomainLaunchPathopen_basedirPHPSSLDelete
+ + + +
+
+
+ + +
+ +
+ + +
+ +
+
+
+ + +
+ +
+

+ {% trans "Configurations" %} +

+ + +
+
+ + + + + + + + + + + + + + +
+ +
+ +
+

{% trans "SSL Saved" %}

+
+ + +
+

{% trans "Could not save SSL. Error message:" %} {$ errorMessage $}

+
+ + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + +
+ + + + + +
+ + + + + + + +
+ +
+ +
+

{% trans "Current configuration in the file fetched." %}

+
+ + +
+

{% trans "Could not fetch current configuration. Error message:" %} {$ errorMessage $}

+
+ + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ +
+

{% trans "Configurations saved." %}

+
+ +
+

{% trans "Could not fetch current configuration. Error message:" %} {$ errorMessage $}

+
+ + +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + +
+ +
+ + + +
+ +
+ + +
+

{% trans "Current rewrite rules in the file fetched." %} Click to read more about whats changed in rewrite rules from v1.7 onwards.

+
+ + +
+

{% trans "Could not fetch current rewrite rules. Error message:" %} {$ errorMessage $}

+
+ + +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+ +
+

{% trans "Configurations saved." %}

+
+ +
+

{% trans "Could not save rewrite rules. Error message:" %} {$ errorMessage $}

+
+ + +
+
+ +
+
+ +
+
+ +
+ +
+ + +
+
+ + +
+ +
+ + + +
+ +
+ + + +
+ +
+ +
+ +
+ +
+ +
+ + + + +
+ +
+ +
+
+ + + +
+ + +
+
+

{% trans "Failed to change PHP version. Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "PHP successfully changed for: " %} {$ websiteDomain $}

+
+ +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+
+ + + +
+ + +
+
+ +
+
+
+
+ + +
+
+

+ {% trans "Files" %} +

+ +
+
+ + + + + + + + + + + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+
+
+ + +
+
+

{% trans "Error message:" %} {$ errorMessage $}

+
+ +
+

{% trans "Changes successfully saved." %}

+
+ +
+

{% trans "Could not connect to server. Please refresh this page." %}

+
+
+ +
+ + +
+
+ + + + + +
+
+
+
+ + {% if marketingStatus %} + + + + {% endif %} + +
+ +
+

+ {% trans "Application Installer" %} +

+ + + +
+
+ + {% else %} + +
+

{{ domain }}

+
+ + + {% endif %} + + + + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/emailMarketing/tests.py b/emailMarketing/tests.py new file mode 100644 index 000000000..5982e6bcd --- /dev/null +++ b/emailMarketing/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/emailMarketing/urls.py b/emailMarketing/urls.py new file mode 100644 index 000000000..b8bf67151 --- /dev/null +++ b/emailMarketing/urls.py @@ -0,0 +1,26 @@ +from django.conf.urls import url +import views +urlpatterns = [ + url(r'^$', views.emailMarketing, name='emailMarketing'), + url(r'^fetchUsers$', views.fetchUsers, name='fetchUsers'), + url(r'^enableDisableMarketing$', views.enableDisableMarketing, name='enableDisableMarketing'), + url(r'^(?P([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?)/emailLists$', views.createEmailList, name='createEmailList'), + url(r'^submitEmailList$', views.submitEmailList, name='submitEmailList'), + url(r'^(?P([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?)/manageLists$', views.manageLists, name='manageLists'), + url(r'^(?P([\da-z\.-]+\.[a-z\.]{2,12}|[\d\.]+)([\/:?=&#]{1}[\da-z\.-]+)*[\/\?]?)/manageSMTP$', views.manageSMTP, name='manageSMTP'), + url(r'^fetchEmails$', views.fetchEmails, name='fetchEmails'), + url(r'^deleteList$', views.deleteList, name='deleteList'), + url(r'^emailVerificationJob$', views.emailVerificationJob, name='emailVerificationJob'), + url(r'^deleteEmail$', views.deleteEmail, name='deleteEmail'), + url(r'^saveSMTPHost$', views.saveSMTPHost, name='saveSMTPHost'), + url(r'^fetchSMTPHosts$', views.fetchSMTPHosts, name='fetchSMTPHosts'), + url(r'^smtpHostOperations$', views.smtpHostOperations, name='smtpHostOperations'), + url(r'^composeEmailMessage$', views.composeEmailMessage, name='composeEmailMessage'), + url(r'^saveEmailTemplate$', views.saveEmailTemplate, name='saveEmailTemplate'), + url(r'^sendEmails$', views.sendEmails, name='sendEmails'), + url(r'^preview/(?P[-\w]+)/$', views.templatePreview, name='templatePreview'), + url(r'^fetchJobs$', views.fetchJobs, name='fetchJobs'), + url(r'^startEmailJob$', views.startEmailJob, name='startEmailJob'), + url(r'^deleteTemplate$', views.deleteTemplate, name='deleteTemplate'), + url(r'^deleteJob$', views.deleteJob, name='deleteJob'), +] \ No newline at end of file diff --git a/emailMarketing/views.py b/emailMarketing/views.py new file mode 100644 index 000000000..a5ba2efc4 --- /dev/null +++ b/emailMarketing/views.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.shortcuts import redirect +from loginSystem.views import loadLoginPage +from emailMarketingManager import EmailMarketingManager +# Create your views here. + + +def emailMarketing(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.emailMarketing() + except KeyError: + return redirect(loadLoginPage) + +def fetchUsers(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.fetchUsers() + except KeyError: + return redirect(loadLoginPage) + +def enableDisableMarketing(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.enableDisableMarketing() + except KeyError: + return redirect(loadLoginPage) + +def createEmailList(request, domain): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request, domain) + return emm.createEmailList() + except KeyError: + return redirect(loadLoginPage) + +def submitEmailList(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.submitEmailList() + except KeyError: + return redirect(loadLoginPage) + +def manageLists(request, domain): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request, domain) + return emm.manageLists() + except KeyError: + return redirect(loadLoginPage) + +def fetchEmails(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.fetchEmails() + except KeyError: + return redirect(loadLoginPage) + +def deleteList(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.deleteList() + except KeyError: + return redirect(loadLoginPage) + +def emailVerificationJob(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.emailVerificationJob() + except KeyError: + return redirect(loadLoginPage) + +def deleteEmail(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.deleteEmail() + except KeyError: + return redirect(loadLoginPage) + +def manageSMTP(request, domain): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request, domain) + return emm.manageSMTP() + except KeyError: + return redirect(loadLoginPage) + +def saveSMTPHost(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.saveSMTPHost() + except KeyError: + return redirect(loadLoginPage) + +def fetchSMTPHosts(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.fetchSMTPHosts() + except KeyError: + return redirect(loadLoginPage) + +def smtpHostOperations(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.smtpHostOperations() + except KeyError: + return redirect(loadLoginPage) + +def composeEmailMessage(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.composeEmailMessage() + except KeyError: + return redirect(loadLoginPage) + +def saveEmailTemplate(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.saveEmailTemplate() + except KeyError: + return redirect(loadLoginPage) + +def sendEmails(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.sendEmails() + except KeyError: + return redirect(loadLoginPage) + +def templatePreview(request, templateName): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request, templateName) + return emm.templatePreview() + except KeyError: + return redirect(loadLoginPage) + +def fetchJobs(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.fetchJobs() + except KeyError: + return redirect(loadLoginPage) + +def startEmailJob(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.startEmailJob() + except KeyError: + return redirect(loadLoginPage) + +def deleteTemplate(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.deleteTemplate() + except KeyError: + return redirect(loadLoginPage) + +def deleteJob(request): + try: + userID = request.session['userID'] + emm = EmailMarketingManager(request) + return emm.deleteJob() + except KeyError: + return redirect(loadLoginPage) \ No newline at end of file diff --git a/install/install.py b/install/install.py index 19f13377c..46fa22abb 100644 --- a/install/install.py +++ b/install/install.py @@ -687,8 +687,8 @@ class preFlightsChecks: count = 0 while (1): - command = "wget http://cyberpanel.net/CyberPanel.1.7.2.tar.gz" - #command = "wget http://cyberpanel.net/CyberPanelTemp.tar.gz" + #command = "wget http://cyberpanel.net/CyberPanel.1.7.2.tar.gz" + command = "wget http://cyberpanel.net/CyberPanelTemp.tar.gz" res = subprocess.call(shlex.split(command)) if res == 1: @@ -707,8 +707,8 @@ class preFlightsChecks: count = 0 while(1): - command = "tar zxf CyberPanel.1.7.2.tar.gz" - #command = "tar zxf CyberPanelTemp.tar.gz" + #command = "tar zxf CyberPanel.1.7.2.tar.gz" + command = "tar zxf CyberPanelTemp.tar.gz" res = subprocess.call(shlex.split(command)) @@ -2582,6 +2582,29 @@ class preFlightsChecks: logging.InstallLog.writeToFile(str(msg) + " [installTLDExtract]") return 0 + def installPYDNS(self): + try: + count = 0 + while (1): + command = "pip install pydns" + + res = subprocess.call(shlex.split(command)) + + if res == 1: + count = count + 1 + preFlightsChecks.stdOut( + "Trying to install pydns, trying again, try number: " + str(count)) + if count == 3: + logging.InstallLog.writeToFile( + "Failed to install pydns! [installTLDExtract]") + else: + logging.InstallLog.writeToFile("pydns successfully installed! [pip]") + preFlightsChecks.stdOut("pydns successfully installed! [pip]") + break + except OSError, msg: + logging.InstallLog.writeToFile(str(msg) + " [installTLDExtract]") + return 0 + def installOpenDKIM(self): try: count = 0 @@ -3003,6 +3026,7 @@ def main(): checks.installCertBot() checks.test_Requests() + checks.installPYDNS() checks.download_install_CyberPanel(installCyberPanel.InstallCyberPanel.mysqlPassword, mysql) checks.setupCLI() checks.setup_cron() diff --git a/plogical/website.py b/plogical/website.py index 198ce662e..1eabfef17 100644 --- a/plogical/website.py +++ b/plogical/website.py @@ -1495,6 +1495,8 @@ class WebsiteManager: lastLine = statusData[-1] if lastLine.find('[200]') > -1: + command = 'sudo rm -f ' + statusFile + subprocess.call(shlex.split(command)) data_ret = {'abort': 1, 'installStatus': 1, 'installationProgress': "100", 'currentStatus': 'Successfully Installed.'} json_data = json.dumps(data_ret) @@ -1507,7 +1509,10 @@ class WebsiteManager: else: progress = lastLine.split(',') currentStatus = progress[0] - installationProgress = progress[1] + try: + installationProgress = progress[1] + except: + installationProgress = 0 data_ret = {'abort': 0, 'installStatus': 0, 'installationProgress': installationProgress, 'currentStatus': currentStatus} json_data = json.dumps(data_ret) diff --git a/requirments.txt b/requirments.txt index cacd75630..cb196634f 100644 --- a/requirments.txt +++ b/requirments.txt @@ -35,6 +35,7 @@ psutil==5.4.3 ptyprocess==0.6.0 pycparser==2.18 pycurl==7.19.0 +pydns==2.3.6 pygpgme==0.3 pyliblzma==0.5.3 pyOpenSSL==17.5.0 diff --git a/websiteFunctions/pluginManager.py b/websiteFunctions/pluginManager.py index 757114926..1659ac516 100644 --- a/websiteFunctions/pluginManager.py +++ b/websiteFunctions/pluginManager.py @@ -51,6 +51,14 @@ class pluginManager: def postWebsiteModification(request, response): return pluginManagerGlobal.globalPlug(request, postWebsiteModification, response) + @staticmethod + def preDomain(request): + return pluginManagerGlobal.globalPlug(request, preDomain) + + @staticmethod + def postDomain(request, response): + return pluginManagerGlobal.globalPlug(request, postDomain, response) + @staticmethod def preSaveConfigsToFile(request): return pluginManagerGlobal.globalPlug(request, preSaveConfigsToFile) diff --git a/websiteFunctions/signals.py b/websiteFunctions/signals.py index edae8427b..3876b7461 100644 --- a/websiteFunctions/signals.py +++ b/websiteFunctions/signals.py @@ -39,6 +39,13 @@ preWebsiteModification = Signal(providing_args=["request"]) ## This event is fired after CyberPanel core finished suspension of website postWebsiteModification = Signal(providing_args=["request", "response"]) + +## This event is fired before CyberPanel core load website launcher +preDomain = Signal(providing_args=["request"]) + +## This event is fired after CyberPanel core finished loading website launcher +postDomain = Signal(providing_args=["request", "response"]) + ## This event is fired before CyberPanel core start saving changes to vhost conf preSaveConfigsToFile = Signal(providing_args=["request"]) diff --git a/websiteFunctions/views.py b/websiteFunctions/views.py index 7d91ac470..265e0d7cd 100644 --- a/websiteFunctions/views.py +++ b/websiteFunctions/views.py @@ -211,9 +211,23 @@ def saveWebsiteChanges(request): def domain(request, domain): try: + if not request.GET._mutable: + request.GET._mutable = True + request.GET['domain'] = domain + + result = pluginManager.preDomain(request) + if result != 200: + return result + userID = request.session['userID'] wm = WebsiteManager(domain) - return wm.loadDomainHome(request, userID) + coreResult = wm.loadDomainHome(request, userID) + + result = pluginManager.postDomain(request, coreResult) + if result != 200: + return result + + return coreResult except KeyError: return redirect(loadLoginPage)