IO4IT 4.0.3__tar.gz → 4.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. {io4it-4.0.3 → io4it-4.0.5}/PKG-INFO +1 -1
  2. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/PKG-INFO +1 -1
  3. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/SOURCES.txt +7 -0
  4. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/mail.py +153 -65
  5. io4it-4.0.5/orangecontrib/IO4IT/utils/pptx2jpg.py +64 -0
  6. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py +0 -2
  7. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +1 -1
  8. io4it-4.0.5/orangecontrib/IO4IT/widgets/OWPPTX2JPG.py +207 -0
  9. io4it-4.0.5/orangecontrib/IO4IT/widgets/OWWebSearch.py +647 -0
  10. io4it-4.0.5/orangecontrib/IO4IT/widgets/OWXLSX_insert.py +225 -0
  11. io4it-4.0.5/orangecontrib/IO4IT/widgets/designer/owinsertdatatoexcel.ui +111 -0
  12. io4it-4.0.5/orangecontrib/IO4IT/widgets/designer/owpptx2jpg.ui +132 -0
  13. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owwebsearch.ui +71 -4
  14. io4it-4.0.5/orangecontrib/IO4IT/widgets/icons/pptx2jpg.png +0 -0
  15. io4it-4.0.5/orangecontrib/IO4IT/widgets/icons/xlsx_insert.png +0 -0
  16. {io4it-4.0.3 → io4it-4.0.5}/setup.py +1 -1
  17. io4it-4.0.3/orangecontrib/IO4IT/widgets/OWWebSearch.py +0 -373
  18. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/dependency_links.txt +0 -0
  19. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/entry_points.txt +0 -0
  20. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/namespace_packages.txt +0 -0
  21. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/requires.txt +0 -0
  22. {io4it-4.0.3 → io4it-4.0.5}/io4it.egg-info/top_level.txt +0 -0
  23. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/__init__.py +0 -0
  24. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
  25. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
  26. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/toolViews/designer/key_manager_ui.ui +0 -0
  27. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/toolViews/designer/link_workflow_manager_ui.ui +0 -0
  28. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/toolViews/key_manager_ui.py +0 -0
  29. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/toolViews/linkHTLMWorkflow_manager_ui.py +0 -0
  30. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/__init__.py +0 -0
  31. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/keys_manager.py +0 -0
  32. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/pool_exec_utils.py +0 -0
  33. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/secret_manager.py +0 -0
  34. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/utils/utils_md.py +0 -0
  35. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWChatGpt.py +0 -0
  36. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +0 -0
  37. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py +0 -0
  38. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +0 -0
  39. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py +0 -0
  40. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWJsonToDataTable.py +0 -0
  41. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWMD2HTML.py +0 -0
  42. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWMarkdownLoader.py +0 -0
  43. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py +0 -0
  44. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWParserHTML.py +0 -0
  45. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWPdfType.py +0 -0
  46. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py +0 -0
  47. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
  48. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
  49. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
  50. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
  51. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
  52. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -0
  53. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
  54. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
  55. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
  56. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/ow_extract_tables_docx_to_xlsx.ui +0 -0
  57. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -0
  58. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/ow_json_to_data_table.ui +0 -0
  59. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -0
  60. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -0
  61. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui +0 -0
  62. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui +0 -0
  63. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -0
  64. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui +0 -0
  65. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -0
  66. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -0
  67. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -0
  68. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owmarkdownloader.ui +0 -0
  69. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owmd2html.ui +0 -0
  70. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui +0 -0
  71. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owparserhtml.ui +0 -0
  72. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owpdftype.ui +0 -0
  73. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui +0 -0
  74. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -0
  75. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
  76. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +0 -0
  77. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
  78. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
  79. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/check_pdf.png +0 -0
  80. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
  81. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/dep_md_old.png +0 -0
  82. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
  83. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
  84. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/extract_table.png +0 -0
  85. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
  86. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/html.png +0 -0
  87. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/json-file.png +0 -0
  88. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
  89. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/load_md.png +0 -0
  90. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
  91. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
  92. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
  93. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/monitor-email.svg +0 -0
  94. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/office_normalizer.png +0 -0
  95. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/owmd2html.svg +0 -0
  96. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/process_pool_executor.png +0 -0
  97. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
  98. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
  99. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
  100. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/websearch.png +0 -0
  101. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
  102. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
  103. {io4it-4.0.3 → io4it-4.0.5}/orangecontrib/__init__.py +0 -0
  104. {io4it-4.0.3 → io4it-4.0.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: io4it
3
- Version: 4.0.3
3
+ Version: 4.0.5
4
4
  Home-page:
5
5
  Author:
6
6
  Author-email:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: io4it
3
- Version: 4.0.3
3
+ Version: 4.0.5
4
4
  Home-page:
5
5
  Author:
6
6
  Author-email:
@@ -14,6 +14,7 @@ orangecontrib/IO4IT/utils/__init__.py
14
14
  orangecontrib/IO4IT/utils/keys_manager.py
15
15
  orangecontrib/IO4IT/utils/mail.py
16
16
  orangecontrib/IO4IT/utils/pool_exec_utils.py
17
+ orangecontrib/IO4IT/utils/pptx2jpg.py
17
18
  orangecontrib/IO4IT/utils/secret_manager.py
18
19
  orangecontrib/IO4IT/utils/utils_md.py
19
20
  orangecontrib/IO4IT/widgets/OWChatGpt.py
@@ -27,6 +28,7 @@ orangecontrib/IO4IT/widgets/OWMD2HTML.py
27
28
  orangecontrib/IO4IT/widgets/OWMarkdownLoader.py
28
29
  orangecontrib/IO4IT/widgets/OWMarkdownizer.py
29
30
  orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py
31
+ orangecontrib/IO4IT/widgets/OWPPTX2JPG.py
30
32
  orangecontrib/IO4IT/widgets/OWParserHTML.py
31
33
  orangecontrib/IO4IT/widgets/OWPdfType.py
32
34
  orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py
@@ -34,6 +36,7 @@ orangecontrib/IO4IT/widgets/OWS3Uploader.py
34
36
  orangecontrib/IO4IT/widgets/OWS3downloader.py
35
37
  orangecontrib/IO4IT/widgets/OWS3list.py
36
38
  orangecontrib/IO4IT/widgets/OWWebSearch.py
39
+ orangecontrib/IO4IT/widgets/OWXLSX_insert.py
37
40
  orangecontrib/IO4IT/widgets/OWmailLoader.py
38
41
  orangecontrib/IO4IT/widgets/OWmailSender.py
39
42
  orangecontrib/IO4IT/widgets/OWwordpdf2docx.py
@@ -53,6 +56,7 @@ orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui
53
56
  orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui
54
57
  orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui
55
58
  orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui
59
+ orangecontrib/IO4IT/widgets/designer/owinsertdatatoexcel.ui
56
60
  orangecontrib/IO4IT/widgets/designer/owmailloader.ui
57
61
  orangecontrib/IO4IT/widgets/designer/owmailsender.ui
58
62
  orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui
@@ -61,6 +65,7 @@ orangecontrib/IO4IT/widgets/designer/owmd2html.ui
61
65
  orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui
62
66
  orangecontrib/IO4IT/widgets/designer/owparserhtml.ui
63
67
  orangecontrib/IO4IT/widgets/designer/owpdftype.ui
68
+ orangecontrib/IO4IT/widgets/designer/owpptx2jpg.ui
64
69
  orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui
65
70
  orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui
66
71
  orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui
@@ -85,10 +90,12 @@ orangecontrib/IO4IT/widgets/icons/md.png
85
90
  orangecontrib/IO4IT/widgets/icons/monitor-email.svg
86
91
  orangecontrib/IO4IT/widgets/icons/office_normalizer.png
87
92
  orangecontrib/IO4IT/widgets/icons/owmd2html.svg
93
+ orangecontrib/IO4IT/widgets/icons/pptx2jpg.png
88
94
  orangecontrib/IO4IT/widgets/icons/process_pool_executor.png
89
95
  orangecontrib/IO4IT/widgets/icons/speech_to_text.png
90
96
  orangecontrib/IO4IT/widgets/icons/upload.png
91
97
  orangecontrib/IO4IT/widgets/icons/visualizationer.png
92
98
  orangecontrib/IO4IT/widgets/icons/websearch.png
93
99
  orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png
100
+ orangecontrib/IO4IT/widgets/icons/xlsx_insert.png
94
101
  orangecontrib/IO4IT/widgets/icons_dev/__init__.py
@@ -669,11 +669,35 @@ def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html,
669
669
  except Exception as e:
670
670
  print("❌ Une erreur s'est produite :", e)
671
671
 
672
+ def extraire_emails(champ):
673
+ """
674
+ Transforme une chaîne du type :
675
+ 'a@test.com;b@test.com' ou 'a@test.com, b@test.com'
676
+ en liste Python propre.
677
+ """
678
+ if not champ:
679
+ return []
672
680
 
673
- def check_send_new_emails(offusc_conf_agent,type_co):
674
- if type_co=="IMAP4_SSL":
675
- agent, domain, _, _,alias = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
676
- mail = agent+domain
681
+ emails = champ.replace(";", ",").split(",")
682
+ return [email.strip() for email in emails if email.strip()]
683
+
684
+ def to_graph_recipients(champ):
685
+ """
686
+ Convertit une chaîne d'emails en format attendu par Microsoft Graph.
687
+ """
688
+ return [
689
+ {
690
+ "emailAddress": {
691
+ "address": email
692
+ }
693
+ }
694
+ for email in extraire_emails(champ)
695
+ ]
696
+
697
+ def check_send_new_emails(offusc_conf_agent, type_co):
698
+ if type_co == "IMAP4_SSL":
699
+ agent, domain, _, _, alias = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
700
+ mail = agent + domain
677
701
  if alias != "":
678
702
  agent = alias
679
703
  chemin_dossier_in, chemin_dossier_out = mail_in_folder(agent, "out")
@@ -684,18 +708,24 @@ def check_send_new_emails(offusc_conf_agent,type_co):
684
708
  if os.path.exists(chemin_dossier_out + "/" + contenu + "/mail.ok"):
685
709
  chemin = chemin_dossier_out + "/" + contenu + "/mail.txt"
686
710
  infos = lire_message(chemin)
687
- # Affichage des informations extraites
688
711
  cles_requises = ["eme", "des", "cop", "pri", "tit", "txt"]
689
712
  if all(cle in infos for cle in cles_requises):
713
+ destinataires = extraire_emails(infos["eme"])
714
+ copies = extraire_emails(infos.get("cop", ""))
715
+ if not destinataires:
716
+ print("Aucun destinataire trouvé dans 'eme'")
717
+ continue
718
+
690
719
  send_mail(
691
720
  mail,
692
721
  offusc_conf_agent,
693
- infos["eme"],
722
+ destinataires,
694
723
  infos["tit"],
695
724
  infos["txt"],
696
- piece_jointe_paths= chemin_dossier_out + "/" + contenu + "/pj" #à rajouter quand PJ ok chemin_dossier_out + "/" + contenu + "/pj"
725
+ cc=copies,
726
+ piece_jointe_paths=chemin_dossier_out + "/" + contenu + "/pj"
697
727
  )
698
- MetManagement.reset_folder(chemin_dossier_in + contenu , recreate=False)
728
+ MetManagement.reset_folder(chemin_dossier_in + contenu, recreate=False)
699
729
  MetManagement.reset_folder(chemin_dossier_out + contenu, recreate=False)
700
730
  else:
701
731
  print("il manque des clefs dans le contenu du mail")
@@ -703,15 +733,21 @@ def check_send_new_emails(offusc_conf_agent,type_co):
703
733
  print("Le dossier est vide.")
704
734
  else:
705
735
  print("Le dossier n'existe pas ou le chemin n'est pas un dossier.")
706
- elif type_co=="MICROSOFT_EXCHANGE_OWA":
736
+ elif type_co == "MICROSOFT_EXCHANGE_OWA":
707
737
  try:
708
738
  mail, alias, server, username, password, interval_second = keys_manager.lire_config_owa(
709
- offusc_conf_agent)
739
+ offusc_conf_agent
740
+ )
710
741
  credentials = Credentials(username=username, password=password)
