Python-Script zum Versenden und Lesen von E-Mails via SMTP/IMAP mit JSON-Output und Batch-Support.
Python: 3.7+
Dependencies: Keine! Nutzt nur Python Standard Library:
smtplib- SMTP clientimaplib- IMAP clientemail- Email message handlingjson- JSON parsing/outputcsv- CSV file parsingargparse- CLI argument parsingpathlib- File path handlingre- Email validation
1. Repository klonen:
git clone https://github.com/kreasteve/shellmail.git
cd shellmail2. Ausführbar machen:
chmod +x send_email.py3. Konfigurieren:
./send_email.py setup4. Testen:
./send_email.py -t your@email.com -s "Test" -m "Hello World"Optional - Globale Installation:
# Symlink erstellen für systemweite Nutzung
sudo ln -s $(pwd)/send_email.py /usr/local/bin/shellmail
# Dann von überall:
shellmail -t user@example.com -s "Test" -m "Hello"✅ Versteckte Config - Zugangsdaten sicher in .email_config.json (neben dem Script oder in ~/)
✅ JSON Output - Strukturierte, parsbare Ausgaben für KI/Automation
✅ Batch-Versand - Mehrere Empfänger aus CSV/Text-Datei
✅ Category-System - Filter Empfänger nach Alert-Level (Notfall, Error, Info, etc.)
✅ Email-Validierung - Prüft Adressen vor dem Versand
✅ Exit Codes - Verschiedene Codes für verschiedene Fehlertypen
✅ IMAP Empfang - Postfach lesen, filtern nach Absender/Zeit, als gelesen markieren
1. Einmalige Konfiguration:
cd ~/email
./send_email.py setup2. E-Mail senden:
./send_email.py -t empfaenger@example.com -s "Betreff" -m "Nachricht"Einzelne E-Mail mit JSON:
./send_email.py --json -t user@example.com -s "Test" -m "Hello"Output:
{
"status": "success",
"code": 0,
"message": "Email sent successfully",
"to": "user@example.com",
"subject": "Test",
"from": "mt@kreasteve.de",
"attachments": [],
"message_id": "",
"timestamp": "2026-01-27T08:26:57.787158",
"elapsed_seconds": 0.35
}Exit Codes:
0- Erfolg1- Konfigurationsfehler2- Versandfehler3- Validierungsfehler4- Dateifehler
recipients.txt:
admin@example.com
dev@example.com
monitor@example.com
Versenden:
./send_email.py --batch recipients.txt -s "Maintenance" -m "Server wird gewartet"alerts.csv:
email,categories,name
admin@example.com,"Notfall,Error,Ausfall",Admin Team
developer@example.com,"Error,Info",Dev Team
monitor@example.com,"Info,Erfolg",Monitoring
oncall@example.com,"Notfall,Ausfall",On-Call Team
report@example.com,"Erfolg,Info",Report TeamBeispiele:
# Nur an "Notfall"-Empfänger senden
./send_email.py --batch alerts.csv --category "Notfall" \
-s "NOTFALL: Server down" -m "Kritischer Ausfall!"
# An "Error" ODER "Info" senden
./send_email.py --batch alerts.csv --category "Error" --category "Info" \
-s "Update" -m "Neues Update verfügbar"
# Alle Empfänger (keine Filter)
./send_email.py --batch alerts.csv -s "Newsletter" -m "Monatlicher Report"
# Mit JSON Output
./send_email.py --json --batch alerts.csv --category "Notfall" \
-s "Alert" -m "Kritischer Fehler"Batch-JSON-Output:
{
"status": "batch",
"code": 0,
"total": 2,
"success": 2,
"failed": 0,
"details": [
{
"status": "success",
"code": 0,
"message": "Email sent successfully",
"to": "admin@example.com",
...
},
{
"status": "success",
"code": 0,
"message": "Email sent successfully",
"to": "oncall@example.com",
...
}
],
"timestamp": "2026-01-27T09:04:16.373143"
}# Alle Emails (JSON)
shellmail check --json
# Nur ungelesene
shellmail check --unread
# Von bestimmtem Absender
shellmail check --from boss@example.com
# Seit heute
shellmail check --since today
# Letzte Stunde
shellmail check --since 1h
# Letzte 30 Minuten
shellmail check --since 30m
# Letzte 2 Tage
shellmail check --since 2d
# Kombiniert
shellmail check --from boss@example.com --since today --jsoncheck JSON-Output:
{
"status": "success",
"code": 0,
"count": 2,
"emails": [
{
"uid": "42",
"message_id": "<abc123@mail.example.com>",
"from": "boss@example.com",
"subject": "Weekly Report",
"date": "Fri, 13 Mar 2026 10:00:00 +0100",
"unread": true,
"body": "Please review the attached..."
}
],
"timestamp": "2026-03-13T11:00:00.000000"
}# Email mit UID lesen (UID kommt aus 'check' Output)
shellmail read 42
# Als JSON
shellmail read 42 --jsonDie Email wird automatisch als gelesen markiert (unread: false).
read JSON-Output:
{
"status": "success",
"code": 0,
"uid": "42",
"message_id": "<abc123@mail.example.com>",
"from": "boss@example.com",
"subject": "Weekly Report",
"date": "Fri, 13 Mar 2026 10:00:00 +0100",
"unread": false,
"body": "Please review the attached...",
"timestamp": "2026-03-13T11:00:00.000000"
}Statt regelmäßig zu pollen wartet wait per IMAP IDLE-Protokoll auf eine Server-Push-Benachrichtigung. Das Script blockiert bis eine neue Email eintrifft (oder der Timeout abläuft) und gibt sie dann sofort aus.
# Auf nächste Email warten (max. 5 Minuten, Standard)
shellmail wait --json
# Nur auf Email von bestimmtem Absender warten
shellmail wait --from boss@example.com --json
# Mit eigenem Timeout (60 Sekunden)
shellmail wait --from boss@example.com --timeout 60 --json
# Human-readable Output
shellmail wait --from boss@example.comVerhalten:
- Nutzt IMAP IDLE (RFC 2177) – keine Polling-Schleife
- Wenn der Timeout abläuft ohne passende Email: Ausgabe
NO_NEW_EMAIL, Exit-Code 5 - Wenn eine Email ankommt: wird gelesen, als gelesen markiert und ausgegeben
- Gibt Fehler aus, wenn der IMAP-Server IDLE nicht unterstützt
wait JSON-Output (Email gefunden):
{
"status": "success",
"code": 0,
"uid": "43",
"message_id": "<xyz@mail.example.com>",
"from": "boss@example.com",
"subject": "Dringende Anfrage",
"date": "Fri, 13 Mar 2026 11:30:00 +0100",
"unread": false,
"body": "Bitte sofort melden...",
"timestamp": "2026-03-13T11:30:05.000000"
}wait JSON-Output (Timeout):
{
"status": "timeout",
"code": 5,
"message": "NO_NEW_EMAIL",
"timestamp": "2026-03-13T11:35:00.000000"
}Verwendung in Scripts:
RESULT=$(shellmail wait --from boss@example.com --timeout 120 --json)
STATUS=$(echo "$RESULT" | jq -r '.status')
if [ "$STATUS" = "success" ]; then
SUBJECT=$(echo "$RESULT" | jq -r '.subject')
echo "Neue Email: $SUBJECT"
elif [ "$STATUS" = "timeout" ]; then
echo "Keine neue Email innerhalb des Timeouts"
fiDas Script nutzt dieselben Zugangsdaten (smtp_user / smtp_pass) für IMAP. Nur IMAP-Host und Port müssen zusätzlich konfiguriert werden:
{
"smtp_host": "smtp.strato.de",
"smtp_port": 587,
"smtp_tls": true,
"smtp_user": "deine@domain.de",
"smtp_pass": "passwort",
"smtp_from": "deine@domain.de",
"imap_host": "imap.strato.de",
"imap_port": 993,
"imap_ssl": true
}Beim setup-Wizard werden die IMAP-Einstellungen für Gmail, Outlook und Strato automatisch gesetzt.
| Provider | imap_host | imap_port | imap_ssl |
|---|---|---|---|
| Strato | imap.strato.de | 993 | true |
| Gmail | imap.gmail.com | 993 | true |
| Outlook | outlook.office365.com | 993 | true |
# Python-Script ruft Email-Tool auf
if error_level == "critical":
subprocess.run([
"./send_email.py", "--json",
"--batch", "alerts.csv",
"--category", "Notfall",
"-s", f"CRITICAL: {error_msg}",
"-m", error_details
])
result = json.loads(output)#!/bin/bash
RESULT=$(./send_email.py --json -t admin@example.com \
-s "Test" -m "Hello" 2>&1)
STATUS=$(echo "$RESULT" | jq -r '.status')
CODE=$(echo "$RESULT" | jq -r '.code')
if [ "$STATUS" = "success" ]; then
echo "Email sent successfully"
else
echo "Failed with code $CODE"
exit $CODE
fi./send_email.py --json --batch users.csv -s "Update" -m "..." > result.json
# Parse Ergebnisse
SUCCESS=$(jq '.success' result.json)
FAILED=$(jq '.failed' result.json)
if [ "$FAILED" -gt 0 ]; then
# Handle failures
jq '.details[] | select(.status=="error")' result.json
fiMit Anhang:
./send_email.py -t user@example.com -s "Report" \
-m "Anbei der Report" -a report.pdf -a data.csvHTML-Email:
./send_email.py -t user@example.com -s "Newsletter" \
--html-file newsletter.htmlNachricht aus Datei:
./send_email.py -t user@example.com -s "Bericht" \
--text-file nachricht.txtVerbose + JSON:
./send_email.py --json -v -t user@example.com -s "Test" -m "Hello"
# Verbose geht nach stderr, JSON nach stdout# Anzeigen
./send_email.py show-config
# Neu einrichten
./send_email.py setup
# Manuell bearbeiten (Pfad je nach Setup)
nano .email_config.json
# oder
nano ~/.email_config.jsonFormat:
{
"smtp_host": "smtp.strato.de",
"smtp_port": 587,
"smtp_tls": true,
"smtp_user": "deine@domain.de",
"smtp_pass": "passwort",
"smtp_from": "deine@domain.de",
"default_to": "empfaenger@example.com",
"imap_host": "imap.strato.de",
"imap_port": 993,
"imap_ssl": true
}default_to (optional): Standard-Empfänger, der verwendet wird wenn -t nicht angegeben ist.
Nützlich für Scripts, die immer an dieselbe Adresse senden.
# Mit default_to in der Config: kein -t nötig
./send_email.py -s "Alert" -m "Server down"Das Script sucht in dieser Reihenfolge nach der Config:
.email_config.jsonim gleichen Verzeichnis wie das Script~/.email_config.jsonim Home-Verzeichnis
setup speichert immer in das Verzeichnis neben dem Script (Option 1).
- CLI-Parameter (höchste)
- Umgebungsvariablen
- Config-Datei (
.email_config.jsonneben Script oder~/.email_config.json) - Defaults
{
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"smtp_tls": true,
"smtp_user": "deine@gmail.com",
"smtp_pass": "app-passwort",
"smtp_from": "deine@gmail.com"
}{
"smtp_host": "smtp-mail.outlook.com",
"smtp_port": 587,
"smtp_tls": true,
"smtp_user": "deine@outlook.com",
"smtp_pass": "passwort",
"smtp_from": "deine@outlook.com"
}{
"smtp_host": "smtp.strato.de",
"smtp_port": 587,
"smtp_tls": true,
"smtp_user": "deine@domain.de",
"smtp_pass": "passwort",
"smtp_from": "deine@domain.de"
}Spezial-Befehle:
setup Interaktive Konfiguration
show-config Config anzeigen (SMTP + IMAP)
check [Optionen] INBOX lesen (IMAP)
read <uid> [--json] Email lesen + als gelesen markieren
wait [Optionen] Auf neue Email warten (IMAP IDLE / Push)
check-Optionen:
--from ADDRESS Filter nach Absender
--since TIMESPEC Filter nach Zeit: 'today', '1h', '30m', '2d', 'YYYY-MM-DD'
--unread Nur ungelesene
--json JSON-Output
wait-Optionen:
--from ADDRESS Nur auf Email von diesem Absender warten
--timeout SECONDS Max. Wartezeit in Sekunden (Standard: 300)
--json JSON-Output
Email-Parameter (send):
-f, --from-email Absender-Adresse
-t, --to Empfänger-Adresse
-s, --subject Betreff (erforderlich)
-m, --message Nachricht
--text-file Nachricht aus Datei
--html HTML-Nachricht
--html-file HTML aus Datei
-a, --attachment Datei anhängen (mehrfach möglich)
Batch-Mode:
--batch FILE CSV oder Text-Datei mit Empfängern
--category CAT Filter nach Category (mehrfach möglich)
SMTP-Config (überschreibt ~/.email_config.json):
--smtp SMTP-Server
--port SMTP-Port
--tls TLS verwenden
-u, --username SMTP-Username
-p, --password SMTP-Passwort
Output/Debug:
--json JSON-Output (für Automation)
-v, --verbose Verbose (stderr)
-h, --help Hilfe
Pflichtfelder:
email(oderto,mail,e-mail)
Optionale Felder:
categories(odertags,category,type) - Komma-separiertname- Wird nicht verwendet, nur für Übersicht
Beispiel:
email,categories,name
admin@example.com,"Notfall,Error",Admin
dev@example.com,"Error,Info",Developer
monitor@example.com,"Info,Erfolg",Monitoring- Immer --json verwenden für parsbare Ausgaben
- Exit Codes prüfen für Fehlerbehandlung
- Batch-Mode nutzen für mehrere Empfänger
- Categories für verschiedene Alert-Level
- Verbose auf stderr → JSON auf stdout bleibt sauber
Beispiel-Script:
import subprocess
import json
result = subprocess.run([
"./send_email.py", "--json",
"--batch", "alerts.csv",
"--category", "Notfall",
"-s", "Alert",
"-m", "Server down!"
], capture_output=True, text=True)
data = json.loads(result.stdout)
if data['status'] == 'batch':
print(f"Sent to {data['success']}/{data['total']} recipients")
for detail in data['details']:
if detail['status'] == 'error':
print(f"Failed: {detail['to']}: {detail['message']}")
sys.exit(result.returncode)JSON-Parse-Fehler:
# Verwende 2>&1 nicht, wenn du --json nutzt
# Richtig:
./send_email.py --json ... > result.json
# Falsch:
./send_email.py --json ... 2>&1 > result.json # stderr vermischt sichVerbose mit JSON:
# Verbose geht nach stderr, JSON nach stdout
./send_email.py --json -v ... 2>debug.log 1>result.jsonCategory-Filter funktioniert nicht:
- Prüfe CSV-Format (Header muss "categories", "tags", oder "category" heißen)
- Categories sind case-sensitive ("Notfall" ≠ "notfall")
- Mehrere Categories komma-separiert: "Cat1,Cat2"
Exit Codes prüfen:
./send_email.py --json -t test@example.com -s "Test" -m "Hello"
echo "Exit code: $?"