From 3999ade26265f36367ea83d7f69f2cef1d4aae9b Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 3 Mar 2026 10:36:27 +0000 Subject: [PATCH] Update gmail-to-tryton/run.py --- gmail-to-tryton/run.py | 84 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/gmail-to-tryton/run.py b/gmail-to-tryton/run.py index 91850b0..2a367d0 100644 --- a/gmail-to-tryton/run.py +++ b/gmail-to-tryton/run.py @@ -2,7 +2,11 @@ import imaplib import time import requests import os +import email +from email import policy +from email.message import EmailMessage from datetime import datetime +from email.header import decode_header, make_header IMAP_SERVER = "imap.gmail.com" IMAP_PORT = 993 @@ -67,9 +71,74 @@ def post_to_tryton(raw_message): log(f"Corps de la réponse Tryton : {r.text[:500]}") return False - log("✔ Mail envoyé à Tryton avec succès.") + log("✔ Envoi réussi vers Tryton.") return True +def decode_clean_header(value): + if not value: + return "" + + try: + value = str(make_header(decode_header(value))) + except Exception: + value = str(value) + + return value.replace("\r", " ").replace("\n", " ").strip() + +def split_and_post_attachments(raw_message): + msg = email.message_from_bytes(raw_message, policy=policy.default) + + original_from = decode_clean_header(msg.get("From")) + original_to = decode_clean_header(msg.get("To")) + original_subject = decode_clean_header(msg.get("Subject")) + + attachments = [] + + for part in msg.walk(): + if part.get_content_disposition() == "attachment": + filename = part.get_filename() + content = part.get_payload(decode=True) + content_type = part.get_content_type() + + if filename and content: + attachments.append((filename, content, content_type)) + + if not attachments: + log("Aucune pièce jointe trouvée, envoi du mail complet.") + return post_to_tryton(raw_message) + + log(f"{len(attachments)} pièce(s) jointe(s) trouvée(s).") + + all_success = True + + for filename, content, content_type in attachments: + try: + maintype, subtype = content_type.split("/", 1) + except ValueError: + maintype, subtype = "application", "octet-stream" + + new_msg = EmailMessage(policy=policy.SMTP) + + new_msg["Subject"] = original_subject or "Document" + new_msg["From"] = original_from + new_msg["To"] = original_to + + # Corps ultra simple + new_msg.set_content("Document attached.") + + new_msg.add_attachment( + content, + maintype=maintype, + subtype=subtype, + filename=filename.replace("'", "").replace('"', "").replace("\n", " ").replace("\r", " ") + ) + + log(f"Envoi vers Tryton de la pièce jointe : {filename}") + + if not post_to_tryton(new_msg.as_bytes(policy=policy.SMTP)): + all_success = False + + return all_success def main_loop(): log("🚀 Worker Gmail → Tryton démarré.") @@ -84,11 +153,20 @@ def main_loop(): for msg_id in unread_ids: raw = get_raw_message(mail, msg_id) - if raw and post_to_tryton(raw): + + if not raw: + continue + + success = split_and_post_attachments(raw) + + if success: mail.store(msg_id, '+FLAGS', '\\Seen') log(f"Mail {msg_id.decode()} marqué comme lu.") + else: + log(f"Mail {msg_id.decode()} NON marqué comme lu (échec partiel ou total).") mail.logout() + except Exception as e: log(f"❌ Erreur générale : {e}") @@ -97,4 +175,4 @@ def main_loop(): if __name__ == "__main__": - main_loop() + main_loop() \ No newline at end of file