django-unicom 25.2.27.dev1__tar.gz → 25.2.27.dev2__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 (146) hide show
  1. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/PKG-INFO +1 -1
  2. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/django_unicom.egg-info/PKG-INFO +1 -1
  3. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/_version.py +2 -2
  4. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/message.py +2 -0
  5. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/message_template.py +4 -0
  6. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/IMAP_thread_manager.py +2 -0
  7. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/listen_to_IMAP.py +8 -2
  8. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/send_email_message.py +4 -1
  9. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/html_inline_images.py +4 -0
  10. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/send_telegram_message.py +4 -1
  11. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/.cursor/rules/match_codebase_style.mdc +0 -0
  12. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/.cursor/rules/preserve_comments_and_irrelevant_code.mdc +0 -0
  13. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/.cursor/rules/require_context_before_changes.mdc +0 -0
  14. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/Dockerfile +0 -0
  15. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/MANIFEST.in +0 -0
  16. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/Makefile +0 -0
  17. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/README.md +0 -0
  18. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/conftest.py +0 -0
  19. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/django_unicom.egg-info/SOURCES.txt +0 -0
  20. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/django_unicom.egg-info/dependency_links.txt +0 -0
  21. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/django_unicom.egg-info/requires.txt +0 -0
  22. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/django_unicom.egg-info/top_level.txt +0 -0
  23. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/docker-compose.yaml +0 -0
  24. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/entrypoint.sh +0 -0
  25. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/manage.py +0 -0
  26. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/pyproject.toml +0 -0
  27. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/pytest.ini +0 -0
  28. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/requirements.txt +0 -0
  29. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/setup.cfg +0 -0
  30. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/setup.py +0 -0
  31. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/test_dkim_security.py +0 -0
  32. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/__init__.py +0 -0
  33. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/test_email_authentication.py +0 -0
  34. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/test_email_live.py +0 -0
  35. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/test_email_request_processing.py +0 -0
  36. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/test_telegram_live.py +0 -0
  37. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/tests/utils.py +0 -0
  38. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/__init__.py +0 -0
  39. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/__init__.py +0 -0
  40. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/account_admin.py +0 -0
  41. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/channel_admin.py +0 -0
  42. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/chat_admin.py +0 -0
  43. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/draft_message_admin.py +0 -0
  44. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/email_inline_image_admin.py +0 -0
  45. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/filters.py +0 -0
  46. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/member_admin.py +0 -0
  47. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/message_admin.py +0 -0
  48. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/message_template_admin.py +0 -0
  49. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/admin/request_admin.py +0 -0
  50. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/apps.py +0 -0
  51. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/__init__.py +0 -0
  52. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/commands/__init__.py +0 -0
  53. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/commands/mail_inbox_listen.py +0 -0
  54. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/commands/run_as_llm_chat.py +0 -0
  55. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/commands/send_scheduled_messages.py +0 -0
  56. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/management/commands/start_imap_listeners.py +0 -0
  57. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0001_initial.py +0 -0
  58. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0002_emailinlineimage.py +0 -0
  59. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0003_alter_emailinlineimage_email_message.py +0 -0
  60. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0004_messagetemplateinlineimage.py +0 -0
  61. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0005_emailinlineimage_hash_and_more.py +0 -0
  62. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0006_channel_created_at_channel_created_by_and_more.py +0 -0
  63. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0007_message_imap_uid.py +0 -0
  64. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0008_add_all_members_group.py +0 -0
  65. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0009_add_tool_call_types.py +0 -0
  66. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0010_request_initial_request_request_llm_calls_count_and_more.py +0 -0
  67. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/0011_toolcall_add_message_reference.py +0 -0
  68. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/migrations/__init__.py +0 -0
  69. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/__init__.py +0 -0
  70. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/account.py +0 -0
  71. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/account_chat.py +0 -0
  72. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/channel.py +0 -0
  73. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/chat.py +0 -0
  74. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/constants.py +0 -0
  75. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/draft_message.py +0 -0
  76. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/fields.py +0 -0
  77. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/member.py +0 -0
  78. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/member_group.py +0 -0
  79. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/request.py +0 -0
  80. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/request_category.py +0 -0
  81. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/tool_call.py +0 -0
  82. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/models/update.py +0 -0
  83. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/__init__.py +0 -0
  84. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/chat_summary.py +0 -0
  85. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/crossplatform/__init__.py +0 -0
  86. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/crossplatform/reply_to_message.py +0 -0
  87. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/crossplatform/scheduler.py +0 -0
  88. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/crossplatform/send_message.py +0 -0
  89. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/decode_base64_image.py +0 -0
  90. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/__init__.py +0 -0
  91. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/email_tracking.py +0 -0
  92. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/quote_filter.py +0 -0
  93. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/replace_cid_images_with_base64.py +0 -0
  94. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/save_email_message.py +0 -0
  95. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/email/validate_email_config.py +0 -0
  96. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/get_public_origin.py +0 -0
  97. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/internal/__init__.py +0 -0
  98. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/internal/generate_text_message_data.py +0 -0
  99. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/internal/save_internal_message.py +0 -0
  100. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/internal/send_internal_message.py +0 -0
  101. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/llm/README.md +0 -0
  102. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/llm/__init__.py +0 -0
  103. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/llm/tool_calls.py +0 -0
  104. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/__init__.py +0 -0
  105. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/download_file.py +0 -0
  106. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/escape_markdown.py +0 -0
  107. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/get_file_path.py +0 -0
  108. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/save_telegram_message.py +0 -0
  109. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/set_telegram_webhook.py +0 -0
  110. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/start_typing_in_telegram.py +0 -0
  111. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/telegram/stop_typing_in_telegram.py +0 -0
  112. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/whatsapp/__init__.py +0 -0
  113. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/whatsapp/get_template.py +0 -0
  114. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/whatsapp/save_whatsapp_message.py +0 -0
  115. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/whatsapp/save_whatsapp_message_status.py +0 -0
  116. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/services/whatsapp/send_whatsapp_message.py +0 -0
  117. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/signals.py +0 -0
  118. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/static/unicom/css/bootstrap_scoped.css +0 -0
  119. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/static/unicom/css/draft_message_mobile.css +0 -0
  120. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/static/unicom/js/channel_config.js +0 -0
  121. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/static/unicom/js/tinymce_ai_template.js +0 -0
  122. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/static/unicom/js/tinymce_init.js +0 -0
  123. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/chat/change_list.html +0 -0
  124. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/chat/compose.html +0 -0
  125. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/chat_history.html +0 -0
  126. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/forms/email_message_form.html +0 -0
  127. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/forms/text_message_form.html +0 -0
  128. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/includes/ai_template_modal.html +0 -0
  129. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/includes/loading_indicators.html +0 -0
  130. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/includes/message_actions_menu.html +0 -0
  131. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/admin/unicom/messagetemplate/change_form.html +0 -0
  132. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/templates/code_templates/category_processor.py +0 -0
  133. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/urls.py +0 -0
  134. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/__init__.py +0 -0
  135. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/chat_history_view.py +0 -0
  136. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/compose_view.py +0 -0
  137. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/email_tracking.py +0 -0
  138. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/inline_image.py +0 -0
  139. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/message_template.py +0 -0
  140. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/telegram_webhook.py +0 -0
  141. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom/views/whatsapp_webhook.py +0 -0
  142. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom_project/__init__.py +0 -0
  143. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom_project/asgi.py +0 -0
  144. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom_project/settings.py +0 -0
  145. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom_project/urls.py +0 -0
  146. {django_unicom-25.2.27.dev1 → django_unicom-25.2.27.dev2}/unicom_project/wsgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-unicom
