add reading password from file

Signed-off-by: Florian Brandes <florian.brandes@posteo.de>
This commit is contained in:
2024-07-11 18:53:48 +02:00
parent 14c87f03ce
commit ffeb686fe0
3 changed files with 42 additions and 5 deletions

View File

@@ -6,7 +6,8 @@
hostname = smtp.mail.example.com
port = 465
username = foo@example.com
password = s3cr3t
# If password_file is supplied, a valid path must be supplied
# password_file = Path/to/file
sender = foo@example.com
# set_reply_to = false
# use_tls = true

View File

@@ -107,6 +107,22 @@ class Config:
email_certs[email] = cert
return email_certs
@classmethod
def _read_from_file(cls, file: Union[Path, str]) -> str:
"""Read string from file"""
if len(file) == 0:
# empty string (which is our fallback), so return empty string
return ""
# file is non-empty and should provide a path
file = Path(file)
if not file.exists():
raise OSError("File wasn't found: " + str(file))
with open(file, "r", encoding="utf8") as fp:
line = fp.readline().strip("\n")
if len(line) == 0:
raise OSError("Empty file supplied: " + str(file))
return line
@classmethod
def _from_config(cls, config: configparser.RawConfigParser) -> "Config":
email_certs = cls._get_emails_and_certs(config.items("emails"))
@@ -120,7 +136,9 @@ class Config:
port=config.getint("client", "port"),
sender=config.get("client", "sender"),
username=config.get("client", "username"),
password=config.get("client", "password"),
password=cls._read_from_file(
(config.get("client", "password_file", fallback=""))
),
set_reply_to=config.getboolean(
"client", "set_reply_to", fallback=False
),

View File

@@ -19,7 +19,6 @@
Tests for smtprd_ng
"""
# pylint: disable=protected-access
# pylint: disable=unused-argument
import configparser
import email
@@ -68,6 +67,7 @@ def test_config_from_config():
assert cfg.client.port == 465
assert cfg.client.smime_cert == ""
assert cfg.client.use_tls is True
assert cfg.client.password == ""
def test_config_from_ini():
@@ -80,6 +80,24 @@ def test_config_from_ini():
assert cfg.client.use_tls is True
def test_read_from_file():
"""Test read_from_file function and the fallback"""
existing_file = "config.example"
non_existing_file = "abcde"
empty_file = "tests/__init__.py"
empty_string = ""
assert smtprd.Config._read_from_file(existing_file) == "# [server]"
with pytest.raises(Exception) as e_info:
smtprd.Config._read_from_file(non_existing_file)
assert e_info.typename == "OSError"
assert str(e_info.value) == "File wasn't found: abcde"
assert smtprd.Config._read_from_file(empty_string) == ""
with pytest.raises(Exception) as e_info:
smtprd.Config._read_from_file(empty_file)
assert e_info.typename == "OSError"
assert str(e_info.value) == "Empty file supplied: tests/__init__.py"
def test_config_emailcerts():
"""test retrieval of email/cert pair"""
email_list = [("email1", "cert1"), ("email2", "cert2")]
@@ -153,7 +171,7 @@ def test_client_sign():
assert "Test to sign" in v.decode()
def test_cli_no_config_file(capsys):
def test_cli_no_config_file():
"""Test whether config file parameter is supplied"""
test_args = ["--config", ""]
with pytest.raises(Exception) as e_info:
@@ -162,7 +180,7 @@ def test_cli_no_config_file(capsys):
assert str(e_info.value) == "No config file supplied"
def test_cli_config_file_not_found(capsys):
def test_cli_config_file_not_found():
"""Test whether config file is found"""
test_args = ["--config", "doesnotexist.conf"]
with pytest.raises(Exception) as e_info: