2025-08-01 14:56:30 +05:00
import json
import os , sys
import time
from django . http import HttpResponse
sys . path . append ( ' /usr/local/CyberCP ' )
import django
os . environ . setdefault ( " DJANGO_SETTINGS_MODULE " , " CyberCP.settings " )
try :
django . setup ( )
except :
pass
import os . path
import shutil
from plogical import CyberCPLogFileWriter as logging
import subprocess
import argparse
import shlex
from plogical . processUtilities import ProcessUtilities
import os
import bcrypt
import getpass
import smtplib
import threading as multi
try :
from mailServer . models import Domains , EUsers
from emailPremium . models import DomainLimits , EmailLimits
from websiteFunctions . models import Websites , ChildDomains
except :
pass
class mailUtilities :
installLogPath = " /home/cyberpanel/openDKIMInstallLog "
spamassassinInstallLogPath = " /home/cyberpanel/spamassassinInstallLogPath "
RspamdInstallLogPath = " /home/cyberpanel/RspamdInstallLogPath "
RspamdUnInstallLogPath = " /home/cyberpanel/RspamdUnInstallLogPath "
cyberPanelHome = " /home/cyberpanel "
mailScannerInstallLogPath = " /home/cyberpanel/mailScannerInstallLogPath "
RSpamdLogPath = ' /var/log/rspamd/rspamd.log '
@staticmethod
def SendEmail ( sender , receivers , message ) :
try :
smtpObj = smtplib . SMTP ( ' localhost ' )
smtpObj . sendmail ( sender , receivers , message )
print ( " Successfully sent email " )
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) )
2025-11-02 20:29:45 +01:00
@staticmethod
def isPostfixInstalled ( ) :
"""
Check if Postfix is actually installed and available
Returns True if postfix is installed , False otherwise
"""
try :
# Check if postfix binary exists
if not ( os . path . exists ( ' /usr/sbin/postfix ' ) or
os . path . exists ( ' /usr/bin/postfix ' ) ) :
return False
# Check if postfix main.cf exists
if not os . path . exists ( ' /etc/postfix/main.cf ' ) :
return False
# Check if postfix service is available
command = ' systemctl list-unit-files postfix.service '
result = ProcessUtilities . outputExecutioner ( command )
return ' postfix.service ' in result
except :
return False
2025-08-01 14:56:30 +05:00
@staticmethod
def AfterEffects ( domain ) :
path = " /usr/local/CyberCP/install/rainloop/cyberpanel.net.ini "
if not os . path . exists ( " /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/ " ) :
os . makedirs ( " /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/ " )
finalPath = " /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/ " + domain + " .ini "
finalPathJson = " /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/ " + domain + " .json "
if not os . path . exists ( finalPath ) :
shutil . copy ( path , finalPath )
contentJSON = """
{
" name " : " %s " ,
" IMAP " : {
" host " : " localhost " ,
" port " : 993 ,
" type " : 1 ,
" timeout " : 300 ,
" shortLogin " : false ,
" sasl " : [
" SCRAM-SHA3-512 " ,
" SCRAM-SHA-512 " ,
" SCRAM-SHA-256 " ,
" SCRAM-SHA-1 " ,
" PLAIN " ,
" LOGIN "
] ,
" ssl " : {
" verify_peer " : false ,
" verify_peer_name " : false ,
" allow_self_signed " : false ,
" SNI_enabled " : true ,
" disable_compression " : true ,
" security_level " : 1
} ,
" use_expunge_all_on_delete " : false ,
" fast_simple_search " : true ,
" force_select " : false ,
" message_all_headers " : false ,
" message_list_limit " : 10000 ,
" search_filter " : " " ,
" disabled_capabilities " : [ ]
} ,
" SMTP " : {
" host " : " localhost " ,
" port " : 587 ,
" type " : 2 ,
" timeout " : 60 ,
" shortLogin " : false ,
" sasl " : [
" SCRAM-SHA3-512 " ,
" SCRAM-SHA-512 " ,
" SCRAM-SHA-256 " ,
" SCRAM-SHA-1 " ,
" PLAIN " ,
" LOGIN "
] ,
" ssl " : {
" verify_peer " : false ,
" verify_peer_name " : false ,
" allow_self_signed " : false ,
" SNI_enabled " : true ,
" disable_compression " : true ,
" security_level " : 1
} ,
" useAuth " : true ,
" setSender " : false ,
" usePhpMail " : false ,
" authPlainLine " : false
} ,
" Sieve " : {
2025-09-10 20:01:52 +02:00
" host " : " localhost " ,
2025-08-01 14:56:30 +05:00
" port " : 4190 ,
" type " : 0 ,
" timeout " : 10 ,
" shortLogin " : false ,
" sasl " : [
" SCRAM-SHA3-512 " ,
" SCRAM-SHA-512 " ,
" SCRAM-SHA-256 " ,
" SCRAM-SHA-1 " ,
" PLAIN " ,
" LOGIN "
] ,
" ssl " : {
" verify_peer " : false ,
" verify_peer_name " : false ,
" allow_self_signed " : false ,
" SNI_enabled " : true ,
" disable_compression " : true ,
" security_level " : 1
} ,
" enabled " : false
} ,
" whiteList " : " "
}
""" % (domain)
WriteToFile = open ( finalPathJson , ' w ' )
WriteToFile . write ( contentJSON )
WriteToFile . close ( )
command = ' chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/ '
ProcessUtilities . normalExecutioner ( command )
@staticmethod
def InstallMailBoxFoldersPlugin ( ) :
### now download and install actual plugin
labsPath = ' /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini '
command = f ' mkdir /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect '
ProcessUtilities . executioner ( command )
command = f ' chmod 700 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect '
ProcessUtilities . executioner ( command )
command = f ' chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect '
ProcessUtilities . executioner ( command )
command = f ' wget -O /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php '
ProcessUtilities . executioner ( command )
command = f ' chmod 644 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php '
ProcessUtilities . executioner ( command )
command = f ' chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php '
ProcessUtilities . executioner ( command )
### Enable plugins and enable mailbox creation plugin
labsDataLines = open ( labsPath , ' r ' ) . readlines ( )
PluginsActivator = 0
WriteToFile = open ( labsPath , ' w ' )
for lines in labsDataLines :
if lines . find ( ' [plugins] ' ) > - 1 :
PluginsActivator = 1
WriteToFile . write ( lines )
elif PluginsActivator and lines . find ( ' enable = ' ) > - 1 :
WriteToFile . write ( f ' enable = On \n ' )
elif PluginsActivator and lines . find ( ' enabled_list = ' ) > - 1 :
WriteToFile . write ( f ' enabled_list = " mailbox-detect " \n ' )
elif PluginsActivator == 1 and lines . find ( ' [defaults] ' ) > - 1 :
PluginsActivator = 0
WriteToFile . write ( lines )
else :
WriteToFile . write ( lines )
WriteToFile . close ( )
## enable auto create in the enabled plugin
PluginsFilePath = ' /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/plugin-mailbox-detect.json '
WriteToFile = open ( PluginsFilePath , ' w ' )
WriteToFile . write ( """ {
" plugin " : {
" autocreate_system_folders " : true
}
}
""" )
WriteToFile . close ( )
command = f ' chown lscpd:lscpd { PluginsFilePath } '
ProcessUtilities . executioner ( command )
command = f ' chmod 600 { PluginsFilePath } '
ProcessUtilities . executioner ( command )
@staticmethod
def createEmailAccount ( domain , userName , password , restore = None ) :
try :
## Check if already exists
finalEmailUsername = userName + " @ " + domain
if EUsers . objects . filter ( email = finalEmailUsername ) . exists ( ) :
raise BaseException ( " This account already exists! " )
## Check for email limits.
ChildCheck = 0
try :
website = Websites . objects . get ( domain = domain )
except :
website = ChildDomains . objects . get ( domain = domain )
ChildCheck = 1
try :
if not Domains . objects . filter ( domain = domain ) . exists ( ) :
if ChildCheck == 0 :
newEmailDomain = Domains ( domainOwner = website , domain = domain )
else :
newEmailDomain = Domains ( childOwner = website , domain = domain )
newEmailDomain . save ( )
if not DomainLimits . objects . filter ( domain = newEmailDomain ) . exists ( ) :
domainLimits = DomainLimits ( domain = newEmailDomain )
domainLimits . save ( )
if ChildCheck == 0 :
if website . package . emailAccounts == 0 or (
newEmailDomain . eusers_set . all ( ) . count ( ) < website . package . emailAccounts ) :
pass
else :
raise BaseException ( " Exceeded maximum amount of email accounts allowed for the package. " )
else :
if website . master . package . emailAccounts == 0 or (
newEmailDomain . eusers_set . all ( ) . count ( ) < website . master . package . emailAccounts ) :
pass
else :
raise BaseException ( " Exceeded maximum amount of email accounts allowed for the package. " )
except :
emailDomain = Domains . objects . get ( domain = domain )
if ChildCheck == 0 :
if website . package . emailAccounts == 0 or (
emailDomain . eusers_set . all ( ) . count ( ) < website . package . emailAccounts ) :
pass
else :
raise BaseException ( " Exceeded maximum amount of email accounts allowed for the package. " )
else :
if website . master . package . emailAccounts == 0 or (
emailDomain . eusers_set . all ( ) . count ( ) < website . master . package . emailAccounts ) :
pass
else :
raise BaseException ( " Exceeded maximum amount of email accounts allowed for the package. " )
## After effects
execPath = " /usr/local/CyberCP/bin/python /usr/local/CyberCP/plogical/mailUtilities.py "
execPath = execPath + " AfterEffects --domain " + domain
if getpass . getuser ( ) == ' root ' :
## This is the case when cPanel Importer is running and token is not present in enviroment.
ProcessUtilities . normalExecutioner ( execPath )
else :
ProcessUtilities . executioner ( execPath , ' lscpd ' )
## After effects ends
emailDomain = Domains . objects . get ( domain = domain )
#emailAcct = EUsers(emailOwner=emailDomain, email=finalEmailUsername, password=hash.hexdigest())
CentOSPath = ' /etc/redhat-release '
if os . path . exists ( CentOSPath ) :
if restore == None :
password = bcrypt . hashpw ( password . encode ( ' utf-8 ' ) , bcrypt . gensalt ( ) )
password = ' {CRYPT} %s ' % ( password . decode ( ) )
emailAcct = EUsers ( emailOwner = emailDomain , email = finalEmailUsername , password = password )
emailAcct . mail = ' maildir:/home/vmail/ %s / %s /Maildir ' % ( domain , userName )
emailAcct . save ( )
else :
if restore == None :
password = bcrypt . hashpw ( password . encode ( ' utf-8 ' ) , bcrypt . gensalt ( ) )
password = ' {CRYPT} %s ' % ( password . decode ( ) )
emailAcct = EUsers ( emailOwner = emailDomain , email = finalEmailUsername , password = password )
emailAcct . mail = ' maildir:/home/vmail/ %s / %s /Maildir ' % ( domain , userName )
emailAcct . save ( )
emailLimits = EmailLimits ( email = emailAcct )
emailLimits . save ( )
### Create maildir structure if it doesn't exist
# Create base maildir path
maildir_base = f " /home/vmail/ { domain } / { userName } "
maildir_path = f " { maildir_base } /Maildir "
# Create the main maildir structure
if not os . path . exists ( maildir_path ) :
command = f " mkdir -p ' { maildir_path } /cur ' ' { maildir_path } /new ' ' { maildir_path } /tmp ' "
ProcessUtilities . executioner ( command , ' vmail ' )
# Set proper permissions
command = f " chmod -R 700 ' { maildir_base } ' "
ProcessUtilities . executioner ( command , ' vmail ' )
# Ensure ownership is correct
command = f " chown -R vmail:vmail ' { maildir_base } ' "
ProcessUtilities . executioner ( command , ' root ' )
# Create standard IMAP folders
standard_folders = [
" .Archive " ,
" .Deleted Items " ,
" .Drafts " ,
" .Sent " ,
" .Junk E-mail "
]
for folder in standard_folders :
folder_path = f " { maildir_path } / { folder } "
if not os . path . exists ( folder_path ) :
command = f " mkdir -p ' { folder_path } /cur ' ' { folder_path } /new ' ' { folder_path } /tmp ' "
ProcessUtilities . executioner ( command , ' vmail ' )
# Set permissions for all folders
command = f " chmod -R 700 ' { maildir_path } ' "
ProcessUtilities . executioner ( command , ' vmail ' )
# Ensure final ownership
command = f " chown -R vmail:vmail ' { maildir_base } ' "
ProcessUtilities . executioner ( command , ' root ' )
#if not os.path.exists('/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'):
# mailUtilities.InstallMailBoxFoldersPlugin()
print ( " 1,None " )
return 1 , " None "
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [createEmailAccount] " )
print ( " 0, " + str ( msg ) )
return 0 , str ( msg )
@staticmethod
def deleteEmailAccount ( email ) :
try :
email = EUsers ( email = email )
email . delete ( )
return 1 , ' None '
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [deleteEmailAccount] " )
return 0 , str ( msg )
@staticmethod
def getEmailAccounts ( virtualHostName ) :
try :
emailDomain = Domains . objects . get ( domain = virtualHostName )
return emailDomain . eusers_set . all ( )
except :
return 0
@staticmethod
def changeEmailPassword ( email , newPassword , encrypt = None ) :
try :
2025-08-02 09:42:18 +05:00
changePass = EUsers . objects . get ( email = email )
2025-08-01 14:56:30 +05:00
if encrypt == None :
2025-08-02 09:42:18 +05:00
# Always use bcrypt hashing regardless of OS
password = bcrypt . hashpw ( newPassword . encode ( ' utf-8 ' ) , bcrypt . gensalt ( ) )
password = ' {CRYPT} %s ' % ( password . decode ( ) )
changePass . password = password
2025-08-01 14:56:30 +05:00
else :
changePass . password = newPassword
2025-08-02 09:42:18 +05:00
changePass . save ( )
2025-08-01 14:56:30 +05:00
return 0 , ' None '
except BaseException as msg :
return 0 , str ( msg )
@staticmethod
def setupDKIM ( virtualHostName ) :
try :
## Generate DKIM Keys
import tldextract
no_cache_extract = tldextract . TLDExtract ( cache_dir = None )
actualDomain = virtualHostName
extractDomain = no_cache_extract ( virtualHostName )
virtualHostName = extractDomain . domain + ' . ' + extractDomain . suffix
if not os . path . exists ( " /etc/opendkim/keys/ " + virtualHostName + " /default.txt " ) :
path = ' /etc/opendkim/keys/ %s ' % ( virtualHostName )
command = ' mkdir %s ' % ( path )
ProcessUtilities . normalExecutioner ( command )
## Generate keys
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = " /usr/sbin/opendkim-genkey -D /etc/opendkim/keys/ %s -d %s -s default " % ( virtualHostName , virtualHostName )
else :
command = " opendkim-genkey -D /etc/opendkim/keys/ %s -d %s -s default " % (
virtualHostName , virtualHostName )
ProcessUtilities . normalExecutioner ( command )
## Fix permissions
command = " chown -R root:opendkim /etc/opendkim/keys/ " + virtualHostName
ProcessUtilities . normalExecutioner ( command )
command = " chmod 640 /etc/opendkim/keys/ " + virtualHostName + " /default.private "
ProcessUtilities . normalExecutioner ( command )
command = " chmod 644 /etc/opendkim/keys/ " + virtualHostName + " /default.txt "
ProcessUtilities . normalExecutioner ( command )
## Edit key file
keyTable = " /etc/opendkim/KeyTable "
configToWrite = " default._domainkey. " + actualDomain + " " + actualDomain + " :default:/etc/opendkim/keys/ " + virtualHostName + " /default.private \n "
if not os . path . exists ( keyTable ) :
writeToFile = open ( keyTable , ' a ' )
writeToFile . write ( " ##### CyberPanel Generated File - Do not edit if you don ' t know what you are doing. \n " )
writeToFile . close ( )
data = open ( keyTable , ' r ' ) . read ( )
if data . find ( " default._domainkey. " + actualDomain ) == - 1 :
writeToFile = open ( keyTable , ' a ' )
writeToFile . write ( configToWrite )
writeToFile . close ( )
## Edit signing table
signingTable = " /etc/opendkim/SigningTable "
configToWrite = " *@ " + actualDomain + " default._domainkey. " + actualDomain + " \n "
if not os . path . exists ( signingTable ) :
writeToFile = open ( signingTable , ' a ' )
writeToFile . write ( " ##### CyberPanel Generated File - Do not edit if you don ' t know what you are doing. \n " )
writeToFile . close ( )
data = open ( signingTable , ' r ' ) . read ( )
if data . find ( " default._domainkey. " + actualDomain ) == - 1 :
writeToFile = open ( signingTable , ' a ' )
writeToFile . write ( configToWrite )
writeToFile . close ( )
## Trusted hosts
trustedHosts = " /etc/opendkim/TrustedHosts "
configToWrite = actualDomain + " \n "
if not os . path . exists ( trustedHosts ) :
writeToFile = open ( trustedHosts , ' a ' )
writeToFile . write ( " ##### CyberPanel Generated File - Do not edit if you don ' t know what you are doing. \n " )
writeToFile . close ( )
data = open ( trustedHosts , ' r ' ) . read ( )
if data . find ( actualDomain ) == - 1 :
writeToFile = open ( trustedHosts , ' a ' )
writeToFile . write ( configToWrite )
writeToFile . close ( )
## Restart Postfix and OpenDKIM
command = " systemctl restart opendkim "
subprocess . call ( shlex . split ( command ) )
command = " systemctl restart postfix "
subprocess . call ( shlex . split ( command ) )
return 1 , " None "
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [setupDKIM:275] " )
return 0 , str ( msg )
@staticmethod
def checkIfDKIMInstalled ( ) :
try :
path = " /etc/opendkim.conf "
command = " sudo cat " + path
return ProcessUtilities . executioner ( command )
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [checkIfDKIMInstalled] " )
return 0
@staticmethod
def generateKeys ( domain ) :
try :
result = mailUtilities . setupDKIM ( domain )
if result [ 0 ] == 0 :
raise BaseException ( result [ 1 ] )
else :
print ( " 1,None " )
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [generateKeys] " )
print ( " 0, " + str ( msg ) )
@staticmethod
def configureOpenDKIM ( ) :
try :
## Configure OpenDKIM specific settings
openDKIMConfigurePath = " /etc/opendkim.conf "
configData = """
Mode sv
Canonicalization relaxed / simple
KeyTable refile : / etc / opendkim / KeyTable
SigningTable refile : / etc / opendkim / SigningTable
ExternalIgnoreList refile : / etc / opendkim / TrustedHosts
InternalHosts refile : / etc / opendkim / TrustedHosts
"""
writeToFile = open ( openDKIMConfigurePath , ' a ' )
writeToFile . write ( configData )
writeToFile . close ( )
## Configure postfix specific settings
postfixFilePath = " /etc/postfix/main.cf "
configData = """
smtpd_milters = inet : 127.0 .0 .1 : 8891
non_smtpd_milters = $ smtpd_milters
milter_default_action = accept
"""
writeToFile = open ( postfixFilePath , ' a ' )
writeToFile . write ( configData )
writeToFile . close ( )
#### Restarting Postfix and OpenDKIM
command = " systemctl start opendkim "
subprocess . call ( shlex . split ( command ) )
command = " systemctl enable opendkim "
subprocess . call ( shlex . split ( command ) )
##
command = " systemctl start postfix "
subprocess . call ( shlex . split ( command ) )
print ( " 1,None " )
return
except OSError as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [configureOpenDKIM] " )
print ( " 0, " + str ( msg ) )
return
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [configureOpenDKIM] " )
print ( " 0, " + str ( msg ) )
return
@staticmethod
def checkHome ( ) :
try :
try :
FNULL = open ( os . devnull , ' w ' )
if getpass . getuser ( ) == ' root ' :
if not os . path . exists ( mailUtilities . cyberPanelHome ) :
command = " mkdir " + mailUtilities . cyberPanelHome
subprocess . call ( shlex . split ( command ) , stdout = FNULL )
command = " sudo chown -R cyberpanel:cyberpanel " + mailUtilities . cyberPanelHome
subprocess . call ( shlex . split ( command ) , stdout = FNULL )
else :
if not os . path . exists ( mailUtilities . cyberPanelHome ) :
command = " mkdir " + mailUtilities . cyberPanelHome
ProcessUtilities . executioner ( command )
command = " chown -R cyberpanel:cyberpanel " + mailUtilities . cyberPanelHome
ProcessUtilities . executioner ( command )
except :
FNULL = open ( os . devnull , ' w ' )
command = " chown -R cyberpanel:cyberpanel " + mailUtilities . cyberPanelHome
subprocess . call ( shlex . split ( command ) , stdout = FNULL )
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [checkHome] " )
@staticmethod
def installOpenDKIM ( install , openDKIMINstall ) :
try :
mailUtilities . checkHome ( )
command = ' sudo yum install opendkim -y '
cmd = shlex . split ( command )
with open ( mailUtilities . installLogPath , ' w ' ) as f :
res = subprocess . call ( cmd , stdout = f )
if res == 1 :
writeToFile = open ( mailUtilities . installLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( " [Could not Install OpenDKIM.] " )
return 0
else :
writeToFile = open ( mailUtilities . installLogPath , ' a ' )
writeToFile . writelines ( " OpenDKIM Installed.[200] \n " )
writeToFile . close ( )
return 1
except BaseException as msg :
writeToFile = open ( mailUtilities . installLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [installOpenDKIM] " )
@staticmethod
def restartServices ( ) :
try :
command = ' systemctl restart postfix '
subprocess . call ( shlex . split ( command ) )
command = ' systemctl restart dovecot '
subprocess . call ( shlex . split ( command ) )
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [restartServices] " )
@staticmethod
def installSpamAssassin ( install , SpamAssassin ) :
try :
if os . path . exists ( mailUtilities . spamassassinInstallLogPath ) :
os . remove ( mailUtilities . spamassassinInstallLogPath )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' sudo yum install spamassassin -y '
else :
command = ' sudo apt-get install spamassassin spamc -y '
cmd = shlex . split ( command )
with open ( mailUtilities . spamassassinInstallLogPath , ' w ' ) as f :
res = subprocess . call ( cmd , stdout = f )
if res == 1 :
writeToFile = open ( mailUtilities . spamassassinInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( " [Could not Install SpamAssassin.] " )
return 0
else :
writeToFile = open ( mailUtilities . spamassassinInstallLogPath , ' a ' )
writeToFile . writelines ( " SpamAssassin Installed.[200] \n " )
writeToFile . close ( )
return 1
except BaseException as msg :
writeToFile = open ( mailUtilities . spamassassinInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [installSpamAssassin] " )
@staticmethod
def SetupEmailLimits ( ) :
rlFile = ' /etc/rspamd/override.d/ratelimit.conf '
rlContent = '''
custom_keywords = " /etc/rspamd/custom_ratelimit.lua " ;
'''
if not os . path . exists ( rlFile ) :
WriteToFile = open ( rlFile , ' w ' )
WriteToFile . write ( rlContent )
WriteToFile . close ( )
rlLUA = ' /etc/rspamd/custom_ratelimit.lua '
rlLUAContent = '''
local custom_keywords = { }
local d = { }
- - create map
d [ ' badusers ' ] = rspamd_config : add_map ( {
[ ' url ' ] = ' /etc/rspamd/badusers.map ' ,
[ ' type ' ] = ' map ' ,
[ ' description ' ] = ' Bad users '
} )
custom_keywords . customrl = function ( task )
local rspamd_logger = require " rspamd_logger "
- - get authenticated user
local user = task : get_user ( )
- - define a default ratelimit
local default_rl = " 10 / 1m "
if not user then return end - - no user , return nil
local user_rl = d [ ' badusers ' ] : get_key ( user )
if user_rl then
local limit , duration , unit = string . match ( user_rl , " ( %d +) %s -/ %s -( %d +)( %a *) " )
if limit and duration then
duration = tonumber ( duration )
if unit == ' m ' then
duration = duration * 60 - - convert minutes to seconds
elseif unit == ' h ' then
duration = duration * 3600 - - convert hours to seconds
elseif unit == ' d ' then
duration = duration * 86400 - - convert days to seconds
end
local custom_rl = limit . . " / " . . duration . . " s "
rspamd_logger . infox ( rspamd_config , " User %s has custom ratelimit: %s " , user , custom_rl )
return " rs_customrl_ " . . user , custom_rl
else
rspamd_logger . errx ( rspamd_config , " Invalid ratelimit format for user %s , using default: %s " , user , default_rl )
return " rs_customrl_ " . . user , default_rl
end
else
rspamd_logger . infox ( rspamd_config , " User %s not found in bad users map, using default ratelimit: %s " , user , default_rl )
return " rs_customrl_ " . . user , default_rl
end
end
return custom_keywords
'''
WriteToFile = open ( rlLUA , ' w ' )
WriteToFile . write ( rlLUAContent )
WriteToFile . close ( )
@staticmethod
def installRspamd ( install , rspamd ) :
from manageServices . serviceManager import ServiceManager
try :
if os . path . exists ( mailUtilities . RspamdInstallLogPath ) :
os . remove ( mailUtilities . RspamdInstallLogPath )
####Frist install redis
ServiceManager . InstallRedis ( )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos :
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Configuring RSPAMD repo.. \n " )
writeToFile . close ( )
command = ' curl https://rspamd.com/rpm-stable/centos-7/rspamd.repo > /etc/yum.repos.d/rspamd.repo '
ProcessUtilities . normalExecutioner ( command , True )
command = ' rpm --import https://rspamd.com/rpm-stable/gpg.key '
ProcessUtilities . normalExecutioner ( command , True )
command = ' yum update '
ProcessUtilities . normalExecutioner ( command , True )
command = ' sudo yum install rspamd clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd -y '
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Configuring RSPAMD repo.. \n " )
writeToFile . close ( )
command = ' curl https://rspamd.com/rpm-stable/centos-8/rspamd.repo > /etc/yum.repos.d/rspamd.repo '
ProcessUtilities . normalExecutioner ( command , True )
command = ' rpm --import https://rspamd.com/rpm-stable/gpg.key '
ProcessUtilities . normalExecutioner ( command , True )
command = ' yum update '
ProcessUtilities . normalExecutioner ( command , True )
command = ' sudo yum install rspamd clamav clamd clamav-update -y '
else :
command = ' DEBIAN_FRONTEND=noninteractive apt-get install rspamd clamav clamav-daemon -y '
with open ( mailUtilities . RspamdInstallLogPath , ' w ' ) as f :
res = subprocess . call ( command , stdout = f , shell = True )
###### makefile
path = " /etc/rspamd/local.d/antivirus.conf "
content = """ # ================= DO NOT MODIFY THIS FILE =================
#
# Manual changes will be lost when this file is regenerated.
#
# Please read the developer's guide, which is available
# at NethServer official site: https://www.nethserver.org
#
#
#Enable or disable the module
enabled = true
# multiple scanners could be checked, for each we create a configuration block with an arbitrary name
clamav {
# If set force this action if any virus is found (default unset: no action is forced, 'rewrite_subject' to tag as spam)
action = " reject " ;
# if `true` only messages with non-image attachments will be checked (default true)
scan_mime_parts = false ;
# If `max_size` is set, messages > n bytes in size are not scanned
max_size = 20000000 ;
# type of scanner: "clamav", "fprot", "sophos" or "savapi"
type = " clamav " ;
# If set true, log message is emitted for clean messages
log_clean = false ;
# Timeout and retransmits increased in case of clamav is reloading its database
# It takes a lot of time (25 to 60 seconds), after rspamd answers a temporally failure
#timeout = 5;
#retransmits = 2;
# servers to query (if port is unspecified, scanner-specific default is used)
# can be specified multiple times to pool servers
# can be set to a path to a unix socket
servers = " 127.0.0.1:3310 " ;
# if `patterns` is specified virus name will be matched against provided regexes and the related
# symbol will be yielded if a match is found. If no match is found, default symbol is yielded.
patterns {
# symbol_name = "pattern";
CLAMAV_VIRUS = " ^Eicar-Test-Signature$ " ;
}
# In version 1.7.0+ patterns could be a list for ordered matching
#patterns = [{SANE_MAL = "Sanesecurity.Malware.*"}, {CLAM_UNOFFICIAL = "UNOFFICIAL$"}];
# `whitelist` points to a map of IP addresses. Mail from these addresses is not scanned.
whitelist = " /etc/rspamd/antivirus.wl " ;
}
"""
wirtedata = open ( path , ' w ' )
wirtedata . writelines ( content )
wirtedata . close ( )
### disable dkim signing in rspamd in ref to https://github.com/usmannasir/cyberpanel/issues/1176
DKIMPath = ' /etc/rspamd/local.d/dkim_signing.conf '
WriteToFile = open ( DKIMPath , ' w ' )
WriteToFile . write ( ' enabled = false; \n ' )
WriteToFile . close ( )
appendpath = " /etc/postfix/main.cf "
lines = open ( appendpath , ' r ' ) . readlines ( )
WriteToFile = open ( appendpath , ' w ' )
for line in lines :
if line . find ( ' inet:127.0.0.1:8891 ' ) > - 1 :
cLine = line . rstrip ( ' \n ' )
content = f ' { cLine } , inet:127.0.0.1:11332 \n '
WriteToFile . write ( ' ### Please do not edit this line, editing this line could break configurations \n ' )
WriteToFile . write ( content )
elif line . find ( ' non_smtpd_milters ' ) > - 1 :
WriteToFile . write ( ' non_smtpd_milters = $smtpd_milters \n ' )
else :
WriteToFile . write ( line )
WriteToFile . close ( )
wpath = " /etc/rspamd/local.d/redis.conf "
wdata = """
write_servers = " 127.0.0.1 " ;
read_servers = " 127.0.0.1 " ;
"""
wirtedata2 = open ( wpath , ' w ' )
wirtedata2 . writelines ( wdata )
wirtedata2 . close ( )
if res == 1 :
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( " [Could not Install Rspamd.] " )
return 0
else :
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' setsebool -P antivirus_can_scan_system 1 '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' setsebool -P clamd_use_jit 1 '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' usermod -a -G clamscan _rspamd '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
clamavcontent = """
User clamscan
PidFile / var / run / clamd . scan / clamd . pid
TCPSocket 3310
TCPAddr 127.0 .0 .1
ConcurrentDatabaseReload no
Debug false
FixStaleSocket true
LocalSocketMode 666
ScanMail true
ScanArchive true
#LogFile /var/log/clamd.scan/clamav.log
"""
writeToFile = open ( ' /etc/clamd.d/scan.conf ' , ' w ' )
writeToFile . write ( clamavcontent )
writeToFile . close ( )
command = ' touch /var/log/clamd.scan/clamav.log '
ProcessUtilities . normalExecutioner ( command , False , ' clamscan ' )
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Updating Freshclam database.. \n " )
writeToFile . close ( )
command = ' freshclam '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' systemctl start clamd@scan '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' systemctl restart rspamd '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
command = ' usermod -a -G clamav _rspamd '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' chown -R clamav:clamav /var/run/clamav '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
clamavcontent = """
User clamav
PidFile / var / run / clamav / clamd . pid
TCPSocket 3310
TCPAddr 127.0 .0 .1
ConcurrentDatabaseReload no
Debug false
FixStaleSocket true
LocalSocketMode 666
ScanMail true
ScanArchive true
LogFile / var / log / clamav / clamav . log
"""
writeToFile = open ( ' /etc/clamav/clamd.conf ' , ' w ' )
writeToFile . write ( clamavcontent )
writeToFile . close ( )
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Updating Freshclam database.. \n " )
writeToFile . close ( )
command = ' freshclam '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' systemctl restart clamav-daemon '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
command = ' systemctl restart rspamd '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdInstallLogPath , ' a ' ) as f :
res = subprocess . call ( cmd , stdout = f )
time . sleep ( 5 )
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Rspamd Installed.[200] \n " )
writeToFile . close ( )
return 1
except BaseException as msg :
writeToFile = open ( mailUtilities . RspamdInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [installRspamd] " )
@staticmethod
def uninstallRspamd ( install , rspamd ) :
from manageServices . serviceManager import ServiceManager
try :
logging . CyberCPLogFileWriter . writeToFile ( " start................[uninstallRspamd] " )
if os . path . exists ( mailUtilities . RspamdUnInstallLogPath ) :
os . remove ( mailUtilities . RspamdUnInstallLogPath )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' sudo yum remove rspamd clamav clamav-daemon -y '
else :
command = ' sudo apt purge rspamd clamav clamav-daemon -y '
cmd = shlex . split ( command )
with open ( mailUtilities . RspamdUnInstallLogPath , ' w ' ) as f :
res = subprocess . call ( cmd , stdout = f )
if res == 1 :
writeToFile = open ( mailUtilities . RspamdUnInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be uninstalled.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( " [Could not Install Rspamd.] " )
return 0
else :
cmdd = ' systemctl stop rspamd '
ProcessUtilities . normalExecutioner ( cmdd )
cmmd = ' systemctl disable rspamd '
ProcessUtilities . normalExecutioner ( cmmd )
writeToFile = open ( mailUtilities . RspamdUnInstallLogPath , ' a ' )
writeToFile . writelines ( " Rspamd unInstalled.[200] \n " )
writeToFile . close ( )
return 1
except BaseException as msg :
writeToFile = open ( mailUtilities . RspamdUnInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [uninstallRspamd] " )
@staticmethod
def changeRspamdConfig ( install , changeRspamdConfig ) :
try :
tempfilepath = " /home/cyberpanel/tempfilerspamdconfigs "
file = open ( tempfilepath , " r " )
jsondata1 = file . read ( )
jsondata = json . loads ( jsondata1 )
file . close ( )
status = jsondata [ ' status ' ]
scan_mime_parts = jsondata [ ' scan_mime_parts ' ]
log_clean = jsondata [ ' log_clean ' ]
max_size = jsondata [ ' max_size ' ]
server = jsondata [ ' Rspamdserver ' ]
CLAMAV_VIRUS = jsondata [ ' CLAMAV_VIRUS ' ]
action_rspamd = jsondata [ ' action_rspamd ' ]
confPath = " /etc/rspamd/local.d/antivirus.conf "
f = open ( confPath , " r " )
dataa = f . read ( )
f . close ( )
data = dataa . splitlines ( )
writeDataToFile = open ( confPath , " w " )
for items in data :
if items . find ( ' enabled ' ) > - 1 :
if status == True :
command = ' systemctl start rspamd '
ProcessUtilities . executioner ( command )
newitem = ' enabled = true '
writeDataToFile . writelines ( newitem + ' \n ' )
elif status == False :
command = ' systemctl stop rspamd '
ProcessUtilities . executioner ( command )
newitem = ' enabled = false '
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' action = ' ) > - 1 :
if action_rspamd == ' Reject ' :
newitem = ' action = " reject " ; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif action_rspamd == ' Unset ' :
newitem = ' action = " unset " ; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' scan_mime_parts ' ) > - 1 :
if scan_mime_parts == True :
newitem = ' scan_mime_parts = true; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif scan_mime_parts == False :
newitem = ' scan_mime_parts = false; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' log_clean = ' ) > - 1 :
if log_clean == True :
newitem = ' log_clean = true; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif log_clean == False :
newitem = ' log_clean = false; '
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' max_size = ' ) > - 1 :
newitem = ' max_size = %s ; ' % max_size
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' CLAMAV_VIRUS = ' ) > - 1 :
newitem = ' CLAMAV_VIRUS = " %s " ; ' % CLAMAV_VIRUS
writeDataToFile . writelines ( newitem + ' \n ' )
elif items . find ( ' servers = ' ) > - 1 :
newitem = ' servers = " %s " ; ' % server
writeDataToFile . writelines ( newitem + ' \n ' )
else :
writeDataToFile . writelines ( items + ' \n ' )
print ( " 1,None " )
return 1 , ' None '
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [changeRspamdConfig] " )
str ( ( msg ) + " [changeRspamdConfig] " )
print ( 0 , str ( msg ) )
return [ 0 , str ( msg ) + " [changeRspamdConfig] " ]
@staticmethod
def changePostfixConfig ( install , changePostfixConfig ) :
try :
tempfilepath = " /home/cyberpanel/tempfilepostfixconfigs "
file = open ( tempfilepath , " r " )
jsondata1 = file . read ( )
jsondata = json . loads ( jsondata1 )
file . close ( )
non_smtpd_milters = jsondata [ ' non_smtpd_milters ' ]
smtpd_milters = jsondata [ ' smtpd_milters ' ]
postfixpath = " /etc/postfix/main.cf "
f = open ( postfixpath , " r " )
dataa = f . read ( )
f . close ( )
data = dataa . splitlines ( )
writeDataToFile = open ( postfixpath , " w " )
for i in data :
if ( i . find ( ' smtpd_milters= ' ) > - 1 or i . find ( ' smtpd_milters = ' ) > - 1 ) and i . find ( ' non_smtpd_milters ' ) < 0 :
newitem = f ' smtpd_milters = inet:127.0.0.1:8891, { smtpd_milters } \n '
writeDataToFile . writelines ( newitem + ' \n ' )
elif i . find ( ' non_smtpd_milters= ' ) > - 1 or i . find ( ' non_smtpd_milters = ' ) > - 1 :
#newitem = 'non_smtpd_milters=%s' % non_smtpd_milters
writeDataToFile . writelines ( ' non_smtpd_milters = $smtpd_milters \n ' )
else :
writeDataToFile . writelines ( i + ' \n ' )
print ( " 1,None " )
return 1 , ' None '
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [changePostfixConfig] " )
str ( ( msg ) + " [changePostfixConfig] " )
print ( 0 , str ( msg ) )
return [ 0 , str ( msg ) + " [changePostfixConfig] " ]
@staticmethod
def changeRedisxConfig ( install , changeRedisxConfig ) :
try :
tempfilepath = " /home/cyberpanel/saveRedisConfigurations "
file = open ( tempfilepath , " r " )
jsondata1 = file . read ( )
jsondata = json . loads ( jsondata1 )
file . close ( )
write_servers = jsondata [ ' write_servers ' ]
read_servers = jsondata [ ' read_servers ' ]
Redispath = " /etc/rspamd/local.d/redis.conf "
f = open ( Redispath , " r " )
dataa = f . read ( )
f . close ( )
data = dataa . splitlines ( )
writeDataToFile = open ( Redispath , " w " )
for i in data :
if i . find ( ' write_servers = ' ) > - 1 :
newitem = ' write_servers = " %s " ; ' % write_servers
writeDataToFile . writelines ( newitem + ' \n ' )
elif i . find ( ' read_servers = ' ) > - 1 :
newitem = ' read_servers = " %s " ; ' % read_servers
writeDataToFile . writelines ( newitem + ' \n ' )
else :
writeDataToFile . writelines ( i + ' \n ' )
print ( " 1,None " )
return 1 , ' None '
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [changeRedisxConfig] " )
str ( ( msg ) + " [changeRedisxConfig] " )
print ( 0 , str ( msg ) )
return [ 0 , str ( msg ) + " [changeRedisxConfig] " ]
@staticmethod
def changeclamavConfig ( install , changeclamavConfig ) :
try :
tempfilepath = " /home/cyberpanel/saveclamavConfigurations "
file = open ( tempfilepath , " r " )
jsondata1 = file . read ( )
jsondata = json . loads ( jsondata1 )
file . close ( )
LogFile = jsondata [ ' LogFile ' ]
TCPAddr = jsondata [ ' TCPAddr ' ]
TCPSocket = jsondata [ ' TCPSocket ' ]
clamav_Debug = jsondata [ ' clamav_Debug ' ]
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
clamavconfpath = ' /etc/clamd.d/scan.conf '
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
clamavconfpath = " /etc/clamav/clamd.conf "
f = open ( clamavconfpath , " r " )
dataa = f . read ( )
f . close ( )
data = dataa . splitlines ( )
writeDataToFile = open ( clamavconfpath , " w " )
for i in data :
if i . find ( ' TCPSocket ' ) > - 1 :
newitem = ' TCPSocket %s ' % TCPSocket
writeDataToFile . writelines ( newitem + ' \n ' )
elif i . find ( ' TCPAddr ' ) > - 1 :
newitem = ' TCPAddr %s ' % TCPAddr
writeDataToFile . writelines ( newitem + ' \n ' )
elif i . find ( ' LogFile ' ) > - 1 :
newitem = ' LogFile %s ' % LogFile
writeDataToFile . writelines ( newitem + ' \n ' )
elif i . find ( ' Debug = ' ) > - 1 :
if clamav_Debug == True :
newitem = ' Debug true '
writeDataToFile . writelines ( newitem + ' \n ' )
elif clamav_Debug == False :
newitem = ' Debug false '
writeDataToFile . writelines ( newitem + ' \n ' )
else :
writeDataToFile . writelines ( i + ' \n ' )
return 1 , ' None '
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [changeclamavConfig] " )
str ( ( msg ) + " [changeclamavConfig] " )
print ( 0 , str ( msg ) )
return [ 0 , str ( msg ) + " [changeclamavConfig] " ]
@staticmethod
def installMailScanner ( install , SpamAssassin ) :
try :
if os . path . exists ( mailUtilities . mailScannerInstallLogPath ) :
os . remove ( mailUtilities . mailScannerInstallLogPath )
if mailUtilities . checkIfSpamAssassinInstalled ( ) :
command = ' chmod +x /usr/local/CyberCP/CPScripts/mailscannerinstaller.sh '
ProcessUtilities . executioner ( command )
command = ' /usr/local/CyberCP/CPScripts/mailscannerinstaller.sh '
cmd = shlex . split ( command )
with open ( mailUtilities . mailScannerInstallLogPath , ' w ' ) as f :
res = subprocess . call ( cmd , stdout = f , shell = True )
if res == 1 :
writeToFile = open ( mailUtilities . mailScannerInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( " [Could not Install MailScanner.] " )
return 0
else :
writeToFile = open ( mailUtilities . mailScannerInstallLogPath , ' a ' )
writeToFile . writelines ( " MailScanner Installed.[200] \n " )
writeToFile . close ( )
return 1
else :
writeToFile = open ( mailUtilities . mailScannerInstallLogPath , ' a ' )
writeToFile . writelines ( " Please install SpamAssassin from CyberPanel before installing MailScanner.[404] \n " )
writeToFile . close ( )
except BaseException as msg :
writeToFile = open ( mailUtilities . mailScannerInstallLogPath , ' a ' )
writeToFile . writelines ( " Can not be installed.[404] \n " )
writeToFile . close ( )
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [installSpamAssassin] " )
@staticmethod
def checkIfSpamAssassinInstalled ( ) :
try :
path = " /etc/postfix/master.cf "
command = " cat " + path
output = ProcessUtilities . outputExecutioner ( command )
if output . find ( ' spamassassin ' ) > - 1 and output . find ( ' user=spamd ' ) > - 1 :
return 1
else :
return 0
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [checkIfSpamAssassinInstalled] " )
return 0
@staticmethod
def configureSpamAssassin ( ) :
try :
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
confFile = " /etc/mail/spamassassin/local.cf "
confData = open ( confFile ) . readlines ( )
conf = open ( confFile , ' w ' )
for items in confData :
if items . find ( ' report_safe ' ) > - 1 or items . find ( ' rewrite_header ' ) > - 1 or items . find ( ' required_score ' ) > - 1 or items . find ( ' required_hits ' ) > - 1 :
conf . write ( items . strip ( ' # ' ) . strip ( ' ' ) )
else :
conf . write ( items )
conf . close ( )
command = " groupadd spamd "
ProcessUtilities . normalExecutioner ( command )
command = " useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd "
ProcessUtilities . normalExecutioner ( command )
##
command = " chown spamd:spamd /var/log/spamassassin "
ProcessUtilities . normalExecutioner ( command )
command = " systemctl enable spamassassin "
ProcessUtilities . normalExecutioner ( command )
command = " systemctl start spamassassin "
ProcessUtilities . normalExecutioner ( command )
## Configuration to postfix
postfixConf = ' /etc/postfix/master.cf '
data = open ( postfixConf , ' r ' ) . readlines ( )
writeToFile = open ( postfixConf , ' w ' )
checker = 1
for items in data :
if items . find ( ' smtp ' ) > - 1 and items . find ( ' inet ' ) > - 1 and items . find ( ' smtpd ' ) > - 1 and checker == 1 :
writeToFile . writelines ( items . strip ( ' \n ' ) + ' -o content_filter=spamassassin \n ' )
checker = 0
else :
writeToFile . writelines ( items )
writeToFile . writelines ( ' spamassassin unix - n n - - pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f $ {sender} $ {recipient} ' )
writeToFile . close ( )
command = ' systemctl restart postfix '
ProcessUtilities . normalExecutioner ( command )
print ( " 1,None " )
return
except OSError as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [configureSpamAssassin] " )
print ( " 0, " + str ( msg ) )
return
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile ( str ( msg ) + " [configureSpamAssassin] " )
print ( " 0, " + str ( msg ) )
return
@staticmethod
def saveSpamAssassinConfigs ( tempConfigPath ) :
try :
data = open ( tempConfigPath ) . readlines ( )
os . remove ( tempConfigPath )
confFile = " /etc/mail/spamassassin/local.cf "
confData = open ( confFile ) . readlines ( )
conf = open ( confFile , ' w ' )
rsCheck = 0
for items in confData :
if items . find ( ' report_safe ' ) > - 1 :
conf . writelines ( data [ 0 ] )
continue
elif items . find ( ' required_hits ' ) > - 1 :
conf . writelines ( data [ 1 ] )
continue
elif items . find ( ' rewrite_header ' ) > - 1 :
conf . writelines ( data [ 2 ] )
continue
elif items . find ( ' required_score ' ) > - 1 :
conf . writelines ( data [ 3 ] )
rsCheck = 1
continue
if rsCheck == 0 :
conf . writelines ( data [ 3 ] )
conf . close ( )
command = ' systemctl restart spamassassin '
subprocess . call ( shlex . split ( command ) )
print ( " 1,None " )
return
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [saveSpamAssassinConfigs] " )
print ( " 0, " + str ( msg ) )
@staticmethod
def savePolicyServerStatus ( install ) :
try :
postfixPath = ' /etc/postfix/main.cf '
if install == ' 1 ' :
if not os . path . exists ( ' /etc/systemd/system/cpecs.service ' ) :
shutil . copy ( " /usr/local/CyberCP/postfixSenderPolicy/cpecs.service " , " /etc/systemd/system/cpecs.service " )
command = ' systemctl enable cpecs '
subprocess . call ( shlex . split ( command ) )
command = ' systemctl start cpecs '
subprocess . call ( shlex . split ( command ) )
writeToFile = open ( postfixPath , ' a ' )
writeToFile . writelines ( ' smtpd_data_restrictions = check_policy_service unix:/var/log/policyServerSocket \n ' )
writeToFile . writelines ( ' smtpd_policy_service_default_action = DUNNO \n ' )
writeToFile . close ( )
command = ' systemctl restart postfix '
subprocess . call ( shlex . split ( command ) )
else :
data = open ( postfixPath , ' r ' ) . readlines ( )
writeToFile = open ( postfixPath , ' w ' )
for items in data :
if items . find ( ' check_policy_service unix:/var/log/policyServerSocket ' ) > - 1 :
continue
elif items . find ( ' smtpd_policy_service_default_action = DUNNO ' ) > - 1 :
continue
else :
writeToFile . writelines ( items )
writeToFile . close ( )
command = ' systemctl stop cpecs '
subprocess . call ( shlex . split ( command ) )
command = ' systemctl restart postfix '
subprocess . call ( shlex . split ( command ) )
print ( " 1,None " )
return
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [savePolicyServerStatus] " )
print ( " 0, " + str ( msg ) )
@staticmethod
def checkIfMailScannerInstalled ( ) :
try :
path = " /usr/local/CyberCP/public/mailwatch "
if os . path . exists ( path ) :
return 1
else :
return 0
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [checkIfMailScannerInstalled] " )
return 0
@staticmethod
def checkIfRspamdInstalled ( ) :
try :
if os . path . exists ( ' /etc/rspamd/rspamd.conf ' ) :
return 1
else :
return 0
except BaseException as msg :
logging . CyberCPLogFileWriter . writeToFile (
str ( msg ) + " [checkIfMailScannerInstalled] " )
return 0
@staticmethod
def FetchPostfixHostname ( ) :
try :
PostfixPath = ' /etc/postfix/main.cf '
if os . path . exists ( PostfixPath ) :
PostFixConf = open ( PostfixPath , ' r ' ) . readlines ( )
for line in PostFixConf :
if line . find ( ' myhostname ' ) > - 1 :
hostname = line . split ( ' = ' ) [ 1 ] . strip ( ' ' ) . rstrip ( ' \n ' )
return hostname
else :
return ' localhost '
except :
return ' localhost '
@staticmethod
def reverse_dns_lookup ( ip_address ) :
2025-12-09 18:32:52 +01:00
"""
Perform reverse DNS lookup for the given IP address using external DNS servers .
2026-01-31 20:46:30 +01:00
Falls back to local DNS resolution if external APIs are unavailable .
2025-12-09 18:32:52 +01:00
Args :
ip_address : The IP address to perform reverse DNS lookup on
Returns :
list : List of rDNS hostnames found , or empty list if lookup fails
"""
2025-08-01 14:56:30 +05:00
try :
import requests
2025-12-09 18:32:52 +01:00
from requests . exceptions import RequestException , Timeout , ConnectionError
2025-08-01 14:56:30 +05:00
2025-12-09 18:32:52 +01:00
# Fetch DNS server URLs with proper error handling
try :
fetchURLs = requests . get ( ' https://cyberpanel.net/dnsServers.txt ' , timeout = 10 )
except ( ConnectionError , Timeout ) as e :
2026-01-31 20:46:30 +01:00
logging . CyberCPLogFileWriter . writeToFile ( f ' Failed to fetch DNS server list from cyberpanel.net: { str ( e ) } . Falling back to local DNS lookup. ' )
fetchURLs = None
2025-12-09 18:32:52 +01:00
except RequestException as e :
2026-01-31 20:46:30 +01:00
logging . CyberCPLogFileWriter . writeToFile ( f ' Request error while fetching DNS server list: { str ( e ) } . Falling back to local DNS lookup. ' )
fetchURLs = None
2025-12-09 18:32:52 +01:00
2026-01-31 20:46:30 +01:00
# Try external API if available
if fetchURLs and fetchURLs . status_code == 200 :
2025-12-09 18:32:52 +01:00
2026-01-31 20:46:30 +01:00
try :
urls_data = fetchURLs . json ( )
if ' urls ' not in urls_data :
logging . CyberCPLogFileWriter . writeToFile ( ' DNS server list response missing " urls " key. Falling back to local DNS lookup. ' )
fetchURLs = None
else :
urls = urls_data [ ' urls ' ]
if not isinstance ( urls , list ) or len ( urls ) == 0 :
logging . CyberCPLogFileWriter . writeToFile ( ' DNS server list is empty or invalid. Falling back to local DNS lookup. ' )
fetchURLs = None
else :
# External API is available, proceed with queries
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' DNS urls { urls } . ' )
2025-12-09 18:32:52 +01:00
2026-01-31 20:46:30 +01:00
results = [ ]
successful_queries = 0
2025-12-09 18:32:52 +01:00
2026-01-31 20:46:30 +01:00
# Query each DNS server
for url in urls :
v2.5.5-dev: FTP Create Account fix, ftp_quotas table, CP_VERSION, mailUtilities indent, deploy scripts and docs
- baseTemplate: CP_VERSION from CYBERPANEL_FULL_VERSION (2.5.5.dev) for cache busting
- FTP Create Account: inline script + polling + scope sync so details form shows after website select
- ftp.js: showFTPDetails, select2/change handlers (ftp/static, static, public/static)
- sql/create_ftp_quotas.sql + deploy-ftp-quotas-table.sh for /ftp/quotaManagement
- plogical/mailUtilities.py: indentation fix in DNS query try/except block
- deploy-ftp-create-account-fix.sh, to-do docs (FTP-QUOTAS-TABLE-FIX, V2.5.5-DEV-FIXES-AND-DEPLOY, RUNTIME-VS-REPO)
2026-02-04 02:33:32 +01:00
try :
response = requests . get ( f ' { url } /index.php?ip= { ip_address } ' , timeout = 5 )
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' url to call { ip_address } is { url } ' )
if response . status_code == 200 :
try :
data = response . json ( )
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' response from dns system { str ( data ) } ' )
# Validate response structure
if not isinstance ( data , dict ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' Invalid response format from { url } : not a dictionary ' )
continue
if ' status ' not in data :
logging . CyberCPLogFileWriter . writeToFile ( f ' Response from { url } missing " status " key ' )
continue
if data [ ' status ' ] == 1 :
# Validate results structure
if ' results ' not in data or not isinstance ( data [ ' results ' ] , dict ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' Response from { url } missing or invalid " results " key ' )
continue
results_dict = data [ ' results ' ]
# Safely extract results from different DNS servers
dns_servers = [ ' 8.8.8.8 ' , ' 1.1.1.1 ' , ' 9.9.9.9 ' ]
for dns_server in dns_servers :
if dns_server in results_dict :
result_value = results_dict [ dns_server ]
if result_value and result_value not in results :
results . append ( result_value )
successful_queries + = 1
else :
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' DNS server { url } returned status != 1: { data . get ( " status " , " unknown " ) } ' )
except ValueError as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Failed to parse JSON response from { url } : { str ( e ) } ' )
continue
except KeyError as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Missing key in response from { url } : { str ( e ) } ' )
continue
else :
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' DNS server { url } returned HTTP { response . status_code } ' )
except Timeout as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Timeout while querying DNS server { url } : { str ( e ) } ' )
continue
except ConnectionError as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Connection error while querying DNS server { url } : { str ( e ) } ' )
continue
except RequestException as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Request error while querying DNS server { url } : { str ( e ) } ' )
continue
except Exception as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Unexpected error while querying DNS server { url } : { str ( e ) } ' )
2025-12-09 18:32:52 +01:00
continue
2025-08-01 14:56:30 +05:00
2026-01-31 20:46:30 +01:00
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' rDNS result of { ip_address } is { str ( results ) } (successful queries: { successful_queries } / { len ( urls ) } ) ' )
# If external API returned results, return them
if results :
return results
# Otherwise fall through to local DNS lookup
logging . CyberCPLogFileWriter . writeToFile ( f ' External DNS API queries returned no results for { ip_address } . Falling back to local DNS lookup. ' )
except ( ValueError , KeyError ) as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Failed to parse DNS server list JSON: { str ( e ) } . Falling back to local DNS lookup. ' )
fetchURLs = None
else :
if fetchURLs :
logging . CyberCPLogFileWriter . writeToFile ( f ' Failed to fetch DNS server list: HTTP { fetchURLs . status_code if fetchURLs else " N/A " } . Falling back to local DNS lookup. ' )
fetchURLs = None
2025-08-01 14:56:30 +05:00
2026-01-31 20:46:30 +01:00
# Fallback to local DNS lookup when external APIs fail or return no results
try :
import socket
rdns = socket . gethostbyaddr ( ip_address ) [ 0 ]
rdns_clean = rdns . rstrip ( ' . ' )
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup successful for { ip_address } : { rdns_clean } ' )
return [ rdns_clean ]
except socket . herror as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup failed for { ip_address } : { str ( e ) } ' )
return [ ]
except Exception as e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Unexpected error in local DNS lookup for { ip_address } : { str ( e ) } ' )
return [ ]
2025-12-09 18:32:52 +01:00
except ImportError as e :
2026-01-31 20:46:30 +01:00
logging . CyberCPLogFileWriter . writeToFile ( f ' Failed to import requests library: { str ( e ) } . Attempting local DNS lookup. ' )
try :
import socket
rdns = socket . gethostbyaddr ( ip_address ) [ 0 ]
rdns_clean = rdns . rstrip ( ' . ' )
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup successful for { ip_address } : { rdns_clean } ' )
return [ rdns_clean ]
except Exception as local_e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup also failed for { ip_address } : { str ( local_e ) } ' )
return [ ]
2025-08-01 14:56:30 +05:00
except BaseException as e :
2026-01-31 20:46:30 +01:00
logging . CyberCPLogFileWriter . writeToFile ( f ' Unexpected error in reverse_dns_lookup for IP { ip_address } : { str ( e ) } . Attempting local DNS lookup. ' )
try :
import socket
rdns = socket . gethostbyaddr ( ip_address ) [ 0 ]
rdns_clean = rdns . rstrip ( ' . ' )
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup successful for { ip_address } : { rdns_clean } ' )
return [ rdns_clean ]
except Exception as local_e :
logging . CyberCPLogFileWriter . writeToFile ( f ' Local DNS lookup also failed for { ip_address } : { str ( local_e ) } ' )
return [ ]
2025-08-01 14:56:30 +05:00
@staticmethod
def SaveEmailLimitsNew ( tempPath ) :
try :
content = open ( tempPath , ' r ' ) . read ( )
email = content . split ( ' ' ) [ 0 ]
path = ' /etc/rspamd/badusers.map '
WriteCheck = 0
if os . path . exists ( path ) :
data = open ( path , ' r ' ) . readlines ( )
WriteToFile = open ( path , ' w ' )
for line in data :
if line . find ( email ) > - 1 :
WriteToFile . write ( content )
WriteCheck = 1
else :
WriteToFile . write ( line )
if WriteCheck == 0 :
WriteToFile . write ( content )
WriteToFile . close ( )
else :
WriteToFile = open ( path , ' w ' )
WriteToFile . write ( content )
WriteToFile . close ( )
command = ' systemctl restart rspamd '
ProcessUtilities . executioner ( command )
print ( f ' 1,None ' )
except BaseException as msg :
print ( f ' 0, { str ( msg ) } ' )
####### Imported below functions from mailserver/mailservermanager, need to refactor later
class MailServerManagerUtils ( multi . Thread ) :
def __init__ ( self , request = None , function = None , extraArgs = None ) :
multi . Thread . __init__ ( self )
self . request = request
self . function = function
self . extraArgs = extraArgs
self . MailSSL = 0
def checkIfMailServerSSLIssued ( self ) :
postfixPath = ' /etc/postfix/main.cf '
postFixData = ProcessUtilities . outputExecutioner ( ' cat %s ' % ( postfixPath ) )
if postFixData . find ( ' myhostname = server.example.com ' ) > - 1 :
self . MailSSL = 0
return 0
else :
try :
postFixLines = ProcessUtilities . outputExecutioner ( ' cat %s ' % ( postfixPath ) ) . splitlines ( )
for items in postFixLines :
if items . find ( ' myhostname ' ) > - 1 and items [ 0 ] != ' # ' :
self . mailHostName = items . split ( ' = ' ) [ 1 ] . strip ( ' ' )
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( f ' Mail server SSL is issued with value: { self . mailHostName } ' )
self . MailSSL = 1
except BaseException as msg :
self . MailSSL = 0
logging . CyberCPLogFileWriter . writeToFile ( ' %s . [checkIfMailServerSSLIssued:864] ' % ( str ( msg ) ) )
ipFile = " /etc/cyberpanel/machineIP "
f = open ( ipFile )
ipData = f . read ( )
ipAddress = ipData . split ( ' \n ' , 1 ) [ 0 ]
command = ' openssl s_client -connect %s :465 ' % ( ipAddress )
result = ProcessUtilities . outputExecutioner ( command )
if result . find ( ' 18 (self signed certificate) ' ) > - 1 :
return 0
else :
return 1
def RunServerLevelEmailChecks ( self ) :
try :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Checking if MailServer SSL issued..,10 ' )
reportFile = self . extraArgs [ ' reportFile ' ]
report = { }
report [ ' MailSSL ' ] = self . checkIfMailServerSSLIssued ( )
writeToFile = open ( reportFile , ' w ' )
writeToFile . write ( json . dumps ( report ) )
writeToFile . close ( )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Completed [200]. ' )
except BaseException as msg :
final_dic = { ' installOpenDKIM ' : 0 , ' error_message ' : str ( msg ) }
final_json = json . dumps ( final_dic )
return HttpResponse ( final_json )
def FetchCloudLinuxAlmaVersionVersion ( self ) :
if os . path . exists ( ' /etc/os-release ' ) :
data = open ( ' /etc/os-release ' , ' r ' ) . read ( )
if ( data . find ( ' CloudLinux ' ) > - 1 or data . find ( ' cloudlinux ' ) > - 1 ) and (
data . find ( ' 8.9 ' ) > - 1 or data . find ( ' Anatoly Levchenko ' ) > - 1 or data . find ( ' VERSION= " 8. ' ) > - 1 ) :
return ' cl-89 '
elif ( data . find ( ' CloudLinux ' ) > - 1 or data . find ( ' cloudlinux ' ) > - 1 ) and (
data . find ( ' 8.8 ' ) > - 1 or data . find ( ' Anatoly Filipchenko ' ) > - 1 ) :
return ' cl-88 '
elif ( data . find ( ' CloudLinux ' ) > - 1 or data . find ( ' cloudlinux ' ) > - 1 ) and (
data . find ( ' 9.4 ' ) > - 1 or data . find ( ' VERSION= " 9. ' ) > - 1 ) :
return ' cl-88 '
elif ( data . find ( ' AlmaLinux ' ) > - 1 or data . find ( ' almalinux ' ) > - 1 ) and (
data . find ( ' 8.9 ' ) > - 1 or data . find ( ' Midnight Oncilla ' ) > - 1 or data . find ( ' VERSION= " 8. ' ) > - 1 ) :
return ' al-88 '
elif ( data . find ( ' AlmaLinux ' ) > - 1 or data . find ( ' almalinux ' ) > - 1 ) and (
data . find ( ' 8.7 ' ) > - 1 or data . find ( ' Stone Smilodon ' ) > - 1 ) :
return ' al-87 '
elif ( data . find ( ' AlmaLinux ' ) > - 1 or data . find ( ' almalinux ' ) > - 1 ) and (
data . find ( ' 9.4 ' ) > - 1 or data . find ( ' 9.3 ' ) > - 1 or data . find ( ' Shamrock Pampas ' ) > - 1 or data . find (
' Seafoam Ocelot ' ) > - 1 or data . find ( ' VERSION= " 9. ' ) > - 1 ) :
return ' al-93 '
else :
return - 1
def install_postfix_dovecot ( self ) :
try :
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' yum remove postfix* dovecot* -y '
ProcessUtilities . executioner ( command , None , True )
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
command = ' apt-get -y remove postfix* dovecot* '
ProcessUtilities . executioner ( command , None , True )
### On Ubuntu 18 find if old dovecot and remove
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu :
try :
command = ' apt-get purge dovecot* -y '
ProcessUtilities . executioner ( command , None , True )
command = ' apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 18A348AEED409DA1 '
ProcessUtilities . executioner ( command )
writeToFile = open ( ' /etc/apt/sources.list.d/dovecot.list ' , ' a ' )
writeToFile . writelines ( ' deb [arch=amd64] https://repo.dovecot.org/ce-2.3-latest/ubuntu/bionic bionic main \n ' )
writeToFile . close ( )
command = ' apt update '
ProcessUtilities . executioner ( command )
except :
pass
##
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Re-installing postfix..,10 ' )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos :
2025-08-19 18:36:48 +05:00
command = ' yum --nogpg install https://mirror.ghettoforge.net/distributions/gf/gf-release-latest.gf.el7.noarch.rpm -y '
2025-08-01 14:56:30 +05:00
ProcessUtilities . executioner ( command )
command = ' yum install --enablerepo=gf-plus -y postfix3 postfix3-ldap postfix3-mysql postfix3-pcre '
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
clAPVersion = self . FetchCloudLinuxAlmaVersionVersion ( )
type = clAPVersion . split ( ' - ' ) [ 0 ]
version = int ( clAPVersion . split ( ' - ' ) [ 1 ] )
if type == ' al ' and version > = 90 :
2025-08-19 18:36:48 +05:00
command = ' dnf --nogpg install -y https://mirror.ghettoforge.net/distributions/gf/gf-release-latest.gf.el9.noarch.rpm '
2025-08-01 14:56:30 +05:00
ProcessUtilities . executioner ( command )
else :
2025-08-19 18:36:48 +05:00
command = ' dnf --nogpg install -y https://mirror.ghettoforge.net/distributions/gf/gf-release-latest.gf.el8.noarch.rpm '
2025-08-01 14:56:30 +05:00
ProcessUtilities . executioner ( command )
command = ' dnf install --enablerepo=gf-plus postfix3 postfix3-mysql -y '
else :
import socket
command = ' apt-get install -y debconf-utils '
ProcessUtilities . executioner ( command )
file_name = ' pf.unattend.text '
pf = open ( file_name , ' w ' )
pf . write ( ' postfix postfix/mailname string ' + str ( socket . getfqdn ( ) + ' \n ' ) )
pf . write ( ' postfix postfix/main_mailer_type string " Internet Site " \n ' )
pf . close ( )
command = ' debconf-set-selections ' + file_name
ProcessUtilities . executioner ( command )
command = ' apt-get -y install postfix postfix-mysql '
# os.remove(file_name)
ProcessUtilities . executioner ( command )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Re-installing Dovecot..,15 ' )
##
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos :
command = ' yum --enablerepo=gf-plus -y install dovecot23 dovecot23-mysql '
ProcessUtilities . executioner ( command )
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' dnf install --enablerepo=gf-plus dovecot23 dovecot23-mysql -y '
ProcessUtilities . executioner ( command )
else :
command = ' DEBIAN_FRONTEND=noninteractive apt-get -y install dovecot-mysql dovecot-imapd dovecot-pop3d '
os . system ( command )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Postfix/dovecot reinstalled.,40 ' )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' %s [install_postfix_dovecot][404] ' % ( str ( msg ) ) , 10 )
return 0
return 1
def setup_email_Passwords ( self , mysqlPassword ) :
try :
mysql_virtual_domains = " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_domains.cf "
mysql_virtual_forwardings = " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_forwardings.cf "
mysql_virtual_mailboxes = " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_mailboxes.cf "
mysql_virtual_email2email = " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_email2email.cf "
dovecotmysql = " /usr/local/CyberCP/install/email-configs-one/dovecot-sql.conf.ext "
### update password:
data = open ( dovecotmysql , " r " ) . readlines ( )
writeDataToFile = open ( dovecotmysql , " w " )
dataWritten = " connect = host=localhost dbname=cyberpanel user=cyberpanel password= " + mysqlPassword + " port=3306 \n "
for items in data :
if items . find ( " connect " ) > - 1 :
writeDataToFile . writelines ( dataWritten )
else :
writeDataToFile . writelines ( items )
# if self.distro == ubuntu:
# os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile . close ( )
### update password:
data = open ( mysql_virtual_domains , " r " ) . readlines ( )
writeDataToFile = open ( mysql_virtual_domains , " w " )
dataWritten = " password = " + mysqlPassword + " \n "
for items in data :
if items . find ( " password " ) > - 1 :
writeDataToFile . writelines ( dataWritten )
else :
writeDataToFile . writelines ( items )
# if self.distro == ubuntu:
# os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile . close ( )
### update password:
data = open ( mysql_virtual_forwardings , " r " ) . readlines ( )
writeDataToFile = open ( mysql_virtual_forwardings , " w " )
dataWritten = " password = " + mysqlPassword + " \n "
for items in data :
if items . find ( " password " ) > - 1 :
writeDataToFile . writelines ( dataWritten )
else :
writeDataToFile . writelines ( items )
# if self.distro == ubuntu:
# os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile . close ( )
### update password:
data = open ( mysql_virtual_mailboxes , " r " ) . readlines ( )
writeDataToFile = open ( mysql_virtual_mailboxes , " w " )
dataWritten = " password = " + mysqlPassword + " \n "
for items in data :
if items . find ( " password " ) > - 1 :
writeDataToFile . writelines ( dataWritten )
else :
writeDataToFile . writelines ( items )
# if self.distro == ubuntu:
# os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile . close ( )
### update password:
data = open ( mysql_virtual_email2email , " r " ) . readlines ( )
writeDataToFile = open ( mysql_virtual_email2email , " w " )
dataWritten = " password = " + mysqlPassword + " \n "
for items in data :
if items . find ( " password " ) > - 1 :
writeDataToFile . writelines ( dataWritten )
else :
writeDataToFile . writelines ( items )
# if self.distro == ubuntu:
# os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
writeDataToFile . close ( )
if self . remotemysql == ' ON ' :
command = " sed -i ' s|host=localhost|host= %s |g ' %s " % ( self . mysqlhost , dovecotmysql )
ProcessUtilities . executioner ( command )
command = " sed -i ' s|port=3306|port= %s |g ' %s " % ( self . mysqlport , dovecotmysql )
ProcessUtilities . executioner ( command )
##
command = " sed -i ' s|localhost| %s : %s |g ' %s " % ( self . mysqlhost , self . mysqlport , mysql_virtual_domains )
ProcessUtilities . executioner ( command )
command = " sed -i ' s|localhost| %s : %s |g ' %s " % (
self . mysqlhost , self . mysqlport , mysql_virtual_forwardings )
ProcessUtilities . executioner ( command )
command = " sed -i ' s|localhost| %s : %s |g ' %s " % (
self . mysqlhost , self . mysqlport , mysql_virtual_mailboxes )
ProcessUtilities . executioner ( command )
command = " sed -i ' s|localhost| %s : %s |g ' %s " % (
self . mysqlhost , self . mysqlport , mysql_virtual_email2email )
ProcessUtilities . executioner ( command )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' %s [setup_email_Passwords][404] ' % ( str ( msg ) ) , 10 )
return 0
return 1
def centos_lib_dir_to_ubuntu ( self , filename , old , new ) :
try :
#command = "sed -i 's|%s|%s|g' %s" % (old, new, filename)
#ProcessUtilities.executioner(command, None, True)
fd = open ( filename , ' r ' )
lines = fd . readlines ( )
fd . close ( )
fd = open ( filename , ' w ' )
centos_prefix = old
ubuntu_prefix = new
for line in lines :
index = line . find ( centos_prefix )
if index != - 1 :
line = line [ : index ] + ubuntu_prefix + line [ index + len ( centos_prefix ) : ]
fd . write ( line )
fd . close ( )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' %s [centos_lib_dir_to_ubuntu][404] ' % ( str ( msg ) ) , 10 )
def setup_postfix_dovecot_config ( self ) :
try :
mysql_virtual_domains = " /etc/postfix/mysql-virtual_domains.cf "
mysql_virtual_forwardings = " /etc/postfix/mysql-virtual_forwardings.cf "
mysql_virtual_mailboxes = " /etc/postfix/mysql-virtual_mailboxes.cf "
mysql_virtual_email2email = " /etc/postfix/mysql-virtual_email2email.cf "
main = " /etc/postfix/main.cf "
master = " /etc/postfix/master.cf "
dovecot = " /etc/dovecot/dovecot.conf "
dovecotmysql = " /etc/dovecot/dovecot-sql.conf.ext "
if os . path . exists ( mysql_virtual_domains ) :
os . remove ( mysql_virtual_domains )
if os . path . exists ( mysql_virtual_forwardings ) :
os . remove ( mysql_virtual_forwardings )
if os . path . exists ( mysql_virtual_mailboxes ) :
os . remove ( mysql_virtual_mailboxes )
if os . path . exists ( mysql_virtual_email2email ) :
os . remove ( mysql_virtual_email2email )
if os . path . exists ( main ) :
os . remove ( main )
if os . path . exists ( master ) :
os . remove ( master )
if os . path . exists ( dovecot ) :
os . remove ( dovecot )
if os . path . exists ( dovecotmysql ) :
os . remove ( dovecotmysql )
###############Getting SSL
command = ' openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj " /C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com " -keyout /etc/postfix/key.pem -out /etc/postfix/cert.pem '
ProcessUtilities . executioner ( command )
##
command = ' openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj " /C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com " -keyout /etc/dovecot/key.pem -out /etc/dovecot/cert.pem '
ProcessUtilities . executioner ( command )
# Cleanup config files for ubuntu
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
self . centos_lib_dir_to_ubuntu ( " /usr/local/CyberCP/install/email-configs-one/master.cf " , " /usr/libexec/ " ,
" /usr/lib/ " )
self . centos_lib_dir_to_ubuntu ( " /usr/local/CyberCP/install/email-configs-one/main.cf " ,
" /usr/libexec/postfix " ,
" /usr/lib/postfix/sbin " )
########### Copy config files
import shutil
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_domains.cf " ,
" /etc/postfix/mysql-virtual_domains.cf " )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_forwardings.cf " ,
" /etc/postfix/mysql-virtual_forwardings.cf " )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_mailboxes.cf " ,
" /etc/postfix/mysql-virtual_mailboxes.cf " )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/mysql-virtual_email2email.cf " ,
" /etc/postfix/mysql-virtual_email2email.cf " )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/main.cf " , main )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/master.cf " , master )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/dovecot.conf " , dovecot )
shutil . copy ( " /usr/local/CyberCP/install/email-configs-one/dovecot-sql.conf.ext " , dovecotmysql )
######################################## Permissions
command = ' chmod o= /etc/postfix/mysql-virtual_domains.cf '
ProcessUtilities . executioner ( command )
##
command = ' chmod o= /etc/postfix/mysql-virtual_forwardings.cf '
ProcessUtilities . executioner ( command )
##
command = ' chmod o= /etc/postfix/mysql-virtual_mailboxes.cf '
ProcessUtilities . executioner ( command )
##
command = ' chmod o= /etc/postfix/mysql-virtual_email2email.cf '
ProcessUtilities . executioner ( command )
##
command = ' chmod o= ' + main
ProcessUtilities . executioner ( command )
##
command = ' chmod o= ' + master
ProcessUtilities . executioner ( command )
#######################################
command = ' chgrp postfix /etc/postfix/mysql-virtual_domains.cf '
ProcessUtilities . executioner ( command )
##
command = ' chgrp postfix /etc/postfix/mysql-virtual_forwardings.cf '
ProcessUtilities . executioner ( command )
##
command = ' chgrp postfix /etc/postfix/mysql-virtual_mailboxes.cf '
ProcessUtilities . executioner ( command )
##
command = ' chgrp postfix /etc/postfix/mysql-virtual_email2email.cf '
ProcessUtilities . executioner ( command )
##
command = ' chgrp postfix ' + main
ProcessUtilities . executioner ( command )
##
command = ' chgrp postfix ' + master
ProcessUtilities . executioner ( command )
######################################## users and groups
command = ' groupadd -g 5000 vmail '
ProcessUtilities . executioner ( command )
##
command = ' useradd -g vmail -u 5000 vmail -d /home/vmail -m '
ProcessUtilities . executioner ( command )
######################################## Further configurations
# hostname = socket.gethostname()
################################### Restart postix
command = ' systemctl enable postfix.service '
ProcessUtilities . executioner ( command )
##
command = ' systemctl start postfix.service '
ProcessUtilities . executioner ( command )
######################################## Permissions
command = ' chgrp dovecot /etc/dovecot/dovecot-sql.conf.ext '
ProcessUtilities . executioner ( command )
##
command = ' chmod o= /etc/dovecot/dovecot-sql.conf.ext '
ProcessUtilities . executioner ( command )
################################### Restart dovecot
command = ' systemctl enable dovecot.service '
ProcessUtilities . executioner ( command )
##
command = ' systemctl start dovecot.service '
ProcessUtilities . executioner ( command )
##
command = ' systemctl restart postfix.service '
ProcessUtilities . executioner ( command )
## changing permissions for main.cf
command = " chmod 755 " + main
ProcessUtilities . executioner ( command )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
command = " mkdir -p /etc/pki/dovecot/private/ "
ProcessUtilities . executioner ( command )
command = " mkdir -p /etc/pki/dovecot/certs/ "
ProcessUtilities . executioner ( command )
command = " mkdir -p /etc/opendkim/keys/ "
ProcessUtilities . executioner ( command )
command = " sed -i ' s/auth_mechanisms = plain/#auth_mechanisms = plain/g ' /etc/dovecot/conf.d/10-auth.conf "
ProcessUtilities . executioner ( command )
## Ubuntu 18.10 ssl_dh for dovecot 2.3.2.1
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu :
dovecotConf = ' /etc/dovecot/dovecot.conf '
data = open ( dovecotConf , ' r ' ) . readlines ( )
writeToFile = open ( dovecotConf , ' w ' )
for items in data :
if items . find ( ' ssl_key = <key.pem ' ) > - 1 :
writeToFile . writelines ( items )
writeToFile . writelines ( ' ssl_dh = </usr/share/dovecot/dh.pem \n ' )
else :
writeToFile . writelines ( items )
writeToFile . close ( )
command = " systemctl restart dovecot "
ProcessUtilities . executioner ( command )
## For ubuntu 20
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
command = " sed -i ' s|daemon_directory = /usr/libexec/postfix|daemon_directory = /usr/lib/postfix/sbin|g ' /etc/postfix/main.cf "
ProcessUtilities . executioner ( command )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' %s [setup_postfix_dovecot_config][404] ' % (
str ( msg ) ) , 10 )
return 0
return 1
def fixCyberPanelPermissions ( self ) :
###### fix Core CyberPanel permissions
command = " find /usr/local/CyberCP -type d -exec chmod 0755 {} \ ; "
ProcessUtilities . executioner ( command )
command = " find /usr/local/CyberCP -type f -exec chmod 0644 {} \ ; "
ProcessUtilities . executioner ( command )
command = " chmod -R 755 /usr/local/CyberCP/bin "
ProcessUtilities . executioner ( command )
## change owner
command = " chown -R root:root /usr/local/CyberCP "
ProcessUtilities . executioner ( command )
########### Fix LSCPD
command = " find /usr/local/lscp -type d -exec chmod 0755 {} \ ; "
ProcessUtilities . executioner ( command )
command = " find /usr/local/lscp -type f -exec chmod 0644 {} \ ; "
ProcessUtilities . executioner ( command )
command = " chmod -R 755 /usr/local/lscp/bin "
ProcessUtilities . executioner ( command )
command = " chmod -R 755 /usr/local/lscp/fcgi-bin "
ProcessUtilities . executioner ( command )
command = " chown -R lscpd:lscpd /usr/local/CyberCP/public/phpmyadmin/tmp "
ProcessUtilities . executioner ( command )
## change owner
command = " chown -R root:root /usr/local/lscp "
ProcessUtilities . executioner ( command )
command = " chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data "
ProcessUtilities . executioner ( command )
command = " chmod 700 /usr/local/CyberCP/cli/cyberPanel.py "
ProcessUtilities . executioner ( command )
command = " chmod 700 /usr/local/CyberCP/plogical/upgradeCritical.py "
ProcessUtilities . executioner ( command )
command = " chmod 755 /usr/local/CyberCP/postfixSenderPolicy/client.py "
ProcessUtilities . executioner ( command )
command = " chmod 640 /usr/local/CyberCP/CyberCP/settings.py "
ProcessUtilities . executioner ( command )
command = " chown root:cyberpanel /usr/local/CyberCP/CyberCP/settings.py "
ProcessUtilities . executioner ( command )
files = [ ' /etc/yum.repos.d/MariaDB.repo ' , ' /etc/pdns/pdns.conf ' , ' /etc/systemd/system/lscpd.service ' ,
' /etc/pure-ftpd/pure-ftpd.conf ' , ' /etc/pure-ftpd/pureftpd-pgsql.conf ' ,
' /etc/pure-ftpd/pureftpd-mysql.conf ' , ' /etc/pure-ftpd/pureftpd-ldap.conf ' ,
' /etc/dovecot/dovecot.conf ' , ' /usr/local/lsws/conf/httpd_config.xml ' ,
' /usr/local/lsws/conf/modsec.conf ' , ' /usr/local/lsws/conf/httpd.conf ' ]
for items in files :
command = ' chmod 644 %s ' % ( items )
ProcessUtilities . executioner ( command )
impFile = [ ' /etc/pure-ftpd/pure-ftpd.conf ' , ' /etc/pure-ftpd/pureftpd-pgsql.conf ' ,
' /etc/pure-ftpd/pureftpd-mysql.conf ' , ' /etc/pure-ftpd/pureftpd-ldap.conf ' ,
' /etc/dovecot/dovecot.conf ' , ' /etc/pdns/pdns.conf ' , ' /etc/pure-ftpd/db/mysql.conf ' ,
' /etc/powerdns/pdns.conf ' ]
for items in impFile :
command = ' chmod 600 %s ' % ( items )
ProcessUtilities . executioner ( command )
command = ' chmod 640 /etc/postfix/*.cf '
subprocess . call ( command , shell = True )
command = ' chmod 644 /etc/postfix/main.cf '
subprocess . call ( command , shell = True )
command = ' chmod 640 /etc/dovecot/*.conf '
subprocess . call ( command , shell = True )
command = ' chmod 644 /etc/dovecot/dovecot.conf '
subprocess . call ( command , shell = True )
command = ' chmod 640 /etc/dovecot/dovecot-sql.conf.ext '
subprocess . call ( command , shell = True )
command = ' chmod 644 /etc/postfix/dynamicmaps.cf '
subprocess . call ( command , shell = True )
fileM = [ ' /usr/local/lsws/FileManager/ ' , ' /usr/local/CyberCP/install/FileManager ' ,
' /usr/local/CyberCP/serverStatus/litespeed/FileManager ' , ' /usr/local/lsws/Example/html/FileManager ' ]
for items in fileM :
try :
import shutil
shutil . rmtree ( items )
except :
pass
command = ' chmod 755 /etc/pure-ftpd/ '
subprocess . call ( command , shell = True )
command = ' chmod +x /usr/local/CyberCP/plogical/renew.py '
ProcessUtilities . executioner ( command )
command = ' chmod +x /usr/local/CyberCP/CLManager/CLPackages.py '
ProcessUtilities . executioner ( command )
clScripts = [ ' /usr/local/CyberCP/CLScript/panel_info.py ' , ' /usr/local/CyberCP/CLScript/CloudLinuxPackages.py ' ,
' /usr/local/CyberCP/CLScript/CloudLinuxUsers.py ' ,
' /usr/local/CyberCP/CLScript/CloudLinuxDomains.py '
, ' /usr/local/CyberCP/CLScript/CloudLinuxResellers.py ' , ' /usr/local/CyberCP/CLScript/CloudLinuxAdmins.py ' ,
' /usr/local/CyberCP/CLScript/CloudLinuxDB.py ' , ' /usr/local/CyberCP/CLScript/UserInfo.py ' ]
for items in clScripts :
command = ' chmod +x %s ' % ( items )
ProcessUtilities . executioner ( command )
command = ' chmod 600 /usr/local/CyberCP/plogical/adminPass.py '
ProcessUtilities . executioner ( command )
command = ' chmod 600 /etc/cagefs/exclude/cyberpanelexclude '
ProcessUtilities . executioner ( command )
command = " find /usr/local/CyberCP/ -name ' *.pyc ' -delete "
ProcessUtilities . executioner ( command )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos or ProcessUtilities . cent8 :
command = ' chown root:pdns /etc/pdns/pdns.conf '
ProcessUtilities . executioner ( command )
command = ' chmod 640 /etc/pdns/pdns.conf '
ProcessUtilities . executioner ( command )
command = ' chmod 640 /usr/local/lscp/cyberpanel/logs/access.log '
ProcessUtilities . executioner ( command )
###
def installOpenDKIMNew ( self ) :
try :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Installing opendkim..,40 ' )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . centos :
command = ' yum -y erase opendkim* '
os . system ( command )
command = ' yum -y install opendkim '
elif ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' yum -y erase opendkim* '
os . system ( command )
command = ' dnf install opendkim -y '
else :
command = ' apt-get -y purge opendkim '
os . system ( command )
command = ' DEBIAN_FRONTEND=noninteractive apt-get -y install opendkim '
os . system ( command )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' dnf install opendkim-tools -y '
ProcessUtilities . executioner ( command )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 :
command = ' apt install opendkim-tools -y '
ProcessUtilities . executioner ( command )
command = ' mkdir -p /etc/opendkim/keys/ '
ProcessUtilities . executioner ( command )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' %s [installOpenDKIM][404] ' % ( str ( msg ) ) , 10 )
return 0
return 1
def SetupDKIMFromResetMail ( self ) :
from plogical . dnsUtilities import DNS
for website in Websites . objects . all ( ) :
mailUtilities . setupDKIM ( website . domain )
DNS . createDKIMRecords ( website . domain )
for website in ChildDomains . objects . all ( ) :
mailUtilities . setupDKIM ( website . domain )
DNS . createDKIMRecords ( website . domain )
def ResetEmailConfigurations ( self ) :
try :
### Check if remote or local mysql
passFile = " /etc/cyberpanel/mysqlPassword "
try :
jsonData = json . loads ( ProcessUtilities . outputExecutioner ( ' cat %s ' % ( passFile ) ) )
self . mysqluser = jsonData [ ' mysqluser ' ]
self . mysqlpassword = jsonData [ ' mysqlpassword ' ]
self . mysqlport = jsonData [ ' mysqlport ' ]
self . mysqlhost = jsonData [ ' mysqlhost ' ]
self . remotemysql = ' ON '
if self . mysqlhost . find ( ' rds.amazon ' ) > - 1 :
self . RDS = 1
## Also set localhost to this server
ipFile = " /etc/cyberpanel/machineIP "
f = open ( ipFile )
ipData = f . read ( )
ipAddressLocal = ipData . split ( ' \n ' , 1 ) [ 0 ]
self . LOCALHOST = ipAddressLocal
except BaseException as msg :
self . remotemysql = ' OFF '
if os . path . exists ( ProcessUtilities . debugPath ) :
logging . CyberCPLogFileWriter . writeToFile ( ' %s . [setupConnection:75] ' % ( str ( msg ) ) )
###
self . checkIfMailServerSSLIssued ( )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Removing and re-installing postfix/dovecot..,5 ' )
if self . install_postfix_dovecot ( ) == 0 :
return 0
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Resetting configurations..,40 ' )
import sys
sys . path . append ( ' /usr/local/CyberCP ' )
os . environ . setdefault ( " DJANGO_SETTINGS_MODULE " , " CyberCP.settings " )
from CyberCP import settings
if self . setup_email_Passwords ( settings . DATABASES [ ' default ' ] [ ' PASSWORD ' ] ) == 0 :
return 0
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Configurations reset..,70 ' )
if self . setup_postfix_dovecot_config ( ) == 0 :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' setup_postfix_dovecot_config failed. [404]. ' )
return 0
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Restoring OpenDKIM configurations..,70 ' )
if self . installOpenDKIMNew ( ) == 0 :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Install OpenDKIM failed. [404]. ' )
return 0
if self . configureOpenDKIM ( ) == 0 :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' configureOpenDKIM failed. [404]. ' )
return 0
self . SetupDKIMFromResetMail ( )
if self . MailSSL :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Setting up Mail Server SSL if any..,75 ' )
from plogical . virtualHostUtilities import virtualHostUtilities
virtualHostUtilities . issueSSLForMailServer ( self . mailHostName ,
' /home/ %s /public_html ' % ( self . mailHostName ) )
MailServerSSLCheck = 0
from websiteFunctions . models import ChildDomains
from plogical . virtualHostUtilities import virtualHostUtilities
for websites in Websites . objects . all ( ) :
try :
child = ChildDomains . objects . get ( domain = ' mail. %s ' % ( websites . domain ) )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Creating mail domain for %s ..,80 ' % ( websites . domain ) )
virtualHostUtilities . setupAutoDiscover ( 1 , ' /dev/null ' , websites . domain , websites . admin )
except :
pass
if self . MailSSL == 0 and MailServerSSLCheck == 0 :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Setting up Mail Server SSL as no hostname SSL found..,80 ' )
from plogical . virtualHostUtilities import virtualHostUtilities
virtualHostUtilities . issueSSLForMailServer ( websites . domain ,
' /home/ %s /public_html ' % ( websites . domain ) )
MailServerSSLCheck = 1
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Fixing permissions..,90 ' )
self . fixCyberPanelPermissions ( )
command = ' /usr/local/CyberCP/bin/python /usr/local/CyberCP/dns/dnsManager.py ResetDNSConfigurations --tempStatusPath /home/cyberpanel/dnscheck '
ProcessUtilities . executioner ( command )
command = ' touch /home/cyberpanel/postfix '
ProcessUtilities . executioner ( command )
###
etcResolve = ' /etc/resolv.conf '
if os . path . exists ( etcResolve ) :
dataEtcResolv = open ( etcResolve , ' r ' ) . read ( )
else :
dataEtcResolv = ' '
if len ( dataEtcResolv ) < 4 :
writeToFile = open ( etcResolve , ' w ' )
writeToFile . write ( ' nameserver 8.8.8.8 \n ' )
writeToFile . close ( )
command = ' systemctl restart postfix '
ProcessUtilities . executioner ( command )
command = ' systemctl restart dovecot '
ProcessUtilities . executioner ( command )
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] , ' Completed [200]. ' )
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' Failed. Error %s [404]. ' % str ( msg ) )
def configureOpenDKIM ( self ) :
try :
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
command = ' dnf install opendkim-tools -y '
ProcessUtilities . executioner ( command )
## Configure OpenDKIM specific settings
openDKIMConfigurePath = " /etc/opendkim.conf "
configData = """
Mode sv
Canonicalization relaxed / simple
KeyTable refile : / etc / opendkim / KeyTable
SigningTable refile : / etc / opendkim / SigningTable
ExternalIgnoreList refile : / etc / opendkim / TrustedHosts
InternalHosts refile : / etc / opendkim / TrustedHosts
"""
writeToFile = open ( openDKIMConfigurePath , ' a ' )
writeToFile . write ( configData )
writeToFile . close ( )
## Configure postfix specific settings
postfixFilePath = " /etc/postfix/main.cf "
configData = """
smtpd_milters = inet : 127.0 .0 .1 : 8891
non_smtpd_milters = $ smtpd_milters
milter_default_action = accept
"""
writeToFile = open ( postfixFilePath , ' a ' )
writeToFile . write ( configData )
writeToFile . close ( )
if ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu or ProcessUtilities . decideDistro ( ) == ProcessUtilities . ubuntu20 or ProcessUtilities . decideDistro ( ) == ProcessUtilities . cent8 :
data = open ( openDKIMConfigurePath , ' r ' ) . readlines ( )
writeToFile = open ( openDKIMConfigurePath , ' w ' )
for items in data :
if items . find ( ' Socket ' ) > - 1 and items . find ( ' local: ' ) > - 1 :
writeToFile . writelines ( ' Socket inet:8891@localhost \n ' )
else :
writeToFile . writelines ( items )
writeToFile . close ( )
#### Restarting Postfix and OpenDKIM
command = " systemctl start opendkim "
ProcessUtilities . executioner ( command )
command = " systemctl enable opendkim "
ProcessUtilities . executioner ( command )
##
command = " systemctl restart postfix "
ProcessUtilities . executioner ( command )
return 1
except BaseException as msg :
logging . CyberCPLogFileWriter . statusWriter ( self . extraArgs [ ' tempStatusPath ' ] ,
' configureOpenDKIM failed. Error %s [404]. ' % str ( msg ) )
return 0
def debugEmailForSite ( self , websiteName ) :
ipFile = " /etc/cyberpanel/machineIP "
f = open ( ipFile )
ipData = f . read ( )
ipAddress = ipData . split ( ' \n ' , 1 ) [ 0 ]
try :
import socket
siteIPAddr = socket . gethostbyname ( ' mail. %s ' % ( websiteName ) )
if siteIPAddr != ipAddress :
return 0 , ' mail. %s does not point to %s . ' % ( websiteName , ipAddress )
except :
return 0 , ' mail. %s does not point to %s . ' % ( websiteName , ipAddress )
command = ' openssl s_client -connect mail. %s :993 ' % ( websiteName )
result = ProcessUtilities . outputExecutioner ( command )
if result . find ( ' 18 (self signed certificate) ' ) > - 1 :
return 0 , ' No valid SSL on port 993. '
else :
return 1 , ' All checks are OK. '
def main ( ) :
parser = argparse . ArgumentParser ( description = ' CyberPanel Installer ' )
parser . add_argument ( ' function ' , help = ' Specific a function to call! ' )
parser . add_argument ( ' --domain ' , help = ' Domain name! ' )
parser . add_argument ( ' --userName ' , help = ' Email Username! ' )
parser . add_argument ( ' --password ' , help = ' Email password! ' )
parser . add_argument ( ' --tempConfigPath ' , help = ' Temporary Configuration Path! ' )
parser . add_argument ( ' --install ' , help = ' Enable/Disable Policy Server! ' )
parser . add_argument ( ' --tempStatusPath ' , help = ' Path of temporary status file. ' )
args = parser . parse_args ( )
if args . function == " createEmailAccount " :
mailUtilities . createEmailAccount ( args . domain , args . userName , args . password )
elif args . function == " generateKeys " :
mailUtilities . generateKeys ( args . domain )
elif args . function == " configureOpenDKIM " :
mailUtilities . configureOpenDKIM ( )
elif args . function == " configureSpamAssassin " :
mailUtilities . configureSpamAssassin ( )
elif args . function == " saveSpamAssassinConfigs " :
mailUtilities . saveSpamAssassinConfigs ( args . tempConfigPath )
elif args . function == ' savePolicyServerStatus ' :
mailUtilities . savePolicyServerStatus ( args . install )
elif args . function == ' installSpamAssassin ' :
mailUtilities . installSpamAssassin ( " install " , " SpamAssassin " )
elif args . function == ' installRspamd ' :
mailUtilities . installRspamd ( " install " , " rspamd " )
elif args . function == ' uninstallRspamd ' :
mailUtilities . uninstallRspamd ( " install " , " rspamd " )
elif args . function == ' installMailScanner ' :
mailUtilities . installMailScanner ( " install " , " installMailScanner " )
elif args . function == ' changeRspamdConfig ' :
mailUtilities . changeRspamdConfig ( " install " , " changeRspamdConfig " )
elif args . function == ' changePostfixConfig ' :
mailUtilities . changePostfixConfig ( " install " , " changePostfixConfig " )
elif args . function == ' changeRedisxConfig ' :
mailUtilities . changeRedisxConfig ( " install " , " changeRedisxConfig " )
elif args . function == ' changeclamavConfig ' :
mailUtilities . changeclamavConfig ( " install " , " changeclamavConfig " )
elif args . function == ' AfterEffects ' :
mailUtilities . AfterEffects ( args . domain )
elif args . function == " ResetEmailConfigurations " :
extraArgs = { ' tempStatusPath ' : args . tempStatusPath }
background = MailServerManagerUtils ( None , ' ResetEmailConfigurations ' , extraArgs )
background . ResetEmailConfigurations ( )
elif args . function == ' SetupEmailLimits ' :
mailUtilities . SetupEmailLimits ( )
elif args . function == ' SaveEmailLimitsNew ' :
mailUtilities . SaveEmailLimitsNew ( args . tempConfigPath )
if __name__ == " __main__ " :
main ( )