Renamed project

This commit is contained in:
2021-08-05 14:17:38 +02:00
parent 308e5c9b0c
commit 11241d8f99
63 changed files with 59 additions and 59 deletions

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
"""
sh_cpl-core sh-edraft Common Python library
~~~~~~~~~~~~~~~~~~~
sh-edraft Common Python library
:copyright: (c) 2020 - 2021 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'cpl_core.mailing'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de'
__version__ = '2021.10.6'
from collections import namedtuple
# imports:
from .email import EMail
from .email_client_service import EMailClient
from .email_client_abc import EMailClientABC
from .email_client_settings import EMailClientSettings
from .email_client_settings_name_enum import EMailClientSettingsNameEnum
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='2021', minor='10', micro='6')

View File

@@ -0,0 +1,140 @@
import re
class EMail:
r"""Represents an email
Parameter
---------
header: list[:class:`str`]
Header of the E-Mail
subject: :class:`str`
Subject of the E-Mail
body: :class:`str`
Body of the E-Mail
transceiver: :class:`str`
Transceiver of the E-Mail
receiver: list[:class:`str`]
Receiver of the E-Mail
"""
def __init__(self, header: list[str] = None, subject: str = None, body: str = None, transceiver: str = None,
receiver: list[str] = None):
self._header: list[str] = header
self._subject: str = subject
self._body: str = body
self._transceiver: str = transceiver
self._receiver: list[str] = receiver
@property
def header(self) -> str:
return '\r\n'.join(self._header)
@property
def header_list(self) -> list[str]:
return self._header
@header.setter
def header(self, header: list[str]):
self._header = header
@property
def subject(self) -> str:
return self._subject
@subject.setter
def subject(self, subject: str):
self._subject = subject
@property
def body(self) -> str:
return self._body
@body.setter
def body(self, body: str):
self._body = body
@property
def transceiver(self) -> str:
return self._transceiver
@transceiver.setter
def transceiver(self, transceiver: str):
if self.check_mail(transceiver):
self._transceiver = transceiver
else:
raise Exception(f'Invalid email: {transceiver}')
@property
def receiver(self) -> str:
return ','.join(self._receiver)
@property
def receiver_list(self) -> list[str]:
return self._receiver
@receiver.setter
def receiver(self, receiver: list[str]):
self._receiver = receiver
@staticmethod
def check_mail(address: str) -> bool:
r"""Checks if an email is valid
Parameter
---------
address: :class:`str`
The address to check
Returns
-------
Result if E-Mail is valid or not
"""
return bool(re.search('^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(.\\w{2,3})+$', address))
def add_header(self, header: str):
r"""Adds header
Parameter
---------
header: :class:`str`
The header of the E-Mail
"""
if self._header is None:
self._header = []
self._header.append(header)
def add_receiver(self, receiver: str):
r"""Adds receiver
Parameter
---------
receiver: :class:`str`
The receiver of the E-Mail
"""
if self._receiver is None:
self._receiver = []
if self.check_mail(receiver):
self._receiver.append(receiver)
else:
raise Exception(f'Invalid email: {receiver}')
def get_content(self, transceiver: str):
r"""Returns the mail as string
Parameter
---------
transceiver: :class:`str`
The transceiver of the E-Mail
Returns
-------
E-Mail as string
"""
return str(
f'From: {transceiver}\r\nTo: {self.receiver}\r\n{self.header}\r\nSubject: {self.subject}\r\n{self.body}').encode(
'utf-8')

View File

@@ -0,0 +1,27 @@
from abc import abstractmethod, ABC
from cpl.mailing.email import EMail
class EMailClientABC(ABC):
"""ABC of :class:`cpl.mailing.email_client_service.EMailClient`"""
@abstractmethod
def __init__(self):
ABC.__init__(self)
@abstractmethod
def connect(self):
r"""Connects to server"""
pass
@abstractmethod
def send_mail(self, email: EMail):
r"""Sends email
Parameter
---------
email: :class:`cpl.mailing.email.EMail`
Object of the E-Mail to send
"""
pass

View File

@@ -0,0 +1,83 @@
import ssl
from smtplib import SMTP
from typing import Optional
from cpl.environment.application_environment_abc import ApplicationEnvironmentABC
from cpl.logging.logger_abc import LoggerABC
from cpl.mailing.email import EMail
from cpl.mailing.email_client_abc import EMailClientABC
from cpl.mailing.email_client_settings import EMailClientSettings
from cpl.utils.credential_manager import CredentialManager
class EMailClient(EMailClientABC):
r"""Service to send emails
Parameter
---------
environment: :class:`cpl.environment.application_environment_abc.ApplicationEnvironmentABC`
Environment of the application
logger: :class:`cpl.logging.logger_abc.LoggerABC`
The logger to use
mail_settings: :class:`cpl.mailing.email_client_settings.EMailClientSettings`
Settings for mailing
"""
def __init__(self, environment: ApplicationEnvironmentABC, logger: LoggerABC, mail_settings: EMailClientSettings):
EMailClientABC.__init__(self)
self._environment = environment
self._mail_settings = mail_settings
self._logger = logger
self._server: Optional[SMTP] = None
self.create()
def create(self):
r"""Creates connection"""
self._logger.trace(__name__, f'Started {__name__}.create')
self.connect()
self._logger.trace(__name__, f'Stopped {__name__}.create')
def connect(self):
self._logger.trace(__name__, f'Started {__name__}.connect')
try:
self._logger.debug(__name__, f'Try to connect to {self._mail_settings.host}:{self._mail_settings.port}')
self._server = SMTP(self._mail_settings.host, self._mail_settings.port)
self._logger.info(__name__, f'Connected to {self._mail_settings.host}:{self._mail_settings.port}')
self._logger.debug(__name__, 'Try to start tls')
self._server.starttls(context=ssl.create_default_context())
self._logger.info(__name__, 'Started tls')
except Exception as e:
self._logger.error(__name__, 'Cannot connect to mail server', e)
self._logger.trace(__name__, f'Stopped {__name__}.connect')
def login(self):
r"""Login to server"""
self._logger.trace(__name__, f'Started {__name__}.login')
try:
self._logger.debug(__name__, f'Try to login {self._mail_settings.user_name}@{self._mail_settings.host}:{self._mail_settings.port}')
self._server.login(self._mail_settings.user_name, CredentialManager.decrypt(self._mail_settings.credentials))
self._logger.info(__name__, f'Logged on as {self._mail_settings.user_name} to {self._mail_settings.host}:{self._mail_settings.port}')
except Exception as e:
self._logger.error(__name__, 'Cannot login to mail server', e)
self._logger.trace(__name__, f'Stopped {__name__}.login')
def send_mail(self, email: EMail):
self._logger.trace(__name__, f'Started {__name__}.send_mail')
try:
self.login()
email.body += f'\n\nDies ist eine automatische E-Mail.' \
f'\nGesendet von {self._environment.application_name}-{self._environment.environment_name}@{self._environment.host_name} für ' \
f'{self._environment.customer}.'
self._logger.debug(__name__, f'Try to send email to {email.receiver_list}')
self._server.sendmail(self._mail_settings.user_name, email.receiver_list, email.get_content(self._mail_settings.user_name))
self._logger.info(__name__, f'Sent email to {email.receiver_list}')
except Exception as e:
self._logger.error(__name__, f'Cannot send mail to {email.receiver_list}', e)
self._logger.trace(__name__, f'Stopped {__name__}.send_mail')

View File

@@ -0,0 +1,60 @@
import traceback
from cpl.configuration.configuration_model_abc import ConfigurationModelABC
from cpl.console.console import Console
from cpl.mailing.email_client_settings_name_enum import EMailClientSettingsNameEnum
class EMailClientSettings(ConfigurationModelABC):
r"""Representation of mailing settings"""
def __init__(self):
ConfigurationModelABC.__init__(self)
self._host: str = ''
self._port: int = 0
self._user_name: str = ''
self._credentials: str = ''
@property
def host(self) -> str:
return self._host
@host.setter
def host(self, host: str) -> None:
self._host = host
@property
def port(self) -> int:
return self._port
@port.setter
def port(self, port: int) -> None:
self._port = port
@property
def user_name(self) -> str:
return self._user_name
@user_name.setter
def user_name(self, user_name: str) -> None:
self._user_name = user_name
@property
def credentials(self) -> str:
return self._credentials
@credentials.setter
def credentials(self, credentials: str) -> None:
self._credentials = credentials
def from_dict(self, settings: dict):
try:
self._host = settings[EMailClientSettingsNameEnum.host.value]
self._port = settings[EMailClientSettingsNameEnum.port.value]
self._user_name = settings[EMailClientSettingsNameEnum.user_name.value]
self._credentials = settings[EMailClientSettingsNameEnum.credentials.value]
except Exception as e:
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')

View File

@@ -0,0 +1,9 @@
from enum import Enum
class EMailClientSettingsNameEnum(Enum):
host = 'Host'
port = 'Port'
user_name = 'UserName'
credentials = 'Credentials'