711
- config = Configuration(server=server,
712
- credentials=credentials)
713
- account = Account(primary_smtp_address=alias, credentials=credentials, config=config, autodiscover=False,
714
- access_type=DELEGATE)
742
+ config = Configuration(server=server, credentials=credentials)
743
+ account = Account(
744
+ primary_smtp_address=alias,
745
+ credentials=credentials,
746
+ config=config,
747
+ autodiscover=False,
748
+ access_type=DELEGATE
749
+ )
750
+
715
751
  chemin_dossier_in, chemin_dossier_out = mail_in_folder(alias, "out")
716
752
  if os.path.exists(chemin_dossier_out) and os.path.isdir(chemin_dossier_out):
717
753
  contenus = os.listdir(chemin_dossier_out)
@@ -720,61 +756,72 @@ def check_send_new_emails(offusc_conf_agent,type_co):
720
756
  if os.path.exists(chemin_dossier_out + "/" + contenu + "/mail.ok"):
721
757
  chemin = chemin_dossier_out + "/" + contenu + "/mail.txt"
722
758
  infos = lire_message(chemin)
723
- # Affichage des informations extraites
724
759
  cles_requises = ["eme", "des", "cop", "pri", "tit", "txt"]
725
760
  if all(cle in infos for cle in cles_requises):
