Migrate email catcher to Mailpit
This commit is contained in:
+2
-2
@@ -3,6 +3,6 @@ MYSQL_DATABASE=visione
|
|||||||
MYSQL_USER=visione
|
MYSQL_USER=visione
|
||||||
MYSQL_PASSWORD=visione
|
MYSQL_PASSWORD=visione
|
||||||
MYSQL_ROOT_PASSWORD=root
|
MYSQL_ROOT_PASSWORD=root
|
||||||
MAILHOG_SMTP_PORT=1025
|
MAILPIT_SMTP_PORT=1025
|
||||||
MAILHOG_WEB_PORT=8025
|
MAILPIT_WEB_PORT=8025
|
||||||
CORS_ALLOWED_ORIGIN=http://localhost:3000
|
CORS_ALLOWED_ORIGIN=http://localhost:3000
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
- This repository is the backend for **Visione**, an urban issue reporting webapp.
|
- 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.
|
- 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.
|
- 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
|
## Authoritative References
|
||||||
- Local Drogon source: `/home/gabdevele/Projects/snitchitaly/backend/drogon`
|
- Local Drogon source: `/home/gabdevele/Projects/snitchitaly/backend/drogon`
|
||||||
@@ -31,5 +31,5 @@
|
|||||||
## Development Workflow
|
## Development Workflow
|
||||||
- Update docs when behavior, schema, setup or API contracts change.
|
- Update docs when behavior, schema, setup or API contracts change.
|
||||||
- After each completed and verified feature, create a short commit.
|
- 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.
|
- Do not spend excessive time on exhaustive tests; cover high-risk behavior and regressions.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Visione Backend
|
# Visione Backend
|
||||||
|
|
||||||
C++20 API backend built with Drogon for the Visione urban reporting project.
|
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
|
## Setup
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ cmake --build build
|
|||||||
```
|
```
|
||||||
|
|
||||||
The API listens on `http://localhost:5555`.
|
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.
|
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
|
Multipart uploads currently accept report images and videos up to the app body
|
||||||
limit configured in `config.json`.
|
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`.
|
domain in Dokploy against service `backend` and container port `5555`.
|
||||||
|
|
||||||
The runtime image includes `config.json`; override environment-specific values
|
The runtime image includes `config.json`; override environment-specific values
|
||||||
with Dokploy environment variables. The SMTP catcher service keeps the internal
|
with Dokploy environment variables. The SMTP catcher service uses the
|
||||||
name `mailhog` for compatibility, but uses the multi-architecture Mailpit image
|
multi-architecture Mailpit image to avoid `exec format error` failures on ARM
|
||||||
to avoid `exec format error` failures on ARM servers.
|
servers.
|
||||||
|
|
||||||
Set `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `MYSQL_ROOT_PASSWORD` and
|
Set `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `MYSQL_ROOT_PASSWORD` and
|
||||||
`CORS_ALLOWED_ORIGIN` in Dokploy environment variables. Use the exact browser
|
`CORS_ALLOWED_ORIGIN` in Dokploy environment variables. Use the exact browser
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ services:
|
|||||||
DB_PASSWORD: ${DB_PASSWORD:-visione}
|
DB_PASSWORD: ${DB_PASSWORD:-visione}
|
||||||
DB_NAME: ${DB_NAME:-visione}
|
DB_NAME: ${DB_NAME:-visione}
|
||||||
DB_TIMEOUT: ${DB_TIMEOUT:-30}
|
DB_TIMEOUT: ${DB_TIMEOUT:-30}
|
||||||
SMTP_HOST: ${SMTP_HOST:-mailhog}
|
SMTP_HOST: ${SMTP_HOST:-mailpit}
|
||||||
SMTP_PORT: ${SMTP_PORT:-1025}
|
SMTP_PORT: ${SMTP_PORT:-1025}
|
||||||
CORS_ALLOWED_ORIGIN: ${CORS_ALLOWED_ORIGIN:-http://localhost:3000}
|
CORS_ALLOWED_ORIGIN: ${CORS_ALLOWED_ORIGIN:-http://localhost:3000}
|
||||||
expose:
|
expose:
|
||||||
@@ -46,7 +46,7 @@ services:
|
|||||||
retries: 20
|
retries: 20
|
||||||
start_period: 20s
|
start_period: 20s
|
||||||
|
|
||||||
mailhog:
|
mailpit:
|
||||||
image: axllent/mailpit:latest
|
image: axllent/mailpit:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
+4
-4
@@ -17,11 +17,11 @@ services:
|
|||||||
retries: 20
|
retries: 20
|
||||||
start_period: 20s
|
start_period: 20s
|
||||||
|
|
||||||
mailhog:
|
mailpit:
|
||||||
image: mailhog/mailhog:v1.0.1
|
image: axllent/mailpit:latest
|
||||||
ports:
|
ports:
|
||||||
- "${MAILHOG_SMTP_PORT:-1025}:1025"
|
- "${MAILPIT_SMTP_PORT:-1025}:1025"
|
||||||
- "${MAILHOG_WEB_PORT:-8025}:8025"
|
- "${MAILPIT_WEB_PORT:-8025}:8025"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql-data:
|
mysql-data:
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ Base path: `/api/v1`.
|
|||||||
|
|
||||||
## Auth
|
## Auth
|
||||||
- `POST /auth/register`: create a citizen account.
|
- `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/otp/verify`: verify OTP and create an API token.
|
||||||
- `POST /auth/login/password`: password login fallback.
|
- `POST /auth/login/password`: password login fallback.
|
||||||
- `POST /auth/change-password`: change the authenticated user's password.
|
- `POST /auth/change-password`: change the authenticated user's password.
|
||||||
|
|||||||
@@ -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.
|
in repository/database helpers because the schema is still evolving.
|
||||||
|
|
||||||
## Local Email
|
## 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.
|
inspectable through its web UI.
|
||||||
|
|
||||||
## Password Hashing
|
## Password Hashing
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ and use intervention summaries.
|
|||||||
Admins manage roles, users, areas, teams, reference data, moderation and stats.
|
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
|
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.
|
the backend are later delivery tasks.
|
||||||
|
|
||||||
Important conventions:
|
Important conventions:
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
## Implemented in this milestone
|
## Implemented in this milestone
|
||||||
- Project identity and documentation for Visione.
|
- Project identity and documentation for Visione.
|
||||||
- Root `AGENTS.md` for future coding agents.
|
- 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.
|
- Initial MySQL schema and seed data.
|
||||||
- Drogon backend structure for auth, reports, admin data and stats.
|
- 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.
|
- Focused regression tests for technical endpoints and core validation helpers.
|
||||||
- Local admin seed: `[email protected]` / `ChangeMe123!`, with forced password change flag.
|
- Local admin seed: `[email protected]` / `ChangeMe123!`, with forced password change flag.
|
||||||
- Multipart report media upload endpoint storing files under `uploads/reports/`.
|
- Multipart report media upload endpoint storing files under `uploads/reports/`.
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Valid milestone 2 transitions:
|
|||||||
- `REJECTED -> CLOSED`.
|
- `REJECTED -> CLOSED`.
|
||||||
|
|
||||||
## MVP Scope
|
## 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.
|
- MySQL persistence with migrations and seed data.
|
||||||
- Report creation/list/detail/status/message/assignment/feedback/moderation flows.
|
- Report creation/list/detail/status/message/assignment/feedback/moderation flows.
|
||||||
- Area polygons stored as GeoJSON and matched by backend logic.
|
- Area polygons stored as GeoJSON and matched by backend logic.
|
||||||
|
|||||||
@@ -897,7 +897,7 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"delivery": {
|
"delivery": {
|
||||||
"example": "mailhog",
|
"example": "mailpit",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"expires_in_minutes": {
|
"expires_in_minutes": {
|
||||||
@@ -2209,7 +2209,7 @@
|
|||||||
},
|
},
|
||||||
"/api/v1/auth/otp/request": {
|
"/api/v1/auth/otp/request": {
|
||||||
"post": {
|
"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",
|
"operationId": "AuthController.requestOtp",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
|
|||||||
+1
-1
@@ -466,6 +466,6 @@ with docs_tab:
|
|||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
st.text_input("Backend API", key="base_url")
|
st.text_input("Backend API", key="base_url")
|
||||||
st.text_input("Bearer token", key="token", type="password")
|
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"):
|
if st.button("Health check"):
|
||||||
show_response(request("GET", "/health", timeout=5))
|
show_response(request("GET", "/health", timeout=5))
|
||||||
|
|||||||
@@ -147,12 +147,12 @@ Json::Value AuthService::requestOtp(const Json::Value &body)
|
|||||||
email::EmailService mail;
|
email::EmailService mail;
|
||||||
if (!mail.sendOtp(user[0]["email"].as<std::string>(), code))
|
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");
|
return failure("otp_email_failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = success();
|
auto response = success();
|
||||||
response["delivery"] = "mailhog";
|
response["delivery"] = "mailpit";
|
||||||
response["expires_in_minutes"] = otpTtlMinutes();
|
response["expires_in_minutes"] = otpTtlMinutes();
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user