Skip to content

Commit 325b15c

Browse files
committed
Merge branch 'hotfix/2025.2.1'
2 parents 29ea8e1 + 5031dab commit 325b15c

File tree

11 files changed

+374
-331
lines changed

11 files changed

+374
-331
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,22 @@ tech changes will usually be stripped from release notes for the public
1010

1111
## Unreleased
1212

13+
## [2025.2.1]
14+
15+
This fixes/adds support for a wider variety of smtp email servers.
16+
17+
### Added
18+
19+
- SSL email configuration
20+
- Choose between START TLS / TLS / SSL / LMTP for smtp connection
21+
22+
### Fixed
23+
24+
- Mail not working in envs where username env is missing (e.g. docker)
25+
- This is a problem in the mail lib used, but circumvented in the Dockerfile
26+
- Mail error showing a 500 error in the client
27+
- Email setup reset when the config changes to make sure new email values are used
28+
1329
## [2025.2]
1430

1531
**Server owners:** The server config has changed location and format. Ensure you check the release notes for the necessary info.

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ VOLUME /planarally/static/mods
5252
ENV PA_GIT_INFO docker:${DOCKER_TAG}-${SOURCE_COMMIT}
5353
ENV PYTHONUNBUFFERED=1
5454
ENV UV_CACHE_DIR /planarally/.uv
55+
# This is only done to ensure that the mail lib does not crash :4
56+
ENV USERNAME=planarally
5557

5658
RUN apt-get update && apt-get install --no-install-recommends dumb-init curl libffi-dev libssl-dev gcc -y && \
5759
rm -rf /var/lib/apt/lists/*

client/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "client",
3-
"version": "2025.2.0",
3+
"version": "2025.2.1",
44
"private": true,
55
"type": "module",
66
"scripts": {

server/VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
2025.2.0
1+
2025.2.1
22

33
**Server owners:** The server config has changed location and format. Ensure you check the release notes for the necessary info.
44
The old config files are not yet removed from git to prevent losing modifications you made to these files.
@@ -64,4 +64,4 @@ They will be removed in a future release though.
6464
- Asset picker out of game now uses the newer UI
6565
- Dropping assets you have shared-view permission for on the map was not working
6666
- Movement only door toggle not immediately rerendering screen
67-
- Select tool UI would sometimes stick around when there is no shape selected anymore
67+
- Select tool UI would sometimes stick around when there is no shape selected anymore

server/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "planarally-server"
3-
version = "2025.2.0"
3+
version = "2025.2.1"
44
description = "Planarally server"
55
readme = "README.md"
66
requires-python = ">=3.13.2"

server/src/api/http/auth.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,13 @@ async def forgot_password(request):
9595
reset_url = f"{cfg().general.client_url}/auth/login?resetToken={reset_token}"
9696

9797
# Send the email
98-
send_mail(
98+
if not send_mail(
9999
"Password reset request",
100100
f"A password reset for the PlanarAlly account associated with this email address was requested. Visit {reset_url} to reset your password. If you did not do this, please ignore this email.",
101101
f"A password reset for the PlanarAlly account associated with this email address was requested. Visit <a href='{reset_url}'>{reset_url}</a> to reset your password.<br><br>If you did not do this, please ignore this email.",
102102
[email],
103-
)
103+
):
104+
return web.HTTPInternalServerError(reason="Failed to send email - check with your administrator")
104105

105106
return web.HTTPOk()
106107

server/src/config/manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ def load_config(self, *, startup=False) -> None:
5050

5151
if not startup:
5252
from ..logs import logger
53+
from ..mail import reset_email
5354

5455
logger.info("Config file changed, reloading")
56+
reset_email()
5557
except rtoml.TomlParsingError as e:
5658
print(f"Error loading config: {e}")
5759
except ValidationError as e:

server/src/config/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class MailConfig(BaseModel):
101101
password: Optional[str] = None
102102
# The default from address to use for emails
103103
default_from_address: EmailStr
104+
ssl_mode: Literal["ssl", "tls", "starttls", "lmtp"] = "starttls"
104105

105106

106107
class StatsConfig(BaseModel):

server/src/mail/__init__.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
from smtplib import LMTP, SMTP_SSL
2+
13
from redmail.email.sender import EmailSender
24

35
from ..config import cfg
6+
from ..logs import logger
47

58
_email = None
69

710

11+
def reset_email() -> None:
12+
global _email
13+
_email = None
14+
15+
816
def get_email() -> EmailSender:
917
"""
1018
Get the email sender object.
@@ -28,12 +36,20 @@ def get_email() -> EmailSender:
2836
if not config.mail.default_from_address:
2937
raise ValueError("Mail default from address is not set")
3038

39+
ssl_kwargs = {}
40+
if config.mail.ssl_mode == "ssl":
41+
ssl_kwargs["cls_smtp"] = SMTP_SSL
42+
elif config.mail.ssl_mode == "lmtp":
43+
ssl_kwargs["cls_smtp"] = LMTP
44+
3145
_email = EmailSender(
3246
host=config.mail.host,
3347
port=config.mail.port,
3448
# These are wrongly typed in the redmail library
3549
username=config.mail.username, # type: ignore
3650
password=config.mail.password, # type: ignore
51+
use_starttls=config.mail.ssl_mode == "starttls",
52+
**ssl_kwargs,
3753
)
3854
return _email
3955

@@ -44,15 +60,20 @@ def send_mail(
4460
html: str | None,
4561
to: str | list[str],
4662
from_address: str | None = None,
47-
) -> None:
63+
) -> bool:
4864
email = get_email()
4965
config = cfg()
5066

5167
assert config.mail is not None
52-
email.send(
53-
subject=subject,
54-
text=text,
55-
html=html,
56-
receivers=to,
57-
sender=from_address or config.mail.default_from_address,
58-
)
68+
try:
69+
email.send(
70+
subject=subject,
71+
text=text,
72+
html=html,
73+
receivers=to,
74+
sender=from_address or config.mail.default_from_address,
75+
)
76+
except Exception as e:
77+
logger.error(f"Error sending mail: {e}")
78+
return False
79+
return True

0 commit comments

Comments
 (0)