Files
imap2caldav/README.md
Dan Head c87a99f570 Add IMAP to Nextcloud Calendar importer
- IMAP mailbox monitoring with SSL/TLS, STARTTLS and plain connection support
- ICS attachment extraction from emails and import to Nextcloud via CalDAV
- Create or update calendar events by UID to avoid duplicates
- Event filtering by summary (contains, regex or exact match, with inversion)
- Deduplication by regex pattern extracted from event summaries
- Move or mark processed emails as seen after import
- Continuous polling mode and one-time run mode
- Fully configurable via environment variables
- Docker and Docker Compose support
- Test suite with pytest
2026-04-03 09:47:45 +01:00

6.6 KiB

IMAP to Nextcloud Calendar Importer

Automatically monitors an IMAP mailbox for emails with ICS calendar attachments and imports them to your Nextcloud calendar.

Features

  • 📧 Monitors IMAP mailbox for new emails
  • 📅 Extracts ICS attachments and imports to Nextcloud
  • 🔍 Filter events by SUMMARY field (title)
  • 🔐 Supports SSL/TLS, STARTTLS, and self-signed certificates
  • 🐳 Fully Dockerized
  • ⚙️ Configurable via environment variables
  • 🔄 Continuous or one-time execution modes
  • 📝 Comprehensive logging

Quick Start

  1. Clone or download the files

  2. Create a .env file:

    cp .env.example .env
    
  3. Edit .env with your credentials

  4. Build and run with Docker Compose:

    docker-compose up -d
    
  5. View logs:

    docker-compose logs -f
    

Configuration

Required Environment Variables

Variable Description Example
IMAP_SERVER IMAP server hostname imap.gmail.com
IMAP_PORT IMAP port (usually 993) 993
IMAP_EMAIL Your email address user@example.com
IMAP_PASSWORD Email password or app password your-password
CALDAV_URL Nextcloud CalDAV URL https://cloud.example.com/remote.php/dav
CALDAV_USERNAME Nextcloud username username
CALDAV_PASSWORD Nextcloud password or app password your-password

Optional Environment Variables

Variable Default Description
IMAP_MAILBOX INBOX Mailbox to monitor
IMAP_PROCESSED_FOLDER Processed Folder for processed emails (if MOVE_PROCESSED=true)
IMAP_USE_SSL true Use direct SSL/TLS connection (port 993)
IMAP_USE_STARTTLS false Use STARTTLS (port 143) - set IMAP_USE_SSL=false first
IMAP_VERIFY_SSL true Verify SSL certificates (set to false for self-signed)
CALENDAR_NAME personal Target calendar name in Nextcloud
CALDAV_VERIFY_SSL true Verify SSL certificates (set to false for self-signed)
MARK_AS_SEEN true Mark processed emails as read
MOVE_PROCESSED false Move processed emails to separate folder
CHECK_INTERVAL 300 Seconds between checks (continuous mode)
RUN_ONCE false Run once and exit (useful for cron)
LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR)

Summary Filter Options

Filter calendar events by their SUMMARY (title) field:

Variable Default Description
SUMMARY_FILTER (empty) Filter pattern (leave empty to import all)
SUMMARY_FILTER_MODE contains Filter mode: contains, regex, or exact
INVERT_FILTER false If true, exclude matches instead of including

Filter Examples

Import only events with "Meeting" in the title:

SUMMARY_FILTER=Meeting
SUMMARY_FILTER_MODE=contains
INVERT_FILTER=false

Import events starting with "Team" (regex):

SUMMARY_FILTER=^Team.*
SUMMARY_FILTER_MODE=regex
INVERT_FILTER=false

Exclude dentist appointments:

SUMMARY_FILTER=Dentist
SUMMARY_FILTER_MODE=contains
INVERT_FILTER=true

Import only exact match "Weekly Standup":

SUMMARY_FILTER=Weekly Standup
SUMMARY_FILTER_MODE=exact
INVERT_FILTER=false

IMAP Connection Modes

The script supports different IMAP connection security modes:

Direct encrypted connection from the start:

IMAP_USE_SSL=true
IMAP_USE_STARTTLS=false
IMAP_PORT=993

STARTTLS (Port 143)

Starts unencrypted then upgrades to TLS:

IMAP_USE_SSL=false
IMAP_USE_STARTTLS=true
IMAP_PORT=143

Self-Signed Certificates

If your mail server uses self-signed certificates:

IMAP_VERIFY_SSL=false
CALDAV_VERIFY_SSL=false

Security Warning: Only disable SSL verification for trusted internal servers. This makes connections vulnerable to man-in-the-middle attacks.

Unencrypted connection:

IMAP_USE_SSL=false
IMAP_USE_STARTTLS=false

Usage Modes

Continuous Mode (Default)

The container runs continuously and checks for new emails every CHECK_INTERVAL seconds:

environment:
  - RUN_ONCE=false
  - CHECK_INTERVAL=300

One-Time Mode

Run once and exit (useful with external schedulers like cron):

environment:
  - RUN_ONCE=true

Or run directly:

docker-compose run --rm imap-calendar-importer

Finding Your Nextcloud Calendar Name

  1. Go to your Nextcloud calendar
  2. Click the three dots (⋮) next to your calendar
  3. Look at the calendar URL or settings
  4. The calendar name is usually visible in the settings or URL path

Alternatively, run the script with LOG_LEVEL=DEBUG to see all available calendars.

Security Best Practices

  1. Use app-specific passwords instead of your main account passwords

  2. Protect your .env file:

    chmod 600 .env
    
  3. Never commit credentials to version control:

    echo ".env" >> .gitignore
    

Troubleshooting

Can't connect to IMAP

  • Check server address and port
  • Verify credentials
  • For SSL/TLS use port 993, for STARTTLS use port 143
  • Enable "less secure apps" or use app-specific password
  • For self-signed certificates: set IMAP_VERIFY_SSL=false
  • Check firewall rules

Can't connect to CalDAV

  • Verify Nextcloud URL format: https://your-nextcloud.com/remote.php/dav
  • Check username and password
  • For self-signed certificates: set CALDAV_VERIFY_SSL=false
  • Ensure CalDAV is enabled in Nextcloud

Calendar not found

  • Check calendar name matches exactly
  • Run with LOG_LEVEL=DEBUG to see available calendars
  • Ensure you have access to the calendar

Events not being filtered correctly

  • Check your SUMMARY_FILTER pattern
  • Try SUMMARY_FILTER_MODE=contains for simple matching
  • Use LOG_LEVEL=DEBUG to see what summaries are being processed

Docker Commands

# Start the service
docker-compose up -d

# View logs
docker-compose logs -f

# Stop the service
docker-compose down

# Rebuild after code changes
docker-compose up -d --build

# Run once manually
docker-compose run --rm imap-calendar-importer

Development

Build the image manually:

docker build -t imap-calendar-importer .

Run with custom environment:

docker run --rm --env-file .env imap-calendar-importer

License

MIT License - feel free to modify and use as needed.