mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 23:37:18 +00:00
improved ssl mode
This commit is contained in:
parent
8627ae97a3
commit
21c5eae97d
@ -60,8 +60,8 @@ Group name must refer to architecture, e.g. it should be `email:x86_64` for x86_
|
|||||||
* `port` - SMTP port for sending emails, int, required.
|
* `port` - SMTP port for sending emails, int, required.
|
||||||
* `receivers` - SMTP receiver addresses, space separated list of strings, required.
|
* `receivers` - SMTP receiver addresses, space separated list of strings, required.
|
||||||
* `sender` - SMTP sender address, string, required.
|
* `sender` - SMTP sender address, string, required.
|
||||||
|
* `ssl` - SSL mode for SMTP connection, one of `ssl`, `starttls`, `disabled`, optional, default `disabled`.
|
||||||
* `template_path` - path to Jinja2 template, string, required.
|
* `template_path` - path to Jinja2 template, string, required.
|
||||||
* `use_tls` - use TLS for connection, boolean, optional, default False.
|
|
||||||
* `user` - SMTP user to authenticate, string, optional.
|
* `user` - SMTP user to authenticate, string, optional.
|
||||||
|
|
||||||
### `html:*` groups
|
### `html:*` groups
|
||||||
|
@ -29,6 +29,7 @@ from ahriman.core.report.jinja_template import JinjaTemplate
|
|||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.core.util import pretty_datetime
|
from ahriman.core.util import pretty_datetime
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
||||||
|
|
||||||
|
|
||||||
class Email(Report, JinjaTemplate):
|
class Email(Report, JinjaTemplate):
|
||||||
@ -39,7 +40,7 @@ class Email(Report, JinjaTemplate):
|
|||||||
:ivar port: SMTP port to connect
|
:ivar port: SMTP port to connect
|
||||||
:ivar receivers: list of receivers emails
|
:ivar receivers: list of receivers emails
|
||||||
:ivar sender: sender email address
|
:ivar sender: sender email address
|
||||||
:ivar use_tls: use TLS for SMTP connection
|
:ivar ssl: SSL mode for SMTP connection
|
||||||
:ivar user: username to authenticate via SMTP
|
:ivar user: username to authenticate via SMTP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ class Email(Report, JinjaTemplate):
|
|||||||
self.port = configuration.getint("email", "port")
|
self.port = configuration.getint("email", "port")
|
||||||
self.receivers = configuration.getlist("email", "receivers")
|
self.receivers = configuration.getlist("email", "receivers")
|
||||||
self.sender = configuration.get("email", "sender")
|
self.sender = configuration.get("email", "sender")
|
||||||
self.use_tls = configuration.getboolean("email", "use_tls", fallback=False)
|
self.ssl = SmtpSSLSettings.from_option(configuration.get("email", "ssl", fallback="disabled"))
|
||||||
self.user = configuration.get("email", "user", fallback=None)
|
self.user = configuration.get("email", "user", fallback=None)
|
||||||
|
|
||||||
def _send(self, text: str, attachment: Dict[str, str]) -> None:
|
def _send(self, text: str, attachment: Dict[str, str]) -> None:
|
||||||
@ -78,9 +79,12 @@ class Email(Report, JinjaTemplate):
|
|||||||
attach.add_header("Content-Disposition", "attachment", filename=filename)
|
attach.add_header("Content-Disposition", "attachment", filename=filename)
|
||||||
message.attach(attach)
|
message.attach(attach)
|
||||||
|
|
||||||
|
if self.ssl != SmtpSSLSettings.SSL:
|
||||||
session = smtplib.SMTP(self.host, self.port)
|
session = smtplib.SMTP(self.host, self.port)
|
||||||
if self.use_tls:
|
if self.ssl == SmtpSSLSettings.STARTTLS:
|
||||||
session.starttls()
|
session.starttls()
|
||||||
|
else:
|
||||||
|
session = smtplib.SMTP_SSL(self.host, self.port)
|
||||||
if self.user is not None and self.password is not None:
|
if self.user is not None and self.password is not None:
|
||||||
session.login(self.user, self.password)
|
session.login(self.user, self.password)
|
||||||
session.sendmail(self.sender, self.receivers, message.as_string())
|
session.sendmail(self.sender, self.receivers, message.as_string())
|
||||||
|
49
src/ahriman/models/smtp_ssl_settings.py
Normal file
49
src/ahriman/models/smtp_ssl_settings.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum, auto
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
|
||||||
|
class SmtpSSLSettings(Enum):
|
||||||
|
"""
|
||||||
|
SMTP SSL mode enumeration
|
||||||
|
:cvar Disabled: no SSL enabled
|
||||||
|
:cvar SSL: use SMTP_SSL instead of normal SMTP client
|
||||||
|
:cvar STARTTLS: use STARTTLS in normal SMTP client
|
||||||
|
"""
|
||||||
|
|
||||||
|
Disabled = auto()
|
||||||
|
SSL = auto()
|
||||||
|
STARTTLS = auto()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_option(cls: Type[SmtpSSLSettings], value: str) -> SmtpSSLSettings:
|
||||||
|
"""
|
||||||
|
construct value from configuration
|
||||||
|
:param value: configuration value
|
||||||
|
:return: parsed value
|
||||||
|
"""
|
||||||
|
if value.lower() in ("ssl", "ssl/tls"):
|
||||||
|
return cls.SSL
|
||||||
|
if value.lower() in ("starttls",):
|
||||||
|
return cls.STARTTLS
|
||||||
|
return cls.Disabled
|
@ -56,11 +56,26 @@ def test_send_auth_no_user(configuration: Configuration, mocker: MockerFixture)
|
|||||||
smtp_mock.return_value.login.assert_not_called()
|
smtp_mock.return_value.login.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_send_tls(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must send an email with attachment with tls
|
must send an email with attachment with ssl/tls
|
||||||
"""
|
"""
|
||||||
configuration.set("email", "use_tls", "yes")
|
configuration.set("email", "ssl", "ssl")
|
||||||
|
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
|
||||||
|
|
||||||
|
report = Email("x86_64", configuration)
|
||||||
|
report._send("a text", {"attachment.html": "an attachment"})
|
||||||
|
smtp_mock.return_value.starttls.assert_not_called()
|
||||||
|
smtp_mock.return_value.login.assert_not_called()
|
||||||
|
smtp_mock.return_value.sendmail.assert_called_once()
|
||||||
|
smtp_mock.return_value.quit.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must send an email with attachment with starttls
|
||||||
|
"""
|
||||||
|
configuration.set("email", "ssl", "starttls")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
|
|
||||||
report = Email("x86_64", configuration)
|
report = Email("x86_64", configuration)
|
||||||
|
21
tests/ahriman/models/test_smtp_settings.py
Normal file
21
tests/ahriman/models/test_smtp_settings.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
||||||
|
|
||||||
|
|
||||||
|
def test_from_option_invalid() -> None:
|
||||||
|
"""
|
||||||
|
must return disabled value on invalid option
|
||||||
|
"""
|
||||||
|
assert SmtpSSLSettings.from_option("invalid") == SmtpSSLSettings.Disabled
|
||||||
|
|
||||||
|
|
||||||
|
def test_from_option_valid() -> None:
|
||||||
|
"""
|
||||||
|
must return value from valid options
|
||||||
|
"""
|
||||||
|
assert SmtpSSLSettings.from_option("ssl") == SmtpSSLSettings.SSL
|
||||||
|
assert SmtpSSLSettings.from_option("SSL") == SmtpSSLSettings.SSL
|
||||||
|
assert SmtpSSLSettings.from_option("ssl/tls") == SmtpSSLSettings.SSL
|
||||||
|
assert SmtpSSLSettings.from_option("SSL/TLS") == SmtpSSLSettings.SSL
|
||||||
|
|
||||||
|
assert SmtpSSLSettings.from_option("starttls") == SmtpSSLSettings.STARTTLS
|
||||||
|
assert SmtpSSLSettings.from_option("STARTTLS") == SmtpSSLSettings.STARTTLS
|
Loading…
Reference in New Issue
Block a user