OpenMailer is an open source bulk email system with templates, built with Spring Boot 4.0, PostgreSQL, and Tailwind CSS.
- Prerequisites
- Project Setup
- Configuration
- Running the Application
- Build Commands
- Database Commands
- Liquibase Commands
- Tailwind CSS Commands
- Git Commands
- Project Structure
- Tech Stack
- Java 25 - Download
- Maven 3.9+ - (Included via Maven Wrapper)
- Node.js 18+ - For Tailwind CSS compilation
- PostgreSQL 14+ - Database server
git clone <repository-url>
cd openmailernpm installCopy the Liquibase properties template and configure your database:
cp src/main/resources/liquibase.properties.template src/main/resources/liquibase.propertiesEdit src/main/resources/application-dev.properties and add your database credentials:
spring.datasource.url=jdbc:postgresql://localhost:5432/openmailer
spring.datasource.username=your_username
spring.datasource.password=your_passwordnpm run build:css./mvnw clean packageThe application supports multiple profiles:
- dev - Development profile (default)
- prod - Production profile
Switch profiles by editing application.properties:
spring.profiles.active=devOr run with a specific profile:
./mvnw spring-boot:run -Dspring-boot.run.profiles=prodapplication.properties- Main configurationapplication-dev.properties- Development settingsapplication-prod.properties- Production settingsliquibase.properties- Liquibase Maven plugin settings
./mvnw spring-boot:runThe application will start at: http://localhost:8080
java -jar target/openmailer-0.0.1-SNAPSHOT.jarOpen two terminals:
Terminal 1 - Application:
./mvnw spring-boot:runTerminal 2 - Tailwind CSS:
npm run watch:cssThis auto-rebuilds CSS when you modify HTML templates.
./mvnw clean./mvnw compile./mvnw clean package -DskipTests./mvnw clean package./mvnw test./mvnw clean install./mvnw clean package -Pprod
npm run build:css:prodcreatedb openmailerOr using psql:
CREATE DATABASE openmailer;psql -d openmailer -U your_username\dtdropdb openmailerCreates XML from all existing tables:
./mvnw liquibase:generateChangeLogOutput: src/main/resources/db/changelog/db.changelog-generated.xml
After updating JPA entities, generate a changelog with differences:
./mvnw liquibase:diffOutput: src/main/resources/db/changelog/changes/diff-{timestamp}.xml
Apply all pending changelogs:
./mvnw liquibase:updateSee which changesets have been applied:
./mvnw liquibase:status./mvnw liquibase:rollback -Dliquibase.rollbackCount=1./mvnw liquibase:rollback -Dliquibase.rollbackDate=2025-01-01./mvnw liquibase:validate./mvnw liquibase:clearCheckSums./mvnw liquibase:tag -Dliquibase.tag=v1.0./mvnw liquibase:rollback -Dliquibase.rollbackTag=v1.0npm run build:cssnpm run watch:cssUse this during development - it watches for HTML changes and rebuilds CSS automatically.
npm run build:css:prodgit init
git add .
git commit -m "Initial commit"git add .
git commit -m "Your commit message"git push origin mastergit checkout -b feature/your-feature-namegit statusgit log --onelineopenmailer/
├── src/
│ ├── main/
│ │ ├── java/com/openmailer/openmailer/
│ │ │ ├── config/ # Configuration classes
│ │ │ │ └── SecurityConfig.java
│ │ │ ├── controller/ # REST and MVC controllers
│ │ │ │ └── HomeController.java
│ │ │ ├── dto/ # Data Transfer Objects
│ │ │ ├── exception/ # Custom exceptions
│ │ │ ├── model/ # JPA entities
│ │ │ │ ├── User.java
│ │ │ │ ├── EmailTemplate.java
│ │ │ │ └── EmailCampaign.java
│ │ │ ├── repository/ # Spring Data repositories
│ │ │ ├── service/ # Business logic
│ │ │ └── OpenmailerApplication.java
│ │ └── resources/
│ │ ├── db/changelog/
│ │ │ ├── changes/ # Individual migration files
│ │ │ │ ├── 001-create-users-table.xml
│ │ │ │ ├── 002-create-email-templates-table.xml
│ │ │ │ └── 003-create-email-campaigns-table.xml
│ │ │ └── db.changelog-master.xml
│ │ ├── static/
│ │ │ ├── css/
│ │ │ │ ├── input.css # Tailwind source
│ │ │ │ └── output.css # Generated CSS (gitignored)
│ │ │ ├── js/
│ │ │ └── images/
│ │ ├── templates/ # Thymeleaf templates
│ │ │ └── index.html
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ ├── application-prod.properties
│ │ ├── liquibase.properties (gitignored)
│ │ └── liquibase.properties.template
│ └── test/
│ └── java/com/openmailer/openmailer/
│ └── OpenmailerApplicationTests.java
├── .gitignore
├── mvnw # Maven wrapper (Unix)
├── mvnw.cmd # Maven wrapper (Windows)
├── package.json # NPM dependencies
├── pom.xml # Maven configuration
├── tailwind.config.js # Tailwind configuration
└── README.md
- Spring Boot 4.0 - Application framework
- Spring Data JPA - Database ORM
- Spring Security - Authentication & authorization
- Spring Mail - Email functionality
- PostgreSQL - Database
- Liquibase - Database migration management
- Thymeleaf - Template engine
- Tailwind CSS 3.4 - Utility-first CSS framework
- Heroicons - SVG icons
- Maven - Java dependency management
- NPM - Node package management
- User authentication and management
- Fields: id, username, email, password, enabled, created_at, updated_at
- Store reusable email templates
- Fields: id, name, subject, body, description, created_by, created_at, updated_at
- Manage bulk email campaigns
- Fields: id, name, template_id, status, scheduled_at, sent_at, total_recipients, sent_count, failed_count, created_by, created_at, updated_at
./mvnw clean package -DskipTests./mvnw test -Dtest=YourTestClass./mvnw spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"./mvnw dependency:tree./mvnw versions:display-dependency-updates./mvnw siteFor production deployment, set these environment variables:
DATABASE_URL=jdbc:postgresql://your-host:5432/openmailer
DATABASE_USERNAME=your_username
DATABASE_PASSWORD=your_password
MAIL_HOST=smtp.your-mail-server.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=your_email_passwordIf port 8080 is already in use, change it in application.properties:
server.port=8081- Verify PostgreSQL is running:
systemctl status postgresql - Check credentials in
application-dev.properties - Ensure database exists:
psql -l
- Verify database connection
- Check
liquibase.propertiesconfiguration - Clear checksums:
./mvnw liquibase:clearCheckSums
- Ensure output.css is generated:
npm run build:css - Check browser console for CSS loading errors
- Verify path in HTML:
/css/output.css
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
This project is open source and available under the MIT License.
For issues and questions:
- Create an issue in the repository
- Email: [email protected]
Built with Spring Boot, PostgreSQL, and Tailwind CSS.