Platforma pentru creare, management si livrare newslettere, cu backend FastAPI, frontend React si persistenta PostgreSQL.
- Editor de continut newsletter (blocuri + template-uri)
- Management utilizatori si roluri (admin/editor/subscriber)
- Management template-uri, campanii, liste de destinatari si abonati
- Tracking pentru opens/clicks/unsubscribe
- Upload media pentru continut si newsletter design
- Pagina publica de prezentare + dashboard admin
- Frontend: React 18, TypeScript, Vite, Tailwind
- Backend: FastAPI, SQLAlchemy, Pydantic, Alembic
- Baza de date: PostgreSQL 16
- Runtime: Docker / Docker Compose
- Reverse proxy productie: Traefik (routing pe
/7mail)
7mail/
├── backend/
│ ├── app/
│ │ ├── core/
│ │ ├── models/
│ │ ├── routes/
│ │ ├── schemas/
│ │ ├── services/
│ │ └── main.py
│ ├── alembic/
│ ├── scripts/
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ ├── src/
│ ├── public/
│ ├── package.json
│ ├── vite.config.ts
│ └── Dockerfile
├── postgres/
│ └── init.sql
├── nginx/
├── docker-compose.yml
├── deploy.sh
└── validate.sh
Rutele definite in aplicatie:
/- pagina publica (landing)/admin- dashboard admin
Observatie: in cod exista multe componente pentru editor/campanii/template-uri/subscribers, dar la nivel de router principal sunt montate explicit doar cele 2 rute de mai sus.
Prefix API versionat: /api/v1
POST /api/v1/auth/registerPOST /api/v1/auth/loginPOST /api/v1/auth/refreshGET /api/v1/auth/mePOST /api/v1/auth/lost-password
GET /api/v1/templatesGET /api/v1/templates/myGET /api/v1/templates/{template_id}POST /api/v1/templatesPUT /api/v1/templates/{template_id}DELETE /api/v1/templates/{template_id}POST /api/v1/templates/{template_id}/duplicateGET /api/v1/templates/categories/list
GET /api/v1/campaignsGET /api/v1/campaigns/{campaign_id}POST /api/v1/campaignsPUT /api/v1/campaigns/{campaign_id}DELETE /api/v1/campaigns/{campaign_id}POST /api/v1/campaigns/{campaign_id}/schedulePOST /api/v1/campaigns/{campaign_id}/send-nowPOST /api/v1/campaigns/{campaign_id}/pauseGET /api/v1/campaigns/{campaign_id}/recipients
GET /api/v1/subscribersPOST /api/v1/subscribersGET /api/v1/subscribers/{subscriber_id}PATCH /api/v1/subscribers/{subscriber_id}DELETE /api/v1/subscribers/{subscriber_id}POST /api/v1/subscribers/import-csvGET /api/v1/subscribers/export/csv
GET /api/v1/recipient-listsGET /api/v1/recipient-lists/defaultGET /api/v1/recipient-lists/{list_id}POST /api/v1/recipient-listsPUT /api/v1/recipient-lists/{list_id}DELETE /api/v1/recipient-lists/{list_id}GET /api/v1/recipient-lists/{list_id}/recipientsPOST /api/v1/recipient-lists/{list_id}/recipientsPOST /api/v1/recipient-lists/{list_id}/recipients/importPUT /api/v1/recipient-lists/{list_id}/recipients/{recipient_id}DELETE /api/v1/recipient-lists/{list_id}/recipients/{recipient_id}POST /api/v1/recipient-lists/{list_id}/add-from-subscribers
GET /api/v1/newsletter-designsPOST /api/v1/newsletter-designsGET /api/v1/newsletter-designs/{newsletter_id}PATCH /api/v1/newsletter-designs/{newsletter_id}DELETE /api/v1/newsletter-designs/{newsletter_id}POST /api/v1/newsletter-designs/{newsletter_id}/preview-htmlGET /api/v1/newsletter-designs/{newsletter_id}/htmlGET /api/v1/newsletter-designs/blocks/templates
POST /api/v1/newsletter-media/uploadGET /api/v1/newsletter-media/{media_id}DELETE /api/v1/newsletter-media/{media_id}
GET /api/v1/newsletters/publicGET /api/v1/newsletters/myPOST /api/v1/newsletters/GET /api/v1/newsletters/{newsletter_id}PUT /api/v1/newsletters/{newsletter_id}DELETE /api/v1/newsletters/{newsletter_id}POST /api/v1/newsletters/{newsletter_id}/schedulePOST /api/v1/newsletters/{newsletter_id}/sendGET /api/v1/newsletters/admin/all
GET /api/v1/content/pageGET /api/v1/content/sectionsGET /api/v1/content/sections/{section_id}POST /api/v1/admin/sectionsPUT /api/v1/admin/sections/{section_id}DELETE /api/v1/admin/sections/{section_id}POST /api/v1/admin/sections/{section_id}/contentPOST /api/v1/media/uploadDELETE /api/v1/media/{file_id}GET /api/v1/media/listPOST /api/v1/contactGET /api/v1/admin/contact-settingsPUT /api/v1/admin/contact-settingsPOST /api/v1/admin/contact-settings/testGET /api/v1/admin/email-settingsPOST /api/v1/admin/email-settings/PUT /api/v1/admin/email-settings/POST /api/v1/admin/email-settings/testGET /api/v1/admin/general-settingsPUT /api/v1/admin/general-settingsGET /api/v1/admin/usersGET /api/v1/admin/users/{user_id}POST /api/v1/admin/users/PUT /api/v1/admin/users/{user_id}PATCH /api/v1/admin/users/{user_id}/roleDELETE /api/v1/admin/users/{user_id}
GET /t/open/{tracking_token}GET /t/click/{tracking_token}?url=<target>GET /t/unsubscribe/{tracking_token}GET /robots.txtGET /sitemap.xml
GET /api/healthGET /7mail/api/health
cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reloadBackend docs: http://localhost:8000/docs
cd frontend
npm install
cp .env.example .env
npm run devFrontend dev: http://localhost:3000
cp .env.example .env
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
docker-compose up -d --buildImportant:
docker-compose.ymleste orientat pe infrastructura cu Traefik si retea externashop-online_web- serviciul
frontendnu expune port direct catre host (folosesteexpose), deci accesul browser depinde de proxy-ul Traefik - backend este expus pe
http://localhost:8000
- Email:
admin@example.com - Parola:
admin123
Schimba credentialele in orice mediu non-local.
DB_USERDB_PASSWORDDB_NAMEDB_PORTJWT_SECRET_KEYBACKEND_CORS_ORIGINSENVIRONMENTDEBUG
DATABASE_URLJWT_SECRET_KEYJWT_ALGORITHMACCESS_TOKEN_EXPIRE_MINUTESAPI_V1_STRPROJECT_NAMEPUBLIC_BASE_URLBACKEND_CORS_ORIGINSUPLOAD_DIRMAX_UPLOAD_SIZEADMIN_EMAILADMIN_PASSWORDENVIRONMENT
VITE_API_URLVITE_ENVIRONMENT
# Validare rapida structurala
bash validate.sh
# Deploy helper script local
bash deploy.sh local
# Loguri docker
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f postgres
# Oprire servicii
docker-compose down- Modelele
Campaign,RecipientListsiCampaignRecipientsunt inbackend/app/models/template.py. - Exista si fisierul
backend/app/routes/template_fixed.py, dar routerul incarcat in aplicatie estebackend/app/routes/template.py. - In
frontend/vite.config.ts,baseeste setat la/7mail/.
# Login
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"admin123"}'
# List templates (inlocuieste <TOKEN>)
curl -H "Authorization: Bearer <TOKEN>" \
http://localhost:8000/api/v1/templatesMIT
- GitHub: https://github.com/doimih/7mail