- 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
255 lines
6.6 KiB
Markdown
255 lines
6.6 KiB
Markdown
# 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**:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
3. **Edit `.env` with your credentials**
|
|
|
|
4. **Build and run with Docker Compose**:
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
5. **View logs**:
|
|
```bash
|
|
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:**
|
|
```env
|
|
SUMMARY_FILTER=Meeting
|
|
SUMMARY_FILTER_MODE=contains
|
|
INVERT_FILTER=false
|
|
```
|
|
|
|
**Import events starting with "Team" (regex):**
|
|
```env
|
|
SUMMARY_FILTER=^Team.*
|
|
SUMMARY_FILTER_MODE=regex
|
|
INVERT_FILTER=false
|
|
```
|
|
|
|
**Exclude dentist appointments:**
|
|
```env
|
|
SUMMARY_FILTER=Dentist
|
|
SUMMARY_FILTER_MODE=contains
|
|
INVERT_FILTER=true
|
|
```
|
|
|
|
**Import only exact match "Weekly Standup":**
|
|
```env
|
|
SUMMARY_FILTER=Weekly Standup
|
|
SUMMARY_FILTER_MODE=exact
|
|
INVERT_FILTER=false
|
|
```
|
|
|
|
## IMAP Connection Modes
|
|
|
|
The script supports different IMAP connection security modes:
|
|
|
|
### SSL/TLS (Recommended - Port 993)
|
|
Direct encrypted connection from the start:
|
|
```env
|
|
IMAP_USE_SSL=true
|
|
IMAP_USE_STARTTLS=false
|
|
IMAP_PORT=993
|
|
```
|
|
|
|
### STARTTLS (Port 143)
|
|
Starts unencrypted then upgrades to TLS:
|
|
```env
|
|
IMAP_USE_SSL=false
|
|
IMAP_USE_STARTTLS=true
|
|
IMAP_PORT=143
|
|
```
|
|
|
|
### Self-Signed Certificates
|
|
If your mail server uses self-signed certificates:
|
|
```env
|
|
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.
|
|
|
|
### Plain Connection (NOT RECOMMENDED)
|
|
Unencrypted connection:
|
|
```env
|
|
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:
|
|
|
|
```yaml
|
|
environment:
|
|
- RUN_ONCE=false
|
|
- CHECK_INTERVAL=300
|
|
```
|
|
|
|
### One-Time Mode
|
|
|
|
Run once and exit (useful with external schedulers like cron):
|
|
|
|
```yaml
|
|
environment:
|
|
- RUN_ONCE=true
|
|
```
|
|
|
|
Or run directly:
|
|
```bash
|
|
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
|
|
- Gmail: [Create app password](https://support.google.com/accounts/answer/185833)
|
|
- Nextcloud: Settings → Security → App passwords
|
|
|
|
2. **Protect your `.env` file**:
|
|
```bash
|
|
chmod 600 .env
|
|
```
|
|
|
|
3. **Never commit credentials** to version control:
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
```bash
|
|
docker build -t imap-calendar-importer .
|
|
```
|
|
|
|
Run with custom environment:
|
|
```bash
|
|
docker run --rm --env-file .env imap-calendar-importer
|
|
```
|
|
|
|
## License
|
|
|
|
MIT License - feel free to modify and use as needed.
|