Skip to content

Commit

Permalink
Merge pull request #3 from ds-wizard/release/1.1.0
Browse files Browse the repository at this point in the history
Release 1.1.0
  • Loading branch information
MarekSuchanek committed Jan 11, 2022
2 parents e32823f + 5c70ec7 commit a02465e
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 33 deletions.
Binary file not shown.
13 changes: 13 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ security:
tokens:
- ...

mail:
enabled: false
name:
email:
host:
port:
security:
authEnabled:
username:
password:
recipients:
-

#logging:
# level: WARNING
# format: ...
6 changes: 5 additions & 1 deletion nanopub_submitter/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from nanopub_submitter.consts import NICE_NAME, VERSION, BUILD_INFO,\
ENV_CONFIG, DEFAULT_CONFIG, DEFAULT_ENCODING
from nanopub_submitter.logger import LOG, init_default_logging, init_config_logging
from nanopub_submitter.mailer import Mailer
from nanopub_submitter.nanopub import process, NanopubProcessingError

app = fastapi.FastAPI(
Expand Down Expand Up @@ -86,7 +87,9 @@ async def submit_nanopub(request: fastapi.Request):
status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR,
content='Failed to process the nanopublication',
)
# (4) Return
# (4) Mail
Mailer.get().notice(nanopub_uri=result.location)
# (5) Return
return fastapi.responses.Response(
status_code=fastapi.status.HTTP_201_CREATED,
headers={
Expand All @@ -105,6 +108,7 @@ async def app_init():
with pathlib.Path(config_file).open() as fp:
cfg = cfg_parser.parse_file(fp=fp)
init_config_logging(config=cfg)
Mailer.init(config=cfg)
except Exception as e:
LOG.warn(f'Failed to load config: {config_file}')
LOG.debug(str(e))
Expand Down
54 changes: 52 additions & 2 deletions nanopub_submitter/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, missing: List[str]):
class NanopubConfig:

def __init__(self, servers: List[str], client_exec: str,
strategy: str, strategy_number: int,
strategy: str, strategy_number: int, uri_replace: str,
client_timeout: int, workdir: str, sign_key_type: str,
sign_nanopub: bool, sign_private_key: Optional[str]):
self.servers = servers
Expand All @@ -26,6 +26,7 @@ def __init__(self, servers: List[str], client_exec: str,
self.sign_key_type = sign_key_type
self.sign_private_key = sign_private_key
self.workdir = pathlib.Path(workdir)
self.uri_replace = uri_replace

@property
def target_servers(self) -> list[str]:
Expand Down Expand Up @@ -66,14 +67,33 @@ def __init__(self, level, message_format: str):
self.format = message_format


class MailConfig:

def __init__(self, enabled: bool, name: str, email: str,
host: str, port: int, security: str, auth: bool,
username: str, password: str, recipients: list[str]):
self.enabled = enabled
self.name = name
self.email = email
self.host = host
self.port = port
self.security = security.lower()
self.auth = auth
self.username = username
self.password = password
self.recipients = recipients


class SubmitterConfig:

def __init__(self, nanopub: NanopubConfig, security: SecurityConfig,
triple_store: TripleStoreConfig, logging: LoggingConfig):
triple_store: TripleStoreConfig, logging: LoggingConfig,
mail: MailConfig):
self.nanopub = nanopub
self.security = security
self.triple_store = triple_store
self.logging = logging
self.mail = mail


class SubmitterConfigParser:
Expand All @@ -89,6 +109,7 @@ class SubmitterConfigParser:
'sign_key_type': 'DSA',
'sign_private_key': '',
'workdir': '/app/workdir',
'uri_replace': None,
},
'triple_store': {
'enabled': False,
Expand All @@ -114,6 +135,18 @@ class SubmitterConfigParser:
'level': 'INFO',
'format': '%(asctime)s | %(levelname)s | %(module)s: %(message)s',
},
'mail': {
'enabled': False,
'name': 'Nanopub Submitter',
'email': '',
'host': '',
'port': 25,
'security': 'plain',
'authEnabled': False,
'username': '',
'password': '',
'recipients': [],
},
}

REQUIRED = [] # type: List[List[str]]
Expand Down Expand Up @@ -163,6 +196,7 @@ def _nanopub(self):
sign_key_type=self.get_or_default('nanopub', 'sign_key_type'),
sign_private_key=self.get_or_default('nanopub', 'sign_private_key'),
workdir=self.get_or_default('nanopub', 'workdir'),
uri_replace=self.get_or_default('nanopub', 'uri_replace'),
)

