Skip to content
Commits on Source (2)
......@@ -22,8 +22,8 @@ After ~1m Keycloak should be reachable at the following URLs:
- This is where users sign in, sign up, create anonymous accounts, change the email and password
- Note that the "Try anonymously" and "GitHub" login buttons are there so you can style them, but they are not functional.
- There's no user account by default, you can create user accounts either by signing up or from the admin console.
Account confirmation emails are printed to the `docker compose` log, so keep an eye on it.
- [http://localhost:8025](http://localhost:8025) - Test email server
- All emails sent by Keycloak will be displayed here (such as account activation emails).
## Important!
......
......@@ -54,18 +54,26 @@ services:
- |
apk add inotify-tools sassc make
uid="$$(stat -c '%u' /theme/welcome/theme.properties)"
adduser -D -u $$uid unprivileged
su unprivileged -c 'make -C /theme'
if [[ $$uid == 0 ]]; then
su="sh"
else
su="su unprivileged"
adduser -D -u $$uid unprivileged
fi
$$su -c 'make -C /theme'
while inotifywait -qre close_write /theme/_sass; do
su unprivileged -c 'make -C /theme'
$$su -c 'make -C /theme'
done
# This is a fake SMTP server that prints the received emails to the console.
fake-mail-server:
build: ./fakesmtpd
image: mailhog/mailhog
restart: "unless-stopped"
environment:
PYTHONUNBUFFERED: "1"
command:
- "-smtp-bind-addr"
- ":25"
ports:
- "127.0.0.1:8025:8025"
# Keycloak isn't very smart, and it expects HTTPS requests when HTTPS is disabled.
# This is a hack to forcefully disable the policy by pretending to be a reverse-proxy.
......
FROM python:3.11-alpine
COPY requirements.txt /tmp/requirements.txt
RUN pip install -r /tmp/requirements.txt
COPY fakesmtp.py /usr/bin/fakesmtp
ENTRYPOINT ["/usr/bin/fakesmtp"]
CMD ["0.0.0.0", "25"]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import logging
import sys
from aiosmtpd.controller import Controller
from aiosmtpd.smtp import AuthResult
# noinspection PyPep8Naming,PyMethodMayBeStatic
class PrintHandler:
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
envelope.rcpt_tos.append(address)
return "250 OK"
async def handle_DATA(self, server, session, envelope):
print(f"Message from {envelope.mail_from}")
print(f'Message for {", ".join(envelope.rcpt_tos)}')
print("Message data:\n")
for ln in envelope.content.decode("utf8", errors="replace").splitlines():
print(f"> {ln}".strip())
print()
print("End of message")
print()
print()
return "250 Message accepted for delivery"
def authenticator(*a, **kw):
return AuthResult(success=True)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: fakesmtp.py <hostname> <port>")
sys.exit(1)
hostname = sys.argv[1]
port = int(sys.argv[2])
logging.basicConfig(level=logging.INFO)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
controller = Controller(
PrintHandler(),
hostname=hostname,
port=port,
authenticator=authenticator,
auth_required=False,
auth_require_tls=False,
)
controller.start()
try:
loop.run_forever()
except KeyboardInterrupt:
print("Exiting")