761
+ to_recipients = [
762
+ Mailbox(email_address=email)
763
+ for email in extraire_emails(infos["eme"])
764
+ ]
765
+ cc_recipients = [
766
+ Mailbox(email_address=email)
767
+ for email in extraire_emails(infos.get("cop", ""))
768
+ ]
769
+
770
+ if not to_recipients:
771
+ print("Aucun destinataire trouvé dans 'eme'")
772
+ continue
726
773
 
727
774
  m = Message(
728
775
  account=account,
729
776
  folder=account.sent,
730
777
  subject=infos["tit"],
731
778
  body=HTMLBody(infos["txt"]),
732
- to_recipients=[Mailbox(email_address=infos["eme"])],
779
+ to_recipients=to_recipients,
780
+ cc_recipients=cc_recipients,
733
781
  sender=Mailbox(email_address=alias),
734
782
  )
735
783
  m.send_and_save()
736
784
  time.sleep(1)
737
- MetManagement.reset_folder(chemin_dossier_in + contenu , recreate=False)
785
+ MetManagement.reset_folder(chemin_dossier_in + contenu, recreate=False)
738
786
  MetManagement.reset_folder(chemin_dossier_out + contenu, recreate=False)
739
787
  else:
740
788
  print("il manque des clefs dans le contenu du mail")
