Files
TimeTracker/docs/EMAIL_CONFIGURATION.md
Dries Peeters 543be51c15 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
2025-10-27 10:13:58 +01:00

11 KiB

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:

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

# 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

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 when 2-factor authentication is enabled.

Outlook / Office 365

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

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

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

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 AdminEmail 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 AdminEmail Configuration
  4. Review the configuration status
  5. Send a test email

Using the Command Line

You can also test email configuration programmatically:

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:

<!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:

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:

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:

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

  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:

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:

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
  2. Review application logs
  3. Test with a simple SMTP client to verify credentials
  4. Check your email provider's documentation