@property
Expand Down Expand Up @@ -194,6 +228,21 @@ def _triple_store(self):
strategy=self.get_or_default('triple_store', 'strategy'),
)

@property
def _mail(self):
return MailConfig(
enabled=self.get_or_default('mail', 'enabled'),
name=self.get_or_default('mail', 'name'),
email=self.get_or_default('mail', 'email'),
host=self.get_or_default('mail', 'host'),
port=self.get_or_default('mail', 'port'),
security=self.get_or_default('mail', 'security'),
auth=self.get_or_default('mail', 'authEnabled'),
username=self.get_or_default('mail', 'username'),
password=self.get_or_default('mail', 'password'),
recipients=self.get_or_default('mail', 'recipients'),
)

def parse_file(self, fp) -> SubmitterConfig:
self.cfg = yaml.full_load(fp)
self.validate()
Expand All @@ -206,6 +255,7 @@ def config(self) -> SubmitterConfig:
security=self._security,
logging=self._logging,
triple_store=self._triple_store,
mail=self._mail,
)


Expand Down
2 changes: 1 addition & 1 deletion nanopub_submitter/consts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PACKAGE_NAME = 'nanopub_submitter'
NICE_NAME = 'DSW Nanopublication Submission Service'
PACKAGE_VERSION = '1.0.0'
PACKAGE_VERSION = '1.1.0'
ENV_CONFIG = 'SUBMISSION_CONFIG'
LOGGER_NAME = 'DSW_SUBMITTER'

Expand Down
102 changes: 102 additions & 0 deletions nanopub_submitter/mailer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import email
import smtplib
import ssl

from nanopub_submitter.config import SubmitterConfig
from nanopub_submitter.logger import LOG


class Mailer:
_instance = None

def __init__(self):
self.cfg = None

@classmethod
def init(cls, config: SubmitterConfig):
cls.get().cfg = config

@classmethod
def get(cls):
if cls._instance is None:
cls._instance = Mailer()
return cls._instance

def _msg_text(self, nanopub_uri: str):
return f"Hello,\n" \
f"new nanopublication has been submitted:\n" \
f"{nanopub_uri}\n" \
f"____________________________________________________\n" \
f"Have a nice day!\n" \
f"{self.cfg.mail.name}\n"

def notice(self, nanopub_uri: str):
if not self.cfg.mail.enabled:
LOG.debug(f'Notification for {nanopub_uri} skipped'
f'(mail disabled)')
return
if len(self.cfg.mail.recipients) < 1:
LOG.debug(f'Notification for {nanopub_uri} skipped'
f'(no recipients defined)')
return
LOG.info(f'Sending notification for {nanopub_uri}')

msg = email.message.Message()
msg['From'] = self.cfg.mail.email
msg['To'] = ', '.join(self.cfg.mail.recipients)
msg['Subject'] = f'[{self.cfg.mail.name}] New nanopublication'
msg.add_header('Content-Type', 'text/plain')
msg.set_payload(self._msg_text(nanopub_uri))
try:
result = self._send(msg)
LOG.debug(f'Email result: {result}')
except Exception as e:
LOG.warn(f'Failed to send notification: {str(e)}')

def _send(self, message: email.message.Message):
if self.cfg.mail.security == 'ssl':
return self._send_smtp_ssl(
message=message,
)
return self._send_smtp(
message=message,
use_tls=self.cfg.mail.security == 'starttls',
)

def _send_smtp_ssl(self, message: email.message.Message):
context = ssl.create_default_context()
with smtplib.SMTP_SSL(
host=self.cfg.mail.host,
port=self.cfg.mail.port,
context=context,
) as server:
if self.cfg.mail.auth:
server.login(
user=self.cfg.mail.username,
password=self.cfg.mail.password,
)
return server.send_message(
msg=message,
from_addr=self.cfg.mail.email,
to_addrs=self.cfg.mail.recipients,
)

def _send_smtp(self, message: email.message.Message,
use_tls: bool):
context = ssl.create_default_context()
with smtplib.SMTP(
host=self.cfg.mail.host,
port=self.cfg.mail.port,
) as server:
if use_tls:
server.starttls(context=context)
if self.cfg.mail.auth:
server.login(
user=self.cfg.mail.username,
password=self.cfg.mail.password,
)
return server.send_message(
msg=message,
from_addr=self.cfg.mail.email,
to_addrs=self.cfg.mail.recipients,
)
Loading

0 comments on commit a02465e

Please sign in to comment.