741
789
  else:
742
790
  print("Le dossier est vide.")
743
791
 
744
-
745
-
746
-
747
792
  except Exception as e:
748
793
  print(f"Erreur lors du traitement du mail : {e}")
749
794
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2":
750
795
  try:
751
796
  client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(
752
- offusc_conf_agent)
753
- # Déduire l'alias pour le nom du dossier
797
+ offusc_conf_agent
798
+ )
754
799
  agent = user_email
755
- alias = user_email # tu peux adapter si tu veux un alias distinct plus tard
800
+ alias = user_email
756
801
 
757
802
  chemin_dossier_in, chemin_dossier_out = mail_in_folder(agent, "out")
758
-
759
803
  authority = f"https://login.microsoftonline.com/{tenant_id}"
760
804
 
761
- # === Authentification avec MSAL ===
762
805
  app = ConfidentialClientApplication(
763
806
  client_id=client_id,
764
807
  client_credential=client_secret,
765
808
  authority=authority
766
809
  )
767
810
  print("app", app)
768
- token_result = app.acquire_token_for_client(scopes=["https://outlook.office365.com/.default"])
811
+ token_result = app.acquire_token_for_client(
812
+ scopes=["https://outlook.office365.com/.default"]
813
+ )
769
814
 
770
815
  if "access_token" not in token_result:
771
- raise Exception("Impossible d'obtenir un token : ", token_result.get("error_description"))
816
+ raise Exception(
817
+ f"Impossible d'obtenir un token : {token_result.get('error_description')}"
818
+ )
772
819
 
