feat(admin): improve email configuration UI and logging

Enhance the email support feature with better UX and debugging capabilities:

- **Fix input field styling**: Update all form inputs to use project-standard
  'form-input' class and consistent checkbox styling matching other admin
  pages for uniform appearance across the application

- **Add comprehensive logging**: Implement detailed logging throughout email
  operations with clear prefixes ([EMAIL TEST], [EMAIL CONFIG]) to track:
  - Email configuration changes and validation
  - Test email sending process step-by-step
  - SMTP connection details and status
  - Success/failure indicators (✓/✗) for quick troubleshooting

- **Auto-reload after save**: Page now automatically refreshes 1.5 seconds
  after successfully saving email configuration to ensure UI reflects the
  latest settings and eliminate stale data

These improvements provide better visual consistency, easier debugging of
email issues, and smoother user experience when configuring email settings.

Files modified:
- app/templates/admin/email_support.html
- app/utils/email.py
- app/routes/admin.py
This commit is contained in:
Dries Peeters
2025-10-27 10:13:58 +01:00
parent e1188870e4
commit 543be51c15
12 changed files with 2328 additions and 2 deletions

426
docs/EMAIL_CONFIGURATION.md Normal file
View File

@@ -0,0 +1,426 @@
# Email Configuration Guide
This guide explains how to configure and use the email functionality in TimeTracker.
## Overview
TimeTracker includes built-in email support for:
- Test emails to verify configuration
- Invoice notifications
- Task assignment notifications
- Weekly time summaries
- Comment mentions
- System alerts
## Configuration Methods
TimeTracker supports two ways to configure email:
### 1. **Database Configuration** (Recommended)
Configure email settings through the admin web interface. Settings are saved to the database and persist between sessions.
**Advantages:**
- No server restart required for changes
- Easy to update via web interface
- Settings persist in database
- Can be changed by admins without server access
**To Use:**
1. Navigate to Admin → Email Configuration
2. Check "Enable Database Email Configuration"
3. Fill in the form and save
### 2. **Environment Variables** (Fallback)
Configure email settings through environment variables. These serve as defaults when database configuration is disabled.
**Advantages:**
- More secure for sensitive credentials
- Standard configuration method
- Works without database access
**To Use:**
Add settings to your `.env` file or environment
---
## Configuration Hierarchy
Email settings are loaded in this order (highest priority first):
1. **Database Settings** (when `mail_enabled` is `True` in settings table)
2. **Environment Variables** (fallback)
3. **Default Values**
## Database Configuration
Email settings are configured through environment variables. Add these to your `.env` file or set them in your environment:
### Basic SMTP Configuration
```bash
# SMTP Server Settings
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USE_SSL=false
# Authentication
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
# Sender Information
MAIL_DEFAULT_SENDER=noreply@yourdomain.com
# Optional: Maximum emails per connection
MAIL_MAX_EMAILS=100
```
### Configuration Options
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `MAIL_SERVER` | SMTP server hostname | `localhost` | Yes |
| `MAIL_PORT` | SMTP server port | `587` | Yes |
| `MAIL_USE_TLS` | Use TLS encryption | `true` | No |
| `MAIL_USE_SSL` | Use SSL encryption | `false` | No |
| `MAIL_USERNAME` | SMTP username for authentication | None | Yes (for most providers) |
| `MAIL_PASSWORD` | SMTP password | None | Yes (for most providers) |
| `MAIL_DEFAULT_SENDER` | Default "From" address | `noreply@timetracker.local` | Yes |
| `MAIL_MAX_EMAILS` | Max emails per SMTP connection | `100` | No |
## Common Email Providers
### Gmail
```bash
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_DEFAULT_SENDER=your-email@gmail.com
```
**Important:** Gmail requires an [App Password](https://support.google.com/accounts/answer/185833) when 2-factor authentication is enabled.
### Outlook / Office 365
```bash
MAIL_SERVER=smtp.office365.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=your-email@outlook.com
MAIL_PASSWORD=your-password
MAIL_DEFAULT_SENDER=your-email@outlook.com
```
### SendGrid
```bash
MAIL_SERVER=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=apikey
MAIL_PASSWORD=your-sendgrid-api-key
MAIL_DEFAULT_SENDER=noreply@yourdomain.com
```
### Amazon SES
```bash
MAIL_SERVER=email-smtp.us-east-1.amazonaws.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=your-smtp-username
MAIL_PASSWORD=your-smtp-password
MAIL_DEFAULT_SENDER=noreply@yourdomain.com
```
Replace `us-east-1` with your AWS region.
### Mailgun
```bash
MAIL_SERVER=smtp.mailgun.org
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=postmaster@yourdomain.mailgun.org
MAIL_PASSWORD=your-mailgun-password
MAIL_DEFAULT_SENDER=noreply@yourdomain.com
```
## Testing Email Configuration
### Using the Admin Panel (Database Configuration)
1. Log in as an administrator
2. Navigate to **Admin****Email Configuration**
3. **Configure Settings**:
- Check "Enable Database Email Configuration"
- Fill in: Mail Server, Port, Username, Password, etc.
- Click "Save Configuration"
4. **Test Configuration**:
- Review the configuration status (should show "configured")
- Enter your email address in the test form
- Click "Send Test Email"
- Check your inbox for the test email
### Using Environment Variables
1. Set environment variables in `.env`
2. Restart the application
3. Navigate to **Admin****Email Configuration**
4. Review the configuration status
5. Send a test email
### Using the Command Line
You can also test email configuration programmatically:
```python
from app import create_app
from app.utils.email import send_test_email
app = create_app()
with app.app_context():
success, message = send_test_email('your-email@example.com', 'Test')
print(f"Success: {success}")
print(f"Message: {message}")
```
## Troubleshooting
### Email Not Sending
1. **Check Configuration Status**
- Go to Admin → Email Configuration
- Review any errors or warnings displayed
2. **Verify Credentials**
- Ensure username and password are correct
- For Gmail, use an App Password, not your regular password
3. **Check Firewall Rules**
- Ensure outbound connections to SMTP port are allowed
- Test connectivity: `telnet smtp.gmail.com 587`
4. **Review Logs**
- Check application logs for email-related errors
- Look for SMTP authentication or connection errors
5. **TLS/SSL Configuration**
- Don't enable both `MAIL_USE_TLS` and `MAIL_USE_SSL`
- Use TLS (port 587) for most modern SMTP servers
- Use SSL (port 465) only if required by your provider
### Common Error Messages
#### "Mail server not configured"
- Set `MAIL_SERVER` environment variable
- Ensure it's not set to `localhost`
#### "Authentication failed"
- Verify `MAIL_USERNAME` and `MAIL_PASSWORD`
- For Gmail, generate an App Password
- Check if your account requires 2FA
#### "Connection refused"
- Check firewall rules
- Verify SMTP port is correct (587 for TLS, 465 for SSL, 25 for unencrypted)
- Ensure server can reach SMTP host
#### "TLS/SSL handshake failed"
- Check `MAIL_USE_TLS` and `MAIL_USE_SSL` settings
- Ensure only one is enabled
- Verify port matches TLS/SSL setting
## Security Best Practices
1. **Use App Passwords**
- Never use your main account password
- Generate app-specific passwords for Gmail, Outlook, etc.
2. **Use Environment Variables**
- Never commit email credentials to version control
- Use `.env` file (excluded from git)
- Use secrets management in production
3. **Use Dedicated Email Service**
- For production, use SendGrid, Amazon SES, or similar
- These provide better deliverability and monitoring
- Personal email accounts may have sending limits
4. **Configure SPF/DKIM/DMARC**
- Set up proper DNS records for your sending domain
- Improves email deliverability
- Reduces likelihood of emails being marked as spam
5. **Limit Default Sender**
- Use a proper noreply address
- Don't use personal email as default sender
## Email Templates
Email templates are located in `app/templates/email/`. Available templates:
- `test_email.html` - Test email template
- `overdue_invoice.html` - Overdue invoice notification
- `task_assigned.html` - Task assignment notification
- `weekly_summary.html` - Weekly time summary
- `comment_mention.html` - Comment mention notification
### Customizing Templates
To customize email templates:
1. Navigate to `app/templates/email/`
2. Edit the HTML template files
3. Use Jinja2 syntax for dynamic content
4. Test your changes using the admin panel
Example:
```html
<!DOCTYPE html>
<html>
<body>
<h1>Hello {{ user.display_name }}!</h1>
<p>{{ message }}</p>
</body>
</html>
```
## API Reference
### `send_email(subject, recipients, text_body, html_body=None, sender=None, attachments=None)`
Send an email message.
**Parameters:**
- `subject` (str): Email subject line
- `recipients` (list): List of recipient email addresses
- `text_body` (str): Plain text email body
- `html_body` (str, optional): HTML email body
- `sender` (str, optional): Sender email address (defaults to `MAIL_DEFAULT_SENDER`)
- `attachments` (list, optional): List of (filename, content_type, data) tuples
**Example:**
```python
from app.utils.email import send_email
send_email(
subject='Welcome to TimeTracker',
recipients=['user@example.com'],
text_body='Welcome to our application!',
html_body='<p>Welcome to our application!</p>'
)
```
### `test_email_configuration()`
Test email configuration and return status.
**Returns:**
- `dict`: Configuration status with keys:
- `configured` (bool): Whether email is properly configured
- `settings` (dict): Current email settings
- `errors` (list): Configuration errors
- `warnings` (list): Configuration warnings
**Example:**
```python
from app.utils.email import test_email_configuration
status = test_email_configuration()
if status['configured']:
print("Email is configured!")
else:
print("Errors:", status['errors'])
```
### `send_test_email(recipient_email, sender_name='TimeTracker Admin')`
Send a test email to verify configuration.
**Parameters:**
- `recipient_email` (str): Email address to send test to
- `sender_name` (str, optional): Name of sender
**Returns:**
- `tuple`: (success: bool, message: str)
**Example:**
```python
from app.utils.email import send_test_email
success, message = send_test_email('test@example.com')
if success:
print("Test email sent!")
else:
print("Error:", message)
```
## Docker Configuration
### Option 1: Database Configuration (Recommended)
1. Start TimeTracker with Docker
2. Log in as administrator
3. Navigate to Admin → Email Configuration
4. Configure email through the web interface
5. No restart needed!
### Option 2: Environment Variables
When running TimeTracker in Docker, add email configuration to your `docker-compose.yml`:
```yaml
services:
app:
environment:
- MAIL_SERVER=smtp.gmail.com
- MAIL_PORT=587
- MAIL_USE_TLS=true
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
- MAIL_DEFAULT_SENDER=${MAIL_DEFAULT_SENDER}
```
Then set the values in your `.env` file:
```bash
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_DEFAULT_SENDER=noreply@yourdomain.com
```
**Note:** Database configuration (Option 1) takes precedence when enabled.
## Advanced Configuration
### Rate Limiting
The email test endpoint is rate-limited to 5 requests per minute to prevent abuse.
### Asynchronous Sending
Emails are sent asynchronously in background threads to avoid blocking the main application. This is handled automatically.
### Connection Pooling
Flask-Mail manages SMTP connection pooling automatically based on `MAIL_MAX_EMAILS` setting.
## Support
For issues with email configuration:
1. Check the [GitHub Issues](https://github.com/yourusername/timetracker/issues)
2. Review application logs
3. Test with a simple SMTP client to verify credentials
4. Check your email provider's documentation
## Related Documentation
- [Admin Panel Guide](ADMIN_GUIDE.md)
- [Configuration Guide](CONFIGURATION.md)
- [Deployment Guide](../DEPLOYMENT_GUIDE.md)