mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-12-16 05:19:43 +01:00
Fix custom installation email components bug: Skip email operations when services not installed
This commit resolves the issue where CyberPanel attempts to configure email/DKIM settings even when email services were explicitly disabled during custom installation, causing hostname SSL setup and website creation to fail with "No such file or directory: '/etc/postfix/main.cf'" errors. Changes: - Added emailServicesInstalled() utility function to check for /home/cyberpanel/postfix marker - OnBoardingHostName(): Wrap email operations (issueSSLForMailServer, postfix commands) with checks - OnBoardingHostName(): Allow hostname setup to complete without email services - issueSSLForMailServer(): Add early return if email services not installed - issueSSLForMailServer(): Verify /etc/postfix directory exists before operations - issueSSLForMailServer(): Check /etc/postfix/main.cf exists before reading - setupAutoDiscover(): Add early return if email services not installed - setupAutoDiscover(): Check /etc/postfix/main.cf exists before accessing - mailUtilities.configureOpenDKIM(): Verify main.cf exists before configuration Impact: - Hostname SSL setup now completes successfully without email components - Website creation works correctly on custom installs without email - No more file not found errors for /etc/postfix/main.cf - Graceful degradation: operations skip email setup with log messages Fixes: Custom installation hostname SSL 404 error Fixes: Website creation DKIM failure on custom installs Related: Ticket #RMKRFFGKC
This commit is contained in:
@@ -582,6 +582,12 @@ InternalHosts refile:/etc/opendkim/TrustedHosts
|
|||||||
|
|
||||||
postfixFilePath = "/etc/postfix/main.cf"
|
postfixFilePath = "/etc/postfix/main.cf"
|
||||||
|
|
||||||
|
# Check if postfix main.cf exists before configuring
|
||||||
|
if not os.path.exists(postfixFilePath):
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"configureOpenDKIM: {postfixFilePath} not found, skipping postfix DKIM configuration")
|
||||||
|
print("1,Postfix not installed")
|
||||||
|
return
|
||||||
|
|
||||||
configData = """
|
configData = """
|
||||||
smtpd_milters = inet:127.0.0.1:8891
|
smtpd_milters = inet:127.0.0.1:8891
|
||||||
non_smtpd_milters = $smtpd_milters
|
non_smtpd_milters = $smtpd_milters
|
||||||
|
|||||||
@@ -53,7 +53,16 @@ class virtualHostUtilities:
|
|||||||
redisConf = '/usr/local/lsws/conf/dvhost_redis.conf'
|
redisConf = '/usr/local/lsws/conf/dvhost_redis.conf'
|
||||||
vhostConfPath = '/usr/local/lsws/conf'
|
vhostConfPath = '/usr/local/lsws/conf'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def emailServicesInstalled():
|
||||||
|
"""
|
||||||
|
Check if email services (Postfix/OpenDKIM) are installed and configured.
|
||||||
|
Returns True if email services are available, False otherwise.
|
||||||
|
|
||||||
|
This checks for the marker file /home/cyberpanel/postfix which is created
|
||||||
|
during email services installation.
|
||||||
|
"""
|
||||||
|
return os.path.exists('/home/cyberpanel/postfix')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def OnBoardingHostName(Domain, tempStatusPath, skipRDNSCheck):
|
def OnBoardingHostName(Domain, tempStatusPath, skipRDNSCheck):
|
||||||
@@ -82,29 +91,33 @@ class virtualHostUtilities:
|
|||||||
except:
|
except:
|
||||||
CurrentHostName = ''
|
CurrentHostName = ''
|
||||||
|
|
||||||
if skipRDNSCheck:
|
# Check if email services are installed
|
||||||
pass
|
# If not installed and rDNS check is required, log warning but continue
|
||||||
else:
|
# Email-specific operations will be skipped later
|
||||||
if os.path.exists('/home/cyberpanel/postfix'):
|
emailServicesAvailable = virtualHostUtilities.emailServicesInstalled()
|
||||||
pass
|
|
||||||
else:
|
if not skipRDNSCheck and not emailServicesAvailable:
|
||||||
message = 'This server does not come with postfix installed. [404]'
|
message = 'Email services not installed. Hostname setup will continue without email configuration.'
|
||||||
print(message)
|
print(message)
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
||||||
logging.CyberCPLogFileWriter.writeToFile(message)
|
logging.CyberCPLogFileWriter.writeToFile(message)
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
# Get postfix hostname with error handling
|
# Get postfix hostname with error handling (only if email services are installed)
|
||||||
try:
|
PostFixHostname = None
|
||||||
PostFixHostname = mailUtilities.FetchPostfixHostname()
|
if emailServicesAvailable:
|
||||||
except Exception as e:
|
try:
|
||||||
message = f'Failed to fetch postfix hostname: {str(e)} [404]'
|
PostFixHostname = mailUtilities.FetchPostfixHostname()
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
except Exception as e:
|
||||||
logging.CyberCPLogFileWriter.writeToFile(message)
|
message = f'Failed to fetch postfix hostname: {str(e)}, continuing without email setup'
|
||||||
return 0
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(message)
|
||||||
|
emailServicesAvailable = False # Disable email operations if we can't fetch postfix hostname
|
||||||
|
else:
|
||||||
|
# Set a default hostname when email services are not available
|
||||||
|
PostFixHostname = Domain
|
||||||
|
|
||||||
# Get server IP with error handling
|
# Get server IP with error handling
|
||||||
try:
|
try:
|
||||||
@@ -391,51 +404,66 @@ class virtualHostUtilities:
|
|||||||
|
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Hostname SSL issued,50')
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Hostname SSL issued,50')
|
||||||
|
|
||||||
|
# Only setup mail server SSL if email services are installed
|
||||||
|
if emailServicesAvailable:
|
||||||
|
virtualHostUtilities.issueSSLForMailServer(Domain, path)
|
||||||
|
|
||||||
virtualHostUtilities.issueSSLForMailServer(Domain, path)
|
try:
|
||||||
|
with open(filePath, 'r') as f:
|
||||||
|
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
|
||||||
|
|
||||||
try:
|
# Safely extract SSL provider from issuer components
|
||||||
with open(filePath, 'r') as f:
|
issuer_components = x509.get_issuer().get_components()
|
||||||
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
|
SSLProvider = 'Denial' # Default to Denial if we can't find the provider
|
||||||
|
|
||||||
# Safely extract SSL provider from issuer components
|
|
||||||
issuer_components = x509.get_issuer().get_components()
|
|
||||||
SSLProvider = 'Denial' # Default to Denial if we can't find the provider
|
|
||||||
|
|
||||||
# Look for the Organization (O) field in the issuer
|
|
||||||
for component in issuer_components:
|
|
||||||
if component[0] == b'O': # Organization field
|
|
||||||
SSLProvider = component[1].decode('utf-8')
|
|
||||||
break
|
|
||||||
elif component[0] == b'CN' and SSLProvider == 'Denial': # Fallback to CN if O not found
|
|
||||||
SSLProvider = component[1].decode('utf-8')
|
|
||||||
except (FileNotFoundError, IndexError, OpenSSL.crypto.Error) as e:
|
|
||||||
SSLProvider = 'Denial'
|
|
||||||
logging.CyberCPLogFileWriter.writeToFile(f"Mail server SSL check error: {str(e)}")
|
|
||||||
|
|
||||||
if SSLProvider == 'Denial':
|
# Look for the Organization (O) field in the issuer
|
||||||
message = 'Failed to issue Mail server SSL, either its DNS record is not propagated or the domain is behind Cloudflare. [404]'
|
for component in issuer_components:
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
if component[0] == b'O': # Organization field
|
||||||
logging.CyberCPLogFileWriter.writeToFile(message)
|
SSLProvider = component[1].decode('utf-8')
|
||||||
config['hostname'] = Domain
|
break
|
||||||
config['onboarding'] = 3
|
elif component[0] == b'CN' and SSLProvider == 'Denial': # Fallback to CN if O not found
|
||||||
config['skipRDNSCheck'] = skipRDNSCheck
|
SSLProvider = component[1].decode('utf-8')
|
||||||
admin.config = json.dumps(config)
|
except (FileNotFoundError, IndexError, OpenSSL.crypto.Error) as e:
|
||||||
admin.save()
|
SSLProvider = 'Denial'
|
||||||
return 0
|
logging.CyberCPLogFileWriter.writeToFile(f"Mail server SSL check error: {str(e)}")
|
||||||
|
|
||||||
|
if SSLProvider == 'Denial':
|
||||||
|
message = 'Failed to issue Mail server SSL, either its DNS record is not propagated or the domain is behind Cloudflare. [404]'
|
||||||
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, message)
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(message)
|
||||||
|
config['hostname'] = Domain
|
||||||
|
config['onboarding'] = 3
|
||||||
|
config['skipRDNSCheck'] = skipRDNSCheck
|
||||||
|
admin.config = json.dumps(config)
|
||||||
|
admin.save()
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
config['hostname'] = Domain
|
||||||
|
config['onboarding'] = 1
|
||||||
|
config['skipRDNSCheck'] = skipRDNSCheck
|
||||||
|
admin.config = json.dumps(config)
|
||||||
|
admin.save()
|
||||||
|
# First update the postfix hash database, then restart services
|
||||||
|
command = 'postmap -F hash:/etc/postfix/vmail_ssl.map && systemctl restart postfix && systemctl restart dovecot'
|
||||||
|
ProcessUtilities.executioner(command, 'root', True)
|
||||||
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Completed. [200]')
|
||||||
else:
|
else:
|
||||||
|
# Email services not installed, skip mail server SSL setup
|
||||||
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Email services not installed, skipping mail server SSL setup.')
|
||||||
config['hostname'] = Domain
|
config['hostname'] = Domain
|
||||||
config['onboarding'] = 1
|
config['onboarding'] = 1
|
||||||
config['skipRDNSCheck'] = skipRDNSCheck
|
config['skipRDNSCheck'] = skipRDNSCheck
|
||||||
admin.config = json.dumps(config)
|
admin.config = json.dumps(config)
|
||||||
admin.save()
|
admin.save()
|
||||||
# First update the postfix hash database, then restart services
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Hostname setup completed (without email configuration). [200]')
|
||||||
command = 'postmap -F hash:/etc/postfix/vmail_ssl.map && systemctl restart postfix && systemctl restart dovecot'
|
|
||||||
ProcessUtilities.executioner(command, 'root', True)
|
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Completed. [200]')
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setupAutoDiscover(mailDomain, tempStatusPath, virtualHostName, admin):
|
def setupAutoDiscover(mailDomain, tempStatusPath, virtualHostName, admin):
|
||||||
|
# Check if email services are installed before proceeding
|
||||||
|
if not virtualHostUtilities.emailServicesInstalled():
|
||||||
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Email services not installed, skipping mail domain setup.')
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile('setupAutoDiscover: Email services not installed, skipping.')
|
||||||
|
return
|
||||||
|
|
||||||
if mailDomain:
|
if mailDomain:
|
||||||
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Creating mail child domain..,80')
|
logging.CyberCPLogFileWriter.statusWriter(tempStatusPath, 'Creating mail child domain..,80')
|
||||||
@@ -479,6 +507,11 @@ local_name %s {
|
|||||||
|
|
||||||
postFixPath = '/etc/postfix/main.cf'
|
postFixPath = '/etc/postfix/main.cf'
|
||||||
|
|
||||||
|
# Check if main.cf exists before accessing it
|
||||||
|
if not os.path.exists(postFixPath):
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"setupAutoDiscover: {postFixPath} not found, skipping postfix TLS SNI configuration")
|
||||||
|
return
|
||||||
|
|
||||||
postFixContent = open(postFixPath, 'r').read()
|
postFixContent = open(postFixPath, 'r').read()
|
||||||
|
|
||||||
if postFixContent.find('tls_server_sni_maps') == -1:
|
if postFixContent.find('tls_server_sni_maps') == -1:
|
||||||
@@ -1108,6 +1141,17 @@ local_name %s {
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def issueSSLForMailServer(virtualHost, path):
|
def issueSSLForMailServer(virtualHost, path):
|
||||||
try:
|
try:
|
||||||
|
# Check if email services are installed before proceeding
|
||||||
|
if not virtualHostUtilities.emailServicesInstalled():
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile("Email services not installed, skipping mail server SSL setup")
|
||||||
|
print("1,Email services not installed")
|
||||||
|
return 1, 'Email services not installed'
|
||||||
|
|
||||||
|
# Verify critical email directories exist
|
||||||
|
if not os.path.exists('/etc/postfix'):
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile("/etc/postfix directory not found, skipping mail server SSL")
|
||||||
|
print("1,Postfix directory not found")
|
||||||
|
return 1, 'Postfix directory not found'
|
||||||
|
|
||||||
srcFullChain = '/etc/letsencrypt/live/' + virtualHost + '/fullchain.pem'
|
srcFullChain = '/etc/letsencrypt/live/' + virtualHost + '/fullchain.pem'
|
||||||
srcPrivKey = '/etc/letsencrypt/live/' + virtualHost + '/privkey.pem'
|
srcPrivKey = '/etc/letsencrypt/live/' + virtualHost + '/privkey.pem'
|
||||||
@@ -1183,6 +1227,12 @@ local_name %s {
|
|||||||
|
|
||||||
filePath = "/etc/postfix/main.cf"
|
filePath = "/etc/postfix/main.cf"
|
||||||
|
|
||||||
|
# Check if main.cf exists before trying to read it
|
||||||
|
if not os.path.exists(filePath):
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"{filePath} not found, skipping postfix hostname update")
|
||||||
|
print("1,Postfix main.cf not found")
|
||||||
|
return 1, 'Postfix main.cf not found'
|
||||||
|
|
||||||
data = open(filePath, 'r').readlines()
|
data = open(filePath, 'r').readlines()
|
||||||
|
|
||||||
writeFile = open(filePath, 'w')
|
writeFile = open(filePath, 'w')
|
||||||
|
|||||||
Reference in New Issue
Block a user