773
820
  token_for_exchangelib = OAuth2Token({
774
- 'access_token': token_result['access_token'],
775
- 'expires_in': token_result.get('expires_in', 3600),
776
- 'token_type': token_result.get('token_type', 'Bearer'),
777
- 'scope': 'https://outlook.office365.com/.default'
821
+ "access_token": token_result["access_token"],
822
+ "expires_in": token_result.get("expires_in", 3600),
823
+ "token_type": token_result.get("token_type", "Bearer"),
824
+ "scope": "https://outlook.office365.com/.default"
778
825
  })
779
826
 
780
827
  credentials = OAuth2Credentials(
@@ -786,8 +833,8 @@ def check_send_new_emails(offusc_conf_agent,type_co):
786
833
  )
787
834
  config = Configuration(
788
835
  credentials=credentials,
789
- auth_type='OAuth 2.0',
790
- service_endpoint='https://outlook.office365.com/EWS/Exchange.asmx'
836
+ auth_type="OAuth 2.0",
837
+ service_endpoint="https://outlook.office365.com/EWS/Exchange.asmx"
791
838
  )
792
839
 
793
840
  account = Account(
@@ -806,31 +853,59 @@ def check_send_new_emails(offusc_conf_agent,type_co):
806
853
  infos = lire_message(chemin)
807
854
  cles_requises = ["eme", "des", "cop", "pri", "tit", "txt"]
808
855
  if all(cle in infos for cle in cles_requises):
856
+ to_recipients = [
857
+ Mailbox(email_address=email)
858
+ for email in extraire_emails(infos["eme"])
859
+ ]
860
+ cc_recipients = [
861
+ Mailbox(email_address=email)
862
+ for email in extraire_emails(infos.get("cop", ""))
863
+ ]
864
+
865
+ if not to_recipients:
866
+ print("Aucun destinataire trouvé dans 'eme'")
867
+ continue
868
+
809
869
  m = Message(
810
870
  account=account,
811
871
  folder=account.sent,
812
872
  subject=infos["tit"],
813
873
  body=HTMLBody(infos["txt"]),
814
- to_recipients=[Mailbox(email_address=infos["eme"])],
874
+ to_recipients=to_recipients,
875
+ cc_recipients=cc_recipients,
815
876
  sender=Mailbox(email_address=alias),
816
877
  )
817
878
  m.send_and_save()
818
879
  time.sleep(1)
819
- MetManagement.reset_folder(os.path.join(chemin_dossier_in, contenu), recreate=False)
820
- MetManagement.reset_folder(os.path.join(chemin_dossier_out, contenu), recreate=False)
880
+
881
+ MetManagement.reset_folder(
882
+ os.path.join(chemin_dossier_in, contenu),
883
+ recreate=False
884
+ )
885
+ MetManagement.reset_folder(
886
+ os.path.join(chemin_dossier_out, contenu),
887
+ recreate=False
888
+ )
821
889
  else:
822
890
  print("\n\n Il manque des clefs dans le contenu du mail")
823
891
  else:
824
- print("\n\n KO § os.path.exists(os.path.join(chemin_dossier_out, contenu)", os.path.exists(os.path.join(chemin_dossier_out, contenu, "mail.ok")))
892
+ print(
893
+ "\n\n KO § os.path.exists(os.path.join(chemin_dossier_out, contenu)",
894
+ os.path.exists(os.path.join(chemin_dossier_out, contenu, "mail.ok"))
895
+ )
825
896
  else:
826
897
  print("Le dossier est vide.")
827
898
  else:
828
899
  print("Le dossier n'existe pas ou le chemin n'est pas un dossier.")
900
+
829
901
  except Exception as e:
830
902
  print(f"❌ Erreur lors de l'envoi avec OAuth2 : {e}")
903
+
831
904
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH":
832
905
  try:
833
- client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(offusc_conf_agent, type_co)
906
+ client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(
907
+ offusc_conf_agent, type_co
908
+ )
834
909
 
835
910
  agent = user_email
836
911
  chemin_dossier_in, chemin_dossier_out = mail_in_folder(agent, "out")
@@ -842,15 +917,19 @@ def check_send_new_emails(offusc_conf_agent,type_co):
842
917
  authority=authority
843
918
  )
844
919
 
845
- token_result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
920
+ token_result = app.acquire_token_for_client(
921
+ scopes=["https://graph.microsoft.com/.default"]
922
+ )
846
923
 
847
924
  if "access_token" not in token_result:
