diff --git a/install/installCyberPanel.py b/install/installCyberPanel.py index 9a88dc664..6f39a6788 100644 --- a/install/installCyberPanel.py +++ b/install/installCyberPanel.py @@ -380,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 ###################### @@ -990,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
diff --git a/plogical/firewallUtilities.py b/plogical/firewallUtilities.py index 1c53d2609..9e96b4205 100644 --- a/plogical/firewallUtilities.py +++ b/plogical/firewallUtilities.py @@ -67,6 +67,18 @@ class FirewallUtilities: return 1 + @staticmethod + def addSieveFirewallRule(): + """Add Sieve port 4190 to firewall for all OS variants""" + try: + # Add Sieve port 4190 to firewall + FirewallUtilities.addRule('tcp', '4190', '0.0.0.0/0') + logging.CyberCPLogFileWriter.writeToFile("Sieve port 4190 added to firewall successfully") + return 1 + except BaseException as msg: + logging.CyberCPLogFileWriter.writeToFile("Failed to add Sieve port 4190 to firewall: " + str(msg)) + return 0 + @staticmethod def deleteRule(proto, port, ipAddress): ruleFamily = 'rule family="ipv4"' diff --git a/plogical/mailUtilities.py b/plogical/mailUtilities.py index 2ecb14f64..8f7bae67c 100644 --- a/plogical/mailUtilities.py +++ b/plogical/mailUtilities.py @@ -125,7 +125,7 @@ class mailUtilities: "authPlainLine": false }, "Sieve": { - "host": "", + "host": "localhost", "port": 4190, "type": 0, "timeout": 10,