Migrate email catcher to Mailpit

This commit is contained in:
gabdevele
2026-06-11 01:25:18 +02:00 Unverified
parent c6dc19269a
commit 34c713e8b3
13 changed files with 26 additions and 26 deletions
+2 -2
View File
@@ -3,6 +3,6 @@ MYSQL_DATABASE=visione
MYSQL_USER=visione
MYSQL_PASSWORD=visione
MYSQL_ROOT_PASSWORD=root
MAILHOG_SMTP_PORT=1025
MAILHOG_WEB_PORT=8025
MAILPIT_SMTP_PORT=1025
MAILPIT_WEB_PORT=8025
CORS_ALLOWED_ORIGIN=http://localhost:3000
+2 -2
View File
@@ -4,7 +4,7 @@
- This repository is the backend for **Visione**, an urban issue reporting webapp.
- The backend is C++20 with Drogon. Keep code, symbols, API fields, database names and comments in English.
- User-facing product labels may be Italian when they represent UI/business vocabulary.
- Docker is for local external services only: MySQL, MailHog and future Redis-like dependencies.
- Docker is for local external services only: MySQL, Mailpit and future Redis-like dependencies.
## Authoritative References
- Local Drogon source: `/home/gabdevele/Projects/snitchitaly/backend/drogon`
@@ -31,5 +31,5 @@
## Development Workflow
- Update docs when behavior, schema, setup or API contracts change.
- After each completed and verified feature, create a short commit.
- Keep commit messages concise, for example `Add MailHog config` or `Add report API`.
- Keep commit messages concise, for example `Add Mailpit config` or `Add report API`.
- Do not spend excessive time on exhaustive tests; cover high-risk behavior and regressions.
+5 -5
View File
@@ -1,7 +1,7 @@
# Visione Backend
C++20 API backend built with Drogon for the Visione urban reporting project.
Docker is used only for local external services: MySQL and MailHog.
Docker is used only for local external services: MySQL and Mailpit.
## Setup
@@ -27,7 +27,7 @@ cmake --build build
```
The API listens on `http://localhost:5555`.
MailHog listens on `http://localhost:8025`.
Mailpit listens on `http://localhost:8025`.
Local CORS allows `http://localhost:5173` by default for the future Vue frontend.
Multipart uploads currently accept report images and videos up to the app body
limit configured in `config.json`.
@@ -138,9 +138,9 @@ backend deployment with MySQL and a local SMTP catcher. Configure the public
domain in Dokploy against service `backend` and container port `5555`.
The runtime image includes `config.json`; override environment-specific values
with Dokploy environment variables. The SMTP catcher service keeps the internal
name `mailhog` for compatibility, but uses the multi-architecture Mailpit image
to avoid `exec format error` failures on ARM servers.
with Dokploy environment variables. The SMTP catcher service uses the
multi-architecture Mailpit image to avoid `exec format error` failures on ARM
servers.
Set `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `MYSQL_ROOT_PASSWORD` and
`CORS_ALLOWED_ORIGIN` in Dokploy environment variables. Use the exact browser
+2 -2
View File
@@ -13,7 +13,7 @@ services:
DB_PASSWORD: ${DB_PASSWORD:-visione}
DB_NAME: ${DB_NAME:-visione}
DB_TIMEOUT: ${DB_TIMEOUT:-30}
SMTP_HOST: ${SMTP_HOST:-mailhog}
SMTP_HOST: ${SMTP_HOST:-mailpit}
SMTP_PORT: ${SMTP_PORT:-1025}
CORS_ALLOWED_ORIGIN: ${CORS_ALLOWED_ORIGIN:-http://localhost:3000}
expose:
@@ -46,7 +46,7 @@ services:
retries: 20
start_period: 20s
mailhog:
mailpit:
image: axllent/mailpit:latest
restart: unless-stopped
expose:
+4 -4
View File
@@ -17,11 +17,11 @@ services:
retries: 20
start_period: 20s
mailhog:
image: mailhog/mailhog:v1.0.1
mailpit:
image: axllent/mailpit:latest
ports:
- "${MAILHOG_SMTP_PORT:-1025}:1025"
- "${MAILHOG_WEB_PORT:-8025}:8025"
- "${MAILPIT_SMTP_PORT:-1025}:1025"
- "${MAILPIT_WEB_PORT:-8025}:8025"
volumes:
mysql-data:
+1 -1
View File
@@ -10,7 +10,7 @@ Base path: `/api/v1`.
## Auth
- `POST /auth/register`: create a citizen account.
- `POST /auth/otp/request`: send an OTP email through MailHog.
- `POST /auth/otp/request`: send an OTP email through Mailpit.
- `POST /auth/otp/verify`: verify OTP and create an API token.
- `POST /auth/login/password`: password login fallback.
- `POST /auth/change-password`: change the authenticated user's password.
+1 -1
View File
@@ -20,7 +20,7 @@ The codebase does not use Drogon generated models or `Mapper<T>`. Raw SQL stays
in repository/database helpers because the schema is still evolving.
## Local Email
OTP emails are sent to MailHog over SMTP. MailHog keeps messages local and
OTP emails are sent to Mailpit over SMTP. Mailpit keeps messages local and
inspectable through its web UI.
## Password Hashing
+1 -1
View File
@@ -8,7 +8,7 @@ and use intervention summaries.
Admins manage roles, users, areas, teams, reference data, moderation and stats.
The project runs locally on the host machine. Docker is used only for external
services such as MySQL and MailHog. Real production deployment and Dockerizing
services such as MySQL and Mailpit. Real production deployment and Dockerizing
the backend are later delivery tasks.
Important conventions:
+2 -2
View File
@@ -3,10 +3,10 @@
## Implemented in this milestone
- Project identity and documentation for Visione.
- Root `AGENTS.md` for future coding agents.
- Local Docker services for MySQL and MailHog.
- Local Docker services for MySQL and Mailpit.
- Initial MySQL schema and seed data.
- Drogon backend structure for auth, reports, admin data and stats.
- OTP email delivery through MailHog.
- OTP email delivery through Mailpit.
- Focused regression tests for technical endpoints and core validation helpers.
- Local admin seed: `[email protected]` / `ChangeMe123!`, with forced password change flag.
- Multipart report media upload endpoint storing files under `uploads/reports/`.
+1 -1
View File
@@ -34,7 +34,7 @@ Valid milestone 2 transitions:
- `REJECTED -> CLOSED`.
## MVP Scope
- Local auth with email OTP delivered through MailHog.
- Local auth with email OTP delivered through Mailpit.
- MySQL persistence with migrations and seed data.
- Report creation/list/detail/status/message/assignment/feedback/moderation flows.
- Area polygons stored as GeoJSON and matched by backend logic.
+2 -2
View File
@@ -897,7 +897,7 @@
"additionalProperties": false,
"properties": {
"delivery": {
"example": "mailhog",
"example": "mailpit",
"type": "string"
},
"expires_in_minutes": {
@@ -2209,7 +2209,7 @@
},
"/api/v1/auth/otp/request": {
"post": {
"description": "Sends a one-time code by email through MailHog locally.",
"description": "Sends a one-time code by email through Mailpit locally.",
"operationId": "AuthController.requestOtp",
"parameters": [],
"requestBody": {
+1 -1
View File
@@ -466,6 +466,6 @@ with docs_tab:
with st.sidebar:
st.text_input("Backend API", key="base_url")
st.text_input("Bearer token", key="token", type="password")
st.link_button("MailHog", "http://127.0.0.1:8025")
st.link_button("Mailpit", "http://127.0.0.1:8025")
if st.button("Health check"):
show_response(request("GET", "/health", timeout=5))
+2 -2
View File
@@ -147,12 +147,12 @@ Json::Value AuthService::requestOtp(const Json::Value &body)
email::EmailService mail;
if (!mail.sendOtp(user[0]["email"].as<std::string>(), code))
{
LOG_WARN << "Could not send OTP email through MailHog";
LOG_WARN << "Could not send OTP email through Mailpit";
return failure("otp_email_failed");
}
auto response = success();
response["delivery"] = "mailhog";
response["delivery"] = "mailpit";
response["expires_in_minutes"] = otpTtlMinutes();
return response;
}