3
- Version: 25.2.27.dev1
3
+ Version: 25.2.27.dev2
4
4
  Summary: Unified communication layer for Django (Telegram, WhatsApp, Email)
5
5
  Home-page: https://github.com/meena-erian/unicom
6
6
  Author: Meena (Menas) Erian
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-unicom
3
- Version: 25.2.27.dev1
3
+ Version: 25.2.27.dev2
4
4
  Summary: Unified communication layer for Django (Telegram, WhatsApp, Email)
5
5
  Home-page: https://github.com/meena-erian/unicom
6
6
  Author: Meena (Menas) Erian
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '25.2.27.dev1'
32
- __version_tuple__ = version_tuple = (25, 2, 27, 'dev1')
31
+ __version__ = version = '25.2.27.dev2'
32
+ __version_tuple__ = version_tuple = (25, 2, 27, 'dev2')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -498,6 +498,8 @@ class Message(models.Model):
498
498
  m = re.match(r"data:(.*?);base64,(.*)", url)
499
499
  if m:
500
500
  mime, b64data = m.groups()
501
+ if not isinstance(mime, str):
502
+ raise ValueError(f"Expected mime to be string, got {type(mime)}: {mime}")
501
503
  ext = mime.split("/")[-1]
502
504
  image_file_name = f"media/{uuid.uuid4()}.{ext}"
503
505
  with open(image_file_name, "wb") as f:
@@ -108,7 +108,11 @@ class MessageTemplate(models.Model):
108
108
  for img in soup.find_all('img'):
109
109
  src = img.get('src', '')
110
110
  if src.startswith('data:image/') and ';base64,' in src:
111
+ if not isinstance(src, str):
112
+ raise ValueError(f"Expected src to be string, got {type(src)}: {src}")
111
113
  header, b64data = src.split(';base64,', 1)
