commit eddc35f2a04a418d774b7dbf560d4a8a3a1c551b Author: root Date: Sun Dec 28 20:44:40 2025 +0000 first commit diff --git a/gmail-to-tryton/Dockerfile b/gmail-to-tryton/Dockerfile new file mode 100644 index 0000000..56500cb --- /dev/null +++ b/gmail-to-tryton/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Installer dépendances +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copier scripts +COPY run.py . +COPY entrypoint.sh . + +# Rendre le script exécutable +RUN chmod +x entrypoint.sh + +# Entrypoint +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/gmail-to-tryton/entrypoint.sh b/gmail-to-tryton/entrypoint.sh new file mode 100755 index 0000000..44a0ed5 --- /dev/null +++ b/gmail-to-tryton/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh +set -e +python3 /app/run.py diff --git a/gmail-to-tryton/requirements.txt b/gmail-to-tryton/requirements.txt new file mode 100644 index 0000000..f229360 --- /dev/null +++ b/gmail-to-tryton/requirements.txt @@ -0,0 +1 @@ +requests diff --git a/gmail-to-tryton/run.py b/gmail-to-tryton/run.py new file mode 100644 index 0000000..91850b0 --- /dev/null +++ b/gmail-to-tryton/run.py @@ -0,0 +1,100 @@ +import imaplib +import time +import requests +import os +from datetime import datetime + +IMAP_SERVER = "imap.gmail.com" +IMAP_PORT = 993 + +EMAIL_ACCOUNT = os.getenv("EMAIL_ACCOUNT") +EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD") +TRYTON_ENDPOINT = os.getenv("TRYTON_ENDPOINT") +INTERVAL = int(os.getenv("INTERVAL", "30")) # secondes + +LOG_FILE = "/app/logs/app.log" + + +def log(msg): + timestamp = datetime.now().isoformat() + line = f"[{timestamp}] {msg}" + print(line, flush=True) + with open(LOG_FILE, "a") as f: + f.write(line + "\n") + + +def connect_imap(): + log("Connexion à Gmail via IMAP...") + mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT) + mail.login(EMAIL_ACCOUNT, EMAIL_PASSWORD) + mail.select("INBOX") + log("Connexion IMAP réussie.") + return mail + + +def fetch_unread_messages(mail): + status, data = mail.search(None, '(UNSEEN)') + if status != "OK": + log("Erreur lors de la recherche de mails non lus.") + return [] + msg_ids = data[0].split() + log(f"{len(msg_ids)} mails non lus récupérés.") + return msg_ids + + +def get_raw_message(mail, msg_id): + status, data = mail.fetch(msg_id, '(RFC822)') + if status != "OK": + log(f"Erreur récupération message {msg_id}") + return None + raw = data[0][1] + log(f"Mail {msg_id.decode()} récupéré ({len(raw)} bytes)") + return raw + + +def post_to_tryton(raw_message): + headers = {"Content-Type": "message/rfc822"} + log(f"Envoi du mail vers Tryton : {TRYTON_ENDPOINT}") + + try: + r = requests.post(TRYTON_ENDPOINT, data=raw_message, headers=headers) + except Exception as e: + log(f"❌ Erreur réseau lors de l'envoi à Tryton : {e}") + return False + + log(f"Réponse HTTP Tryton : {r.status_code}") + if r.status_code != 200: + log(f"Corps de la réponse Tryton : {r.text[:500]}") + return False + + log("✔ Mail envoyé à Tryton avec succès.") + return True + + +def main_loop(): + log("🚀 Worker Gmail → Tryton démarré.") + + while True: + try: + mail = connect_imap() + unread_ids = fetch_unread_messages(mail) + + if not unread_ids: + log("Aucun nouvel email à traiter.") + + for msg_id in unread_ids: + raw = get_raw_message(mail, msg_id) + if raw and post_to_tryton(raw): + mail.store(msg_id, '+FLAGS', '\\Seen') + log(f"Mail {msg_id.decode()} marqué comme lu.") + + mail.logout() + except Exception as e: + log(f"❌ Erreur générale : {e}") + + log(f"⏳ Pause {INTERVAL} secondes avant la prochaine vérification...") + time.sleep(INTERVAL) + + +if __name__ == "__main__": + main_loop()