Files
CyberPanel/webmail/services/smtp_client.py
usmannasir 72f33d3bcd Add integrated webmail client with SSO, contacts, and Sieve rules
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
2026-03-05 02:49:00 +05:00

56 lines
2.1 KiB
Python

import smtplib
import ssl
class SMTPClient:
"""Wrapper around smtplib.SMTP for sending mail via Postfix."""
def __init__(self, email_address, password, host='localhost', port=587):
self.email_address = email_address
self.password = password
self.host = host
self.port = port
def send_message(self, mime_message):
"""Send a composed email.message.EmailMessage via SMTP with STARTTLS.
Returns:
dict: {success: bool, message_id: str or None, error: str or None}
"""
try:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
smtp = smtplib.SMTP(self.host, self.port)
smtp.ehlo()
smtp.starttls(context=ctx)
smtp.ehlo()
smtp.login(self.email_address, self.password)
smtp.send_message(mime_message)
smtp.quit()
message_id = mime_message.get('Message-ID', '')
return {'success': True, 'message_id': message_id}
except smtplib.SMTPAuthenticationError as e:
return {'success': False, 'message_id': None, 'error': 'Authentication failed: %s' % str(e)}
except smtplib.SMTPRecipientsRefused as e:
return {'success': False, 'message_id': None, 'error': 'Recipients refused: %s' % str(e)}
except Exception as e:
return {'success': False, 'message_id': None, 'error': str(e)}
def save_to_sent(self, imap_client, raw_message):
"""Append sent message to the Sent folder via IMAP."""
sent_folders = ['Sent', 'INBOX.Sent', 'Sent Messages', 'Sent Items']
for folder in sent_folders:
try:
if imap_client.append_message(folder, raw_message, '\\Seen'):
return True
except Exception:
continue
try:
imap_client.create_folder('Sent')
return imap_client.append_message('Sent', raw_message, '\\Seen')
except Exception:
return False