848
- raise Exception("Impossible d'obtenir un token : ", token_result.get("error_description"))
925
+ raise Exception(
926
+ f"Impossible d'obtenir un token : {token_result.get('error_description')}"
927
+ )
849
928
 
850
- access_token = token_result['access_token']
929
+ access_token = token_result["access_token"]
851
930
  headers = {
852
- 'Authorization': f'Bearer {access_token}',
853
- 'Content-Type': 'application/json'
931
+ "Authorization": f"Bearer {access_token}",
932
+ "Content-Type": "application/json"
854
933
  }
855
934
 
856
935
  if os.path.exists(chemin_dossier_out) and os.path.isdir(chemin_dossier_out):
@@ -867,7 +946,13 @@ def check_send_new_emails(offusc_conf_agent,type_co):
867
946
  cles_requises = ["eme", "des", "cop", "pri", "tit", "txt"]
868
947
  if all(cle in infos for cle in cles_requises):
869
948
 
870
- # --- GESTION DES PIÈCES JOINTES ---
949
+ to_recipients = to_graph_recipients(infos["eme"])
950
+ cc_recipients = to_graph_recipients(infos.get("cop", ""))
951
+
952
+ if not to_recipients:
953
+ print("Aucun destinataire trouvé dans 'eme'")
954
+ continue
955
+
871
956
  attachments = []
872
957
  chemin_pj = os.path.join(dossier_actuel, "pj")
873
958
 
@@ -877,7 +962,7 @@ def check_send_new_emails(offusc_conf_agent,type_co):
877
962
  if os.path.isfile(file_path):
878
963
  with open(file_path, "rb") as f:
879
964
  content_bytes = f.read()
880
- encoded_content = base64.b64encode(content_bytes).decode('utf-8')
965
+ encoded_content = base64.b64encode(content_bytes).decode("utf-8")
881
966
 
882
967
  attachments.append({
883
968
  "@odata.type": "#microsoft.graph.fileAttachment",
@@ -885,27 +970,24 @@ def check_send_new_emails(offusc_conf_agent,type_co):
885
970
  "contentBytes": encoded_content
886
971
  })
887
972
 
