diff --git a/install/installCyberPanel.py b/install/installCyberPanel.py index bb17b5530..6f39a6788 100644 --- a/install/installCyberPanel.py +++ b/install/installCyberPanel.py @@ -66,8 +66,20 @@ class InstallCyberPanel: } actual_service = service_map.get(service_name, service_name) - command = f'systemctl {action} {actual_service}' - return install_utils.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + # For AlmaLinux 9, try both mariadb and mysqld services + if service_name == 'mariadb' and (self.distro == cent8 or self.distro == openeuler): + # Try mariadb first, then mysqld if mariadb fails + command = f'systemctl {action} {actual_service}' + result = install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + if result != 0: + # If mariadb service fails, try mysqld + command = f'systemctl {action} mysqld' + return install_utils.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + return result + else: + command = f'systemctl {action} {actual_service}' + return install_utils.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) def modify_file_content(self, file_path, replacements): """Generic file content modification""" @@ -368,6 +380,29 @@ class InstallCyberPanel: if self.distro != ubuntu: InstallCyberPanel.stdOut("LiteSpeed PHPs successfully installed!", 1) + def installSieve(self): + """Install Sieve (Dovecot Sieve) for email filtering on all OS variants""" + try: + InstallCyberPanel.stdOut("Installing Sieve (Dovecot Sieve) for email filtering...", 1) + + if self.distro == ubuntu: + # Install dovecot-sieve and dovecot-managesieved + self.install_package('dovecot-sieve dovecot-managesieved') + else: + # For CentOS/AlmaLinux/OpenEuler + self.install_package('dovecot-pigeonhole') + + # Add Sieve port 4190 to firewall + from plogical.firewallUtilities import FirewallUtilities + FirewallUtilities.addSieveFirewallRule() + + InstallCyberPanel.stdOut("Sieve successfully installed and configured!", 1) + return 1 + + except BaseException as msg: + logging.InstallLog.writeToFile('[ERROR] ' + str(msg) + " [installSieve]") + return 0 + def installMySQL(self, mysql): ############## Install mariadb ###################### @@ -487,6 +522,13 @@ gpgcheck=1 command = 'sudo dnf module reset mariadb -y' install_utils.call(command, self.distro, command, command, 1, 1, os.EX_OSERR, True) + # Disable problematic mariadb-maxscale repository to avoid 404 errors + command = 'dnf config-manager --disable mariadb-maxscale' + install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR, True) + + # Clear dnf cache to avoid repository issues + command = 'dnf clean all' + install_utils.call(command, self.distro, command, command, 1, 1, os.EX_OSERR, True) command = 'dnf install MariaDB-server MariaDB-client MariaDB-backup -y' @@ -505,9 +547,17 @@ gpgcheck=1 passwordCMD = "use mysql;DROP DATABASE IF EXISTS test;DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%%';GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '%s';flush privileges;" % ( InstallCyberPanel.mysql_Root_password) - command = 'mariadb -u root -e "' + passwordCMD + '"' - - install_utils.call(command, self.distro, command, command, 0, 0, os.EX_OSERR) + # For AlmaLinux 9, try mysql command first, then mariadb + if self.distro == cent8 or self.distro == openeuler: + command = 'mysql -u root -e "' + passwordCMD + '"' + result = install_utils.call(command, self.distro, command, command, 0, 0, os.EX_OSERR) + if result != 0: + # If mysql command fails, try mariadb + command = 'mariadb -u root -e "' + passwordCMD + '"' + install_utils.call(command, self.distro, command, command, 0, 0, os.EX_OSERR) + else: + command = 'mariadb -u root -e "' + passwordCMD + '"' + install_utils.call(command, self.distro, command, command, 0, 0, os.EX_OSERR) def startMariaDB(self): @@ -549,7 +599,14 @@ gpgcheck=1 except IOError as err: self.stdOut("[ERROR] Error in setting: " + fileName + ": " + str(err), 1, 1, os.EX_OSERR) - os.system('systemctl restart mariadb') + # Use the manage_service method for consistent service management + if self.distro == cent8 or self.distro == openeuler: + # Try mariadb first, then mysqld + result = os.system('systemctl restart mariadb') + if result != 0: + os.system('systemctl restart mysqld') + else: + os.system('systemctl restart mariadb') self.stdOut("MariaDB is now setup so it can support Cyberpanel's needs") @@ -956,6 +1013,9 @@ def Main(cwd, mysql, distro, ent, serial=None, port="8090", ftp=None, dns=None, if ent == 0: installer.fix_ols_configs() + logging.InstallLog.writeToFile('Installing Sieve for email filtering..,55') + installer.installSieve() + logging.InstallLog.writeToFile('Installing MySQL,60') installer.installMySQL(mysql) installer.changeMYSQLRootPassword() diff --git a/install/rainloop/cyberpanel.net.ini b/install/rainloop/cyberpanel.net.ini index 0f7022ca9..547ca79ef 100644 --- a/install/rainloop/cyberpanel.net.ini +++ b/install/rainloop/cyberpanel.net.ini @@ -2,9 +2,9 @@ imap_host = "localhost" imap_port = 993 imap_secure = "TLS" imap_short_login = Off -sieve_use = Off -sieve_allow_raw = Off -sieve_host = "" +sieve_use = On +sieve_allow_raw = On +sieve_host = "localhost" sieve_port = 4190 sieve_secure = "None" smtp_host = "localhost" diff --git a/mailServer/mailserverManager.py b/mailServer/mailserverManager.py index 0b367ae19..f65f2c452 100644 --- a/mailServer/mailserverManager.py +++ b/mailServer/mailserverManager.py @@ -1686,6 +1686,99 @@ milter_default_action = accept ### + def installSieveAfterReset(self): + """Reinstall and configure Sieve after email debugger reset""" + try: + from plogical.processUtilities import ProcessUtilities + + # Determine distribution + if ProcessUtilities.decideDistro() == ProcessUtilities.ubuntu: + # Install dovecot-sieve and dovecot-managesieved + command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install dovecot-sieve dovecot-managesieved' + ProcessUtilities.executioner(command) + else: + # For CentOS/AlmaLinux/OpenEuler + command = 'yum -y install dovecot-pigeonhole' + ProcessUtilities.executioner(command) + + # Add Sieve port 4190 to firewall + from plogical.firewallUtilities import FirewallUtilities + FirewallUtilities.addSieveFirewallRule() + + # Configure Sieve in dovecot + self.configureSieveInDovecot() + + logging.CyberCPLogFileWriter.writeToFile("Sieve reinstalled and configured after email reset") + return 1 + + except BaseException as msg: + logging.CyberCPLogFileWriter.writeToFile("Failed to reinstall Sieve after email reset: " + str(msg)) + return 0 + + def configureSieveInDovecot(self): + """Configure Sieve in Dovecot configuration""" + try: + # Enable Sieve plugin in dovecot + sieve_config = """ +# Sieve configuration +protocol lmtp { + mail_plugins = $mail_plugins sieve +} + +protocol lda { + mail_plugins = $mail_plugins sieve +} + +plugin { + sieve = file:~/sieve;active=~/.dovecot.sieve + sieve_global_path = /var/lib/dovecot/sieve/default.sieve + sieve_dir = ~/sieve + sieve_global_dir = /var/lib/dovecot/sieve/ + sieve_extensions = +notify +imapflags + sieve_max_script_size = 1M + sieve_quota_max_scripts = 0 + sieve_quota_max_storage = 0 +} + +service managesieve-login { + inet_listener sieve { + port = 4190 + } + inet_listener sieve_deprecated { + port = 2000 + } +} + +service managesieve { + process_limit = 1024 +} + +protocol sieve { + managesieve_max_line_length = 65536 + managesieve_implementation_string = dovecot + managesieve_logout_format = bytes ( in=%i, out=%o ) +} +""" + + # Write Sieve configuration to dovecot + config_path = "/etc/dovecot/conf.d/90-sieve.conf" + with open(config_path, 'w') as f: + f.write(sieve_config) + + # Create sieve directories + ProcessUtilities.executioner('mkdir -p /var/lib/dovecot/sieve') + ProcessUtilities.executioner('chown -R vmail:vmail /var/lib/dovecot/sieve') + + # Restart dovecot to apply changes + ProcessUtilities.executioner('systemctl restart dovecot') + + logging.CyberCPLogFileWriter.writeToFile("Sieve configured in Dovecot successfully") + return 1 + + except BaseException as msg: + logging.CyberCPLogFileWriter.writeToFile("Failed to configure Sieve in Dovecot: " + str(msg)) + return 0 + def ResetEmailConfigurations(self): try: ### Check if remote or local mysql @@ -1727,6 +1820,10 @@ milter_default_action = accept if self.install_postfix_dovecot() == 0: return 0 + # Ensure Sieve remains functional after email debugger reset + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Reinstalling Sieve after email reset..,45') + self.installSieveAfterReset() + logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Resetting configurations..,40') import sys diff --git a/mailServer/templates/mailServer/listEmails.html b/mailServer/templates/mailServer/listEmails.html index 37051f431..c2b0bdb73 100644 --- a/mailServer/templates/mailServer/listEmails.html +++ b/mailServer/templates/mailServer/listEmails.html @@ -689,6 +689,32 @@ + +
| {% trans "Sieve Settings" %} | +|
|---|---|
| {% trans "Server" %} | +{$ serverHostname $} | +
| {% trans "Port" %} | +4190 | +
| {% trans "Security" %} | +None (Plain) | +
| {% trans "Purpose" %} | +Email Filtering | +