114
+ if not isinstance(header, str):
115
+ raise ValueError(f"Expected header to be string, got {type(header)}: {header}")
112
116
  mime = header.split(':')[1]
113
117
  ext = mimetypes.guess_extension(mime) or '.png'
114
118
  data = base64.b64decode(b64data)
@@ -66,6 +66,8 @@ class IMAPThreadManager:
66
66
  channel.listen_to_IMAP()
67
67
  except Exception as e:
68
68
  logger.exception(f"Listener for Channel {channel.pk} crashed: {e}")
69
+ import traceback
70
+ logger.error(f"Full traceback: {traceback.format_exc()}")
69
71
  time.sleep(10)
70
72
  finally:
71
73
  # ensure no DB connections are leaked by this thread
@@ -41,6 +41,8 @@ def listen_to_IMAP(channel):
41
41
  # logger.info(f"Channel {channel.pk}: Found email {msg.id} (uid={uid})")
42
42
  except Exception as e:
43
43
  logger.error(f"Channel {channel.pk}: Failed to process UID {uid}: {e}")
44
+ import traceback
45
+ logger.error(f"Full traceback: {traceback.format_exc()}")
44
46
 
45
47
  if mark_seen_on == 'on_save':
46
48
  if uids:
@@ -85,13 +87,17 @@ def listen_to_IMAP(channel):
85
87
  server.add_flags(uid, [SEEN])
86
88
  logger.debug(f"Incoming email - Message-ID: {msg.id}, In-Reply-To: {msg.raw.get('In-Reply-To') if msg.raw else 'None'}")
87
89
  logger.debug(f"Associated with chat: {msg.chat_id}")
88
- except Exception:
89
- logger.error(f"Channel {channel.pk}: Failed to process UID {uid}")
90
+ except Exception as e:
91
+ logger.error(f"Channel {channel.pk}: Failed to process UID {uid}: {e}")
92
+ import traceback
93
+ logger.error(f"Full traceback: {traceback.format_exc()}")
90
94
  finally:
91
95
  connections.close_all()
92
96
 
93
97
  except Exception as e:
94
98
  logger.error(f"Channel {channel.pk}: Fatal IMAP error: {e}, reconnecting in 30s…")
99
+ import traceback
100
+ logger.error(f"Full traceback: {traceback.format_exc()}")
95
101
  time.sleep(3)
96
102
  finally:
97
103
  # Ensure we close all connections to avoid leaks
@@ -223,7 +223,10 @@ def send_email_message(channel: Channel, params: dict, user: User=None):
223
223
  if parent:
224
224
  # First add any existing References from parent
225
225
  if parent.raw and 'References' in parent.raw:
226
- references.extend(parent.raw['References'].split())
226
+ references_header = parent.raw['References']
227
+ if not isinstance(references_header, str):
228
+ raise ValueError(f"Expected References header to be string, got {type(references_header)}: {references_header}")
229
+ references.extend((references_header or '').split())
227
230
  # Then add the parent's Message-ID
228
231
  references.append(params['reply_to_message_id'])
229
232
  else:
@@ -41,7 +41,11 @@ def html_base64_images_to_shortlinks(html: str) -> tuple[str, list[int]]:
41
41
  for img in soup.find_all('img'):
42
42
  src = img.get('src', '')
43
43
  if src.startswith('data:image/') and ';base64,' in src:
44
+ if not isinstance(src, str):
45
+ raise ValueError(f"Expected src to be string, got {type(src)}: {src}")
44
46
  header, b64data = src.split(';base64,', 1)
47
+ if not isinstance(header, str):
48
+ raise ValueError(f"Expected header to be string, got {type(header)}: {header}")
45
49
  mime = header.split(':')[1]
46
50
  ext = mimetypes.guess_extension(mime) or '.png'
47
51
  data = base64.b64decode(b64data)
@@ -125,7 +125,10 @@ def send_telegram_message(channel: Channel, params: dict, user: User=None, retry
125
125
  params[text_field_key] = params[text_field_key][:4095 - len(cropping_footer)] + cropping_footer
126
126
  elif "Can't find end of the entity starting at byte offset" in ret.get('description', ''):
127
127
  # Extract mentioned byte offset from error message
128
- byte_offset = int(ret['description'].split("byte offset")[1].split()[0])
128
+ description = ret['description']
129
+ if not isinstance(description, str):
130
+ raise ValueError(f"Expected description to be string, got {type(description)}: {description}")
131
+ byte_offset = int(description.split("byte offset")[1].split()[0])
129
132
  print(f"Byte offset: {byte_offset}")
130
133
  mentioned_char = params[text_field_key][byte_offset]
131
134
  print(f"Mentioned char that's causing the error: \"{mentioned_char}\"")