$15 GRAYBYTE WORDPRESS FILE MANAGER $12

SERVER : vnpttt-amd7f72-h1.vietnix.vn #1 SMP Fri May 24 12:42:50 UTC 2024
SERVER IP : 103.200.23.149 | ADMIN IP 216.73.216.22
OPTIONS : CRL = ON | WGT = ON | SDO = OFF | PKEX = OFF
DEACTIVATED : NONE

/opt/cloudlinux/venv/lib/python3.11/site-packages/xray/continuous/

HOME
Current File : /opt/cloudlinux/venv/lib/python3.11/site-packages/xray/continuous//mailer.py
# -*- coding: utf-8 -*-

# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

import logging
import os
import smtplib
import subprocess
from configparser import ConfigParser, SectionProxy
from email.message import EmailMessage
from socket import gethostname
from typing import Optional

from xray import gettext as _
from ..internal.constants import mail_template_location, mail_scripts_location
from ..internal.exceptions import XRayMailerError


class Mailer:
    """
    Class contains X-Ray e-mail send logic
    """
    def __init__(self):
        self.logger = logging.getLogger('mailer')
        self._sender = None

    @property
    def mail_server(self) -> tuple:
        """
        Local mail server address
        """
        return ('localhost', )

    @property
    def sender(self) -> str:
        """
        Retrieve 'From' mail address if it is not already set
        """
        if self._sender is None:
            self._sender = self.retrieve_mail_sender()
        return self._sender

    def retrieve_mail_sender(self) -> str:
        """
        'From' address (control panel admin or dummy one)
        """
        dummy_mail = f"xray.continuous@{gethostname()}"
        admin_mail = self.admin_email()
        return admin_mail if admin_mail is not None else dummy_mail

    def admin_email(self) -> Optional[str]:
        """
        Try to retrieve control panel admin e-mail
        """
        panel = self.get_control_panel()
        if panel is not None:
            get_email_script = f'{mail_scripts_location}/{panel}_email'
            try:
                p = subprocess.run([get_email_script],
                                   capture_output=True, text=True, check=True)
                return p.stdout.strip()
            except subprocess.CalledProcessError as e:
                self.logger.error('% script failed with: %s',
                                  get_email_script, str(e))
            except (OSError, ValueError, subprocess.SubprocessError) as e:
                self.logger.error('Failed to run script %s with: %s',
                                  get_email_script, str(e))

    def get_control_panel(self) -> Optional[str]:
        """
        Get control panel name
        """
        try:
            return subprocess.run(
                ['cldetect', '--detect-cp-name'],
                check=True, text=True,
                capture_output=True).stdout.strip()
        except (subprocess.CalledProcessError, AttributeError) as e:
            self.logger.error('cldetect utility failed with %s',
                              str(e))
        except (OSError, ValueError, subprocess.SubprocessError) as e:
            self.logger.error('Failed to run cldetect utility with %s',
                              str(e))

    @staticmethod
    def read_template(name: str = 'greeting') -> SectionProxy:
        """
        Get preformatted data for e-mail by name of template
        """
        tmpl = f'{mail_template_location}/{name}.ini'
        if os.path.exists(tmpl):
            config = ConfigParser(interpolation=None)
            config.read(tmpl)
            return config['data']
        raise XRayMailerError(_('Failed to find template {} in {}'.format(name, mail_template_location)))

    def _smtp_send(self, message: EmailMessage) -> None:
        """
        Send preformatted e-mail via localhost SMTP
        """
        self.logger.info('Try to send via smtp')
        try:
            with smtplib.SMTP(*self.mail_server) as server:
                result = server.send_message(message)
                self.logger.info('Send result: %s', result)
        except smtplib.SMTPException as e:
            raise XRayMailerError(f'smtp mailing failed: {str(e)}')
        except (ConnectionError, OSError) as e:
            raise XRayMailerError(_('smtp connection failed: %s') % str(e))

    def _console_send(self, message: EmailMessage) -> None:
        """
        Send preformatted e-mail via sendmail utility
        """
        self.logger.info('Try to send via sendmail utility')
        cmd = ["/usr/sbin/sendmail", "-t", "-oi"]
        try:
            subprocess.run(cmd,
                           input=message.as_string(),
                           capture_output=True,
                           text=True, check=True)
        except (OSError, subprocess.CalledProcessError) as e:
            raise XRayMailerError(_('sendmail utility failed with %s') % str(e))

    def _send(self, mail: EmailMessage) -> None:
        """
        Try to send mail via localhost smtp server,
        if fails -- try to use sendmail utility
        """
        try:
            self._smtp_send(mail)
        except XRayMailerError as e:
            self.logger.error(str(e))
            try:
                self._console_send(mail)
            except XRayMailerError as e:
                self.logger.error(str(e))
                self.logger.critical(
                    'Both smtp and sendmail failed to send message to %s',
                    mail['To'])

    def send_mail(self,
                  recipient: str,
                  template: str = 'greeting',
                  **kwargs) -> None:
        data = self.read_template(template)

        msg = EmailMessage()
        msg['Subject'] = data['subject']
        msg['From'] = self.sender
        msg['To'] = recipient
        msg.set_content(data['text'] % kwargs)
        msg.add_alternative(data['html'] % kwargs, subtype='html')

        self.logger.info('Generated mail --> %s', msg.as_string())

        self._send(msg)

Current_dir [ NOT WRITEABLE ] Document_root [ WRITEABLE ]


[ Back ]
NAME
SIZE
LAST TOUCH
USER
CAN-I?
FUNCTIONS
..
--
16 Dec 2025 9.31 PM
root / root
0755
__pycache__
--
17 Dec 2025 12.00 AM
root / root
0755
__init__.py
0 KB
20 Oct 2025 7.04 PM
root / root
0644
common.py
2.755 KB
20 Oct 2025 7.04 PM
root / root
0644
mailer.py
5.561 KB
20 Oct 2025 7.04 PM
root / root
0644
manager.py
3.311 KB
20 Oct 2025 7.04 PM
root / root
0644
tracing.py
5.814 KB
20 Oct 2025 7.04 PM
root / root
0644

GRAYBYTE WORDPRESS FILE MANAGER @ 2026 CONTACT ME
Static GIF