Frank John Begornia d0d82aa8e1 Unified email reports
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2019-11-04 17:12:11 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2019-11-04 17:12:11 +08:00
2019-11-04 17:12:11 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2026-01-02 01:19:07 +08:00
2020-03-19 23:14:11 +08:00

Email Reports - Dockerized Container

Unified Docker container for automated daily order email reports for both Crew Sportswear and MerchBay.

Overview

This container runs cron jobs daily at 23:55 CT to:

  1. Query orders from both Crew and MerchBay databases
  2. Generate separate CSV reports for each brand
  3. Email reports to recipients via SMTP

Cron Schedule:

  • 23:55 - Crew Sportswear report
  • 23:56 - MerchBay report

Quick Start

1. Create .env file

cp .env.example .env
vim .env

Configure your environment variables:

# Crew Database
DB_HOST_CREW=mysql
DB_NAME_CREW=custom_design
DB_USER_CREW=crew_user
DB_PASS_CREW=your_password

# MerchBay Database
DB_HOST_MERCHBAY=mysql
DB_NAME_MERCHBAY=merchbay_laravel
DB_USER_MERCHBAY=merchbay_user
DB_PASS_MERCHBAY=your_password

# SMTP
SMTP_PASS_CREW=crew_gmail_app_password
SMTP_PASS_MERCHBAY=merchbay_gmail_app_password

2. Build and Run

# Build image
docker-compose build

# Start container
docker-compose up -d

# Check logs
docker logs -f email_reports_crew

3. Test Manually

# Test Crew report
docker exec email_reports_unified BRAND=crew php /app/send_report.php

# Test MerchBay report
docker exec email_reports_unified BRAND=merchbay php /app/send_report.php

# Check cron log
docker exec email_reports_unified tail -f /var/log/cron.log

# Check email log (shows both brands)
docker exec email_reports_unified tail -f /app/email.log

┌──────────────────────────────────────────┐ │ Email Reports Container (Unified) │ │ │ │ ┌────────────────────────────────────┐ │ │ │ Cron Jobs: │ │ │ │ 23:55 → BRAND=crew │ │ │ │ 23:56 → BRAND=merchbay │ │ │ │ │ │ │ │ send_report.php │ │ │ │ └─ PHPMailer │ │ │ └────────────────────────────────────┘ │ │ │ │ └─────────────┼────────────────────────────┘ │ ├──> MySQL: custom_design (Crew) ├──> MySQL: merchbay_laravel (MerchBay) └──> SMTP: Gmail (2 accounts) │ ├──────> MySQL (crew-app-net) └──────> SMTP (smtp.gmail.com)