888
- # Construire le message pour Microsoft Graph
889
- message_data = {
890
- "message": {
891
- "subject": infos["tit"],
892
- "body": {
893
- "contentType": "HTML",
894
- "content": infos["txt"]
895
- },
896
- "toRecipients": [
897
- {
898
- "emailAddress": {
899
- "address": infos["eme"]
900
- }
901
- }
902
- ],
903
- "attachments": attachments # Ajout de la liste des PJ
973
+ message = {
974
+ "subject": infos["tit"],
975
+ "body": {
976
+ "contentType": "HTML",
977
+ "content": infos["txt"]
904
978
  },
979
+ "toRecipients": to_recipients,
980
+ "attachments": attachments
981
+ }
982
+
983
+ if cc_recipients:
984
+ message["ccRecipients"] = cc_recipients
985
+
986
+ message_data = {
987
+ "message": message,
905
988
  "saveToSentItems": True
906
989
  }
907
990
 
908
- # Envoyer l'email
909
991
  send_url = f"https://graph.microsoft.com/v1.0/users/{user_email}/sendMail"
910
992
  try:
911
993
  response = requests.post(send_url, headers=headers, json=message_data)
@@ -917,9 +999,15 @@ def check_send_new_emails(offusc_conf_agent,type_co):
917
999
  raise e
918
1000
 
919
1001
  time.sleep(1)
920
- MetManagement.reset_folder(os.path.join(chemin_dossier_in, contenu), recreate=False)
921
- MetManagement.reset_folder(os.path.join(chemin_dossier_out, contenu),
922
- recreate=False)
1002
+ MetManagement.reset_folder(
1003
+ os.path.join(chemin_dossier_in, contenu),
1004
+ recreate=False
1005
+ )
1006
+ MetManagement.reset_folder(
1007
+ os.path.join(chemin_dossier_out, contenu),
1008
+ recreate=False
1009
+ )
1010
+
923
1011
  except Exception as e:
924
1012
  print(f"❌ Erreur lors de l'envoi avec Graph API : {e}")
925
1013
  print(f"📤 [DEBUG] Erreur détaillée: {type(e).__name__}: {str(e)}")
@@ -0,0 +1,64 @@
1
+ import sys
2
+ import time
3
+ import subprocess
4
+ from pathlib import Path
5
+
6
+ def pptx_to_pdf(pptx_path: Path) -> Path:
7
+ pdf_path = pptx_path.with_suffix(".pdf")
8
+ if sys.platform.startswith("win"):
9
+ import win32com.client
10
+ powerpoint = win32com.client.Dispatch("PowerPoint.Application")
11
+ try:
12
+ presentation = powerpoint.Presentations.Open(str(pptx_path), WithWindow=False)
13
+ presentation.SaveAs(str(pdf_path), 32)
14
+ presentation.Close()
15
+ except Exception as e:
16
+ raise RuntimeError(f"Erreur PowerPoint : {e}")
17
+ elif sys.platform == "darwin":
18
+ script = f'tell application "Microsoft PowerPoint" to save (open POSIX file "{pptx_path}") in POSIX file "{pdf_path}" as PDF'
19
+ subprocess.run(["osascript", "-e", script], check=True)
20
+ else:
21
+ raise RuntimeError("Système d'exploitation non supporté.")
22
+ return pdf_path
23
+
24
+ def process_one_pptx(file_path_str: str, unique_folder: bool = True):
25
+ try:
26
+ import fitz
27
+ except ImportError:
28
+ return [file_path_str, "", "nok", "0.0", "Erreur: PyMuPDF (fitz) non installé"]
29
+
30
+ t0 = time.time()
31
+ src = Path(file_path_str).resolve()
32
+
33
+ # ✅ unique_folder=True → un dossier par pptx : images_monFichier/
34
+ # ✅ unique_folder=False → tout dans un dossier commun : images/ (à côté des pptx)
35
+ if unique_folder:
36
+ out_dir = src.parent / f"images_{src.stem}"
37
+ else:
38
+ out_dir = src.parent / "images"
39
+
40
+ try:
41
+ out_dir.mkdir(parents=True, exist_ok=True)
42
+
43
+ pdf_path = pptx_to_pdf(src)
44
+
45
+ doc = fitz.open(str(pdf_path))
46
+ img_list = []
47
+ for i, page in enumerate(doc, start=1):
48
+ pix = page.get_pixmap(dpi=150)
49
+ # ✅ Préfixe avec le nom du pptx pour éviter les collisions en mode commun
50
+ img_path = out_dir / f"{src.stem}_slide_{i:03d}.jpg"
51
+ pix.save(str(img_path))
52
+ img_list.append(str(img_path))
53
+ doc.close()
54
+
55
+ if pdf_path.exists():
56
+ pdf_path.unlink()
57
+
58
+ duration = time.time() - t0
59
+ return [str(src), "|".join(img_list), "ok", f"{duration:.2f}", f"{len(img_list)} slides"]
60
+
61
+ except Exception as e:
62
+ duration = time.time() - t0
63
+ import traceback
64
+ return [str(src), "", "nok", f"{duration:.2f}", f"{str(e)}\n{traceback.format_exc()}"]
@@ -145,9 +145,7 @@ class OWInboxMailMonitoring(widget.OWWidget):
145
145
  if self.type_co == "MICROSOFT_EXCHANGE_OWA":
146
146
  _, agent, _, _, _, _ = keys_manager.lire_config_owa(self.your_email_conf)
147
147
  if self.type_co == "MICROSOFT_EXCHANGE_OAUTH2" or self.type_co == "MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH":
148
- print("ici")
149
148
  _, _, _, agent = keys_manager.lire_config_oauth2(self.your_email_conf, type=self.type_co)
150
- print("icici")
151
149
  if agent != "":
152
150
  chemin_dossier = MetManagement.get_path_mailFolder()
153
151
  self.input_dir = chemin_dossier + str(agent) + "/in"
@@ -10,7 +10,7 @@ import secrets
10
10
  from pathlib import Path
11
11
  from concurrent.futures import ProcessPoolExecutor, as_completed
12
12
 
13
- import numpy as np
13
+
14
14
  import fitz # PyMuPDF
15
15
 
16
16
  from AnyQt.QtCore import QThread, pyqtSignal