- Fix apiSSO() resetting selected account to first one on every call,
now preserves previously selected account if still valid
- Fix webmail.conf ownership to use cyberpanel:cyberpanel (Django runs
as cyberpanel user, not nobody)
- Add error notifications when SSO or folder loading fails
Adds master passdb config to dovecot.conf templates, setupWebmail() to
the installer and upgrade paths to generate credentials and create
/etc/dovecot/master-users and /etc/cyberpanel/webmail.conf automatically.
The upgrade path is idempotent and patches existing dovecot.conf if needed.
- Use correct Dovecot namespace (separator='.', prefix='INBOX.'):
folders are INBOX.Sent, INBOX.Drafts, INBOX.Deleted Items, etc.
- Quote IMAP folder names with spaces (e.g. "INBOX.Deleted Items")
- Add display_name and folder_type to folder list API response
- Fix SMTP for SSO: use local relay on port 25 (permit_mynetworks)
since Dovecot has no auth_master_user_separator for port 587
- Fix Sieve SASL PLAIN auth to use clean RFC 4616 format
- Handle ManageSieve unavailability gracefully with helpful logging
- Update frontend to show clean folder names and correct icons
- Auto-prefix new folder names with INBOX. namespace
Replace SnappyMail link with a custom Django webmail app that provides:
- Full IMAP/SMTP integration (Dovecot + Postfix) with master user SSO
- 3-column responsive UI matching CyberPanel design system
- Compose with rich text editor, attachments, reply/forward
- Contact management with auto-collect from sent messages
- Sieve mail filter rules with ManageSieve protocol support
- Standalone login page for direct webmail access
- Account switcher for admins managing multiple email accounts
- HTML email sanitization (whitelist-based, external image proxy)
- Draft auto-save and per-user settings
Rebuilt module fixes NULL pointer dereference in apply_headers() when
OLS generates error responses (4xx/5xx). The get_req_var_by_id() call
for DOC_ROOT crashed because request variables aren't initialized
during error response generation. Fix adds status code guard to skip
header processing for error responses.
- Add get_ssh_port() to read Port from /etc/ssh/sshd_config
- Use 127.0.0.1 and port=SSH_PORT in asyncssh.connect()
- Web Terminal now works when SSH runs on non-22 port
Add fallback gradient and !important color for btn-primary when
--bg-gradient is undefined (e.g. dark mode/base theme), so the Save
button is always visible instead of appearing white/invisible.
Expand mail-domain detection so proxy stays off for:
mail., smtp., imap., pop3., pop., autodiscover., webmail.
(and subdomains containing these). Other A/AAAA/CNAME get proxied by default.
- Return (success, error_msg) from createNONSSLMapEntry instead of 0/1
- Fix logging: use CyberCPLogFileWriter.writeToFile instead of writeToFile
- Match listener block case-insensitively (listener Default / listener default)
- Raise clear ValueError if Default listener block not found in httpd_config.conf
- Propagate actual error messages in createConfigInMainVirtualHostFile and createConfigInMainDomainHostFile
- dnsManager.fixDNSRecordsCloudFlare: track existing_types_by_name;
skip adding A/AAAA when hostname has CNAME (A/AAAA cannot coexist
with CNAME). Clearer docstring.
- dnsUtilities: comment tweak for proxy-capable record types.
- settings.py: read DB password from /etc/cyberpanel/mysqlPassword
when present so panel stays in sync with CLI/install scripts.
- dnsManager.py: include AAAA in record types that get proxied flag on
update (was only A, CNAME); fix HTTP 500 by hardening loadCFKeys and
addDeleteDNSRecordsCloudFlare (safe file read, always pass
domainsList/cfEmail/cfToken to template).
- dnsUtilities.py: A, AAAA and CNAME can be proxied in Cloudflare;
set proxied only for those types; MX, TXT, etc. cannot be proxied.
- Bug: filtering on '::1' in line incorrectly excluded addresses like
2a02:c206:2238:7806::1, so fixDNS() never created AAAA records.
- Fix: use ipaddress.ip_address() and is_loopback/is_link_local so
only actual loopback (::1) and link-local (fe80::) are excluded.
- GetServerIPv6() now returns correct global IPv6 for DNS AAAA records.
- Delete record: confirmation dialog and local backup before delete
- Clear all DNS records: double confirmation (zone name), local backup, Restore button
- Export/Import DNS records (JSON) for zone
- Check orphan DNS: find A/AAAA/CNAME for hostnames no longer in panel, remove with backup
- Backend: getExportRecordsCloudFlare, clearAllDNSRecordsCloudFlare, importDNSRecordsCloudFlare, getStaleDNSRecordsCloudFlare, removeStaleDNSRecordsCloudFlare
- CyberCP/urls.py: when emailMarketing app is missing/broken, register placeholder path with name='emailMarketing' so {% url 'emailMarketing' %} never raises Reverse not found.
- public/static/baseTemplate/custom-js/system-status.js: replace old copy with full system-status.js that registers dashboardStatsController and systemStatusInfo (fixes Angular [:ctrlreg] and raw {{$ cpuUsage $}} on overview).
- Fix 1: Parse -b/--branch and --mariadb-version with while-loop so only next token is used
(avoids Branch_Name becoming 'v2.5.5-dev --mariadb-version 12.3')
- Fix 2: Default Git_User to master3395 in Pre_Upgrade_Setup_Git_URL (04_git_url, monolithic)
- Fix 3: upgrade.py uses CYBERPANEL_GIT_USER for git clone (default master3395);
export CYBERPANEL_GIT_USER before upgrade.py in 08_main_upgrade and monolithic
- Fix 4: --mariadb-version already supported in 05_repository.sh (MARIADB_VER_REPO)
- firewallUtilities: add closeConnectionsFromIP() using conntrack -D -s IP
- addBannedIP: when IP already banned, close connections and return success message
- Frontend: always call API on Ban IP so backend can close connections; show server message
- Install: add conntrack-tools (RHEL) / conntrack (Debian/Ubuntu) to all install paths
(rhel_deps, debian_deps, install_modules/01_verify_deps, install.py, venvsetup)
- Add updateDNSRecordCloudFlare backend (dnsManager, view, URL)
- Return real priority in getCurrentRecordsForDomainCloudFlare
- Edit (pencil) button + modal with all fields; Save calls update API
- openEditModal, closeEditModal, saveEditRecord in dns.js
modifyWebsite.html uses | filesize for home directory available_space;
filter was missing, causing $injector/unpr FilesizeFilterProvider.
Register app.filter('filesize') with array annotation in all websiteFunctions.js copies.