## Fsend_report.php** - Unified report generator (handles both brands)
- **index.php** - Legacy Crew report (kept for backward compatibility)
- **dbconfig.php** - Database connection (env-aware)
- **phpmailer/** - Email library

## Cron Schedule

```cron
55 23 * * * BRAND=crew php /app/send_report.php >> /var/log/cron.log 2>&1
56 23 * * * BRAND=merchbay php /app/send_report.php >> /var/log/cron.log 2>&1

23:55 CT - Crew Sportswear
23:56 CT - MerchBay

Both run daily, 1 minute apart. 55 23 * * * cd /app && php index.php >> /var/log/cron.log 2>&1


Runs daily at **11:55 PM Central Time**

## Environment Variables

### Crew Sportswear

| Variable | Default | Description |
|----------|---------|-------------|
| DB_HOST_CREW | mysql | MySQL host for Crew |
| DB_PORT_CREW | 3306 | MySQL port |
| DB_NAME_CREW | custom_design | Crew database name |
| DB_USER_CREW | crew_user | Crew database username |
| DB_PASS_CREW | - | Crew database password |
| SMTP_PASS_CREW | - | Gmail app password for mail@crewsportswear.com |

### MerchBay

| Variable | Default | Description |
|----------|---------|-------------|
| DB_HOST_MERCHBAY | mysql | MySQL host for MerchBay |
| DB_PORT_MERCHBAY | 3306 | MySQL port |
| DB_NAME_MERCHBAY | merchbay_laravel | MerchBay database name |
| DB_USER_MERCHBAY | merchbay_user | MerchBay database username |
| DB_PASS_MERCHBAY | - | MerchBay database password |
| SMTP_PASS_MERCHBAY | - | Gmail app password for support@merchbay.com |

### Shared

| Variable | Default | Description |
|----------|---------|-------------|
| SMTP_HOST | smtp.gmail.com | SMTP server |
| SMTP_PORT | 587 | SMTP port |

## Brand Configuration

The unified container handles both brands using the `BRAND` environment variable:

**Crew Sportswear (`BRAND=crew`)**:
- Database: `custom_design`
- From: `orders@crewsportswear.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, angelo, production @crewsportswear.com
- Admin: https://admin.crewsportswear.app
- CSV: `daily_order_reports_crew/`

**MerchBay (`BRAND=merchbay`)**:
- Database: `merchbay_laravel`
- From: `orders@merchbay.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, production @crewsportswear.com
- Admin: https://merchbay.app
- CSV: `daily_order_reports_merchbay/`

## Networks

Container must be on **crew-app-net** to access MySQL:

```yaml
networks:
  - crew-app-net

networks:
  crew-app-net:
    external: true

Create network if it doesn't exist:

docker network create crew-app-net

Volumes

volumes:
  - ./daily_order_reports_crew:/app/daily_order_reports_crew      # Crew CSV archives
  - ./daily_order_reports_merchbay:/app/daily_order_reports_merchbay  # MerchBay CSV archives
  - ./email.log:/app/email.log  # Combined execution log

Both brands write to the same email.log with prefixes [CREW] and [MERCHBAY].

Deployment

Automated Deployment (Gitea Actions)

Production deployment is automated via Gitea Actions when pushing to main or master branch.

# Trigger deployment
git add .
git commit -m "Update email reports"
git push origin main

The workflow will:

  1. Build Docker image
  2. Transfer to production server via SSH
  3. Deploy to /var/www/apps/email_reports
  4. Start container with cron
  5. Verify container is running

Registry build is triggered by version tags:

# Create version tag
git tag v1.0.0
git push origin v1.0.0

This builds and pushes to your Docker registry.

Manual Deployment

# Deploy via docker-compose
docker-compose up -d --build

# Or build specific image version
docker build -t email-reports:1.0.0 .
docker tag email-reports:1.0.0 your-registry/email-reports:1.0.0
docker push your-registry/email-reports:1.0.0

Required Gitea Secrets

Configure in your repository settings:

  • DEPLOY_SSH_KEY - SSH private key for deployment server
  • DEPLOY_HOST - Deployment server hostname/IP
  • DEPLOY_USER - SSH username
  • REGISTRY_URL - Docker registry URL (for version tags)
  • REGISTRY_USER - Registry username
  • REGISTRY_PASSWORD - Registry password

Server Setup (First Time)

On your production server, create the deployment directory and .env file:

# Create directory
sudo mkdir -p /var/www/apps/email_reports
sudo chown $USER:$USER /var/www/apps/email_reports
cd /var/www/apps/email_reports

# Create .env file
cat > .env << 'EOL'
DB_HOST=mysql
DB_PORT=3306
DB_NAME=custom_design
DB_USER=crew_user
DB_PASS=your_secure_password

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=mail@crewsportswear.com
SMTP_PASS=your_gmail_app_password

EMAIL_TO=graphics@crewsportswear.com
EMAIL_BCC=webmaster@crewsportswear.com,angelo@crewsportswear.com,production@crewsportswear.com

APP_URL=https://www.crewsportswear.com
ADMIN_URL=https://admin.crewsportswear.app
EOL

chmod 600 .env

# Create data directories
mkdir -p daily_order_reports
touch email.log
chmod 666 email.log

# Ensure network exists
docker network create crew-app-net || true

Now push to trigger the first deployment!

Multiple Instances

For MerchBay, create similar setup in email_reports_merchbay/:

# docker-compose.yml in email_reports_merchbay/
services:
  email-reports-merchbay:
    build: .
    container_name: email_reports_merchbay
    environment:
      - DB_NAME=merchbay_db
      - EMAIL_TO=orders@merchbay.com
      # ... other env vars

Monitoring

Check Container Health

# Container status
docker ps | grep email_reports

# Should show email_reports_unified

# Health check
docker inspect email_reports_unified | grep -A 5 Health

View Logs

# Real-time cron logs (both brands)
docker exec email_reports_unified tail -f /var/log/cron.log

# Email execution logs (prefixed by brand)
docker exec email_reports_unified tail -f /app/email.log

# Example log output:
# 2026-01-02 23:55:00   [CREW] successfully sent (5 orders)
# 2026-01-02 23:56:00   [MERCHBAY] No order for today

# Last 50 lines
docker logs --tail 50 email_reports_unified

# Filter by brand
docker exec email_reports_unified grep "\[CREW\]" /app/email.log | tail -10
docker exec email_reports_unified grep "\[MERCHBAY\]" /app/email.log | tail -10

Verify Cron Schedule

# View active crontab (should show both jobs)
docker exec email_reports_unified crontab -l

# Expected:
# 55 23 * * * BRAND=crew php /app/send_report.php >> /var/log/cron.log 2>&1
# 56 23 * * * BRAND=merchbay php /app/send_report.php >> /var/log/cron.log 2>&1

# Check if cron is running
docker exec email_reports_unified ps aux | grep crond

Troubleshooting

Database Connection Failed

# Test MySQL connectivity
docker exec email_reports_crew ping mysql

# Test database connection
docker exec email_reports_crew php -r "new PDO('mysql:host=mysql;dbname=custom_design', 'user', 'pass');"

# Check network
docker network inspect crew-app-net

Email Not Sending

# Enable debug mode
docker exec email_reports_crew sed -i 's|// \$mail->SMTPDebug|\$mail->SMTPDebug|' /app/index.php

# Run manually with debug
docker exec email_reports_crew php /app/index.php

# Check SMTP credentials in .env

Cron Not Running

# Check cron daemon
docker exec email_reports_crew ps aux | grep crond

# Restart container
docker restart email_reports_crew

# View crontab
docker exec email_reports_crew cat /etc/crontabs/root

Wrong Timezone

# Verify timezone
docker exec email_reports_crew date
docker exec email_reports_crew cat /etc/timezone

# Should show: America/Chicago

Permissions Issues

# Fix CSV directory permissions
docker exec email_reports_crew chmod 755 /app/daily_order_reports

# Fix log file
docker exec email_reports_crew chmod 666 /app/email.log

Maintenance

Update Cron Schedule

Edit Dockerfile and rebuild:

RUN echo "30 22 * * * cd /app && php index.php" > /etc/crontabs/root

Rotate Logs

# Manually clear logs (optional)
docker exec email_reports_crew truncate -s 0 /var/log/cron.log
docker exec email_reports_crew truncate -s 0 /app/email.log

Backup Reports

# Archive old CSV files
tar -czf daily_reports_backup_$(date +%Y%m%d).tar.gz daily_order_reports/

# Or sync to S3/backup location

Security

  1. Never commit .env - Use .env.example only
  2. Use Gmail App Passwords - Not your main password
  3. Restrict network access - Only join necessary networks
  4. Rotate credentials - Change passwords regularly
  5. Monitor logs - Check for unauthorized access

Advantages of Separate Container

Isolation - Reports run independently of web apps Reusability - Can serve multiple apps (Crew + MerchBay) Simple Deployment - Single purpose, easy to update Resource Control - Limit CPU/memory for cron jobs Independent Scaling - Restart without affecting web traffic Clean Separation - No coupling with Laravel/framework

Next Steps

  1. Test database connectivity
  2. Verify SMTP credentials
  3. Run manual test: docker exec email_reports_crew php /app/index.php
  4. Wait for 23:55 or adjust cron for testing
  5. Monitor logs for first automated run
  6. Set up similar container for MerchBay reports
Description
Email report sender in crew and merchbay
Readme 411 KiB
Languages
PHP 87.1%
CSS 8.6%
HTML 3.3%
Shell 0.7%
Dockerfile 0.3%