@backtomyfuture/exchange-cli-darwin-arm64 0.1.8 → 0.1.10

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 (243) hide show
  1. package/bin/_internal/Python +0 -0
  2. package/bin/_internal/Python.framework/Python +0 -0
  3. package/bin/_internal/Python.framework/Resources/Info.plist +3 -3
  4. package/bin/_internal/Python.framework/Versions/3.12/Python +0 -0
  5. package/bin/_internal/Python.framework/Versions/{3.14 → 3.12}/Resources/Info.plist +3 -3
  6. package/bin/_internal/Python.framework/Versions/Current/Python +0 -0
  7. package/bin/_internal/Python.framework/Versions/Current/Resources/Info.plist +3 -3
  8. package/bin/_internal/_cffi_backend.cpython-312-darwin.so +0 -0
  9. package/bin/_internal/ada92cb5d92a588d1b93__mypyc.cpython-312-darwin.so +0 -0
  10. package/bin/_internal/base_library.zip +0 -0
  11. package/bin/_internal/certifi/cacert.pem +0 -631
  12. package/bin/_internal/charset_normalizer/{md.cpython-314-darwin.so → cd.cpython-312-darwin.so} +0 -0
  13. package/bin/_internal/charset_normalizer/{cd.cpython-314-darwin.so → md.cpython-312-darwin.so} +0 -0
  14. package/bin/_internal/{click-8.3.2.dist-info → click-8.4.2.dist-info}/METADATA +1 -1
  15. package/bin/_internal/click-8.4.2.dist-info/RECORD +40 -0
  16. package/bin/_internal/cryptography/hazmat/bindings/_rust.abi3.so +0 -0
  17. package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/METADATA +7 -36
  18. package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/RECORD +137 -122
  19. package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/WHEEL +1 -1
  20. package/bin/_internal/cryptography-48.0.1.dist-info/sboms/cryptography-rust.cyclonedx.json +1362 -0
  21. package/bin/_internal/cryptography-48.0.1.dist-info/sboms/sbom.json +43 -0
  22. package/bin/_internal/exchangelib/__init__.py +120 -0
  23. package/bin/_internal/exchangelib/account.py +896 -0
  24. package/bin/_internal/exchangelib/attachments.py +268 -0
  25. package/bin/_internal/exchangelib/autodiscover/__init__.py +24 -0
  26. package/bin/_internal/exchangelib/autodiscover/cache.py +150 -0
  27. package/bin/_internal/exchangelib/autodiscover/discovery.py +491 -0
  28. package/bin/_internal/exchangelib/autodiscover/protocol.py +58 -0
  29. package/bin/_internal/exchangelib/configuration.py +106 -0
  30. package/bin/_internal/exchangelib/credentials.py +319 -0
  31. package/bin/_internal/exchangelib/errors.py +1710 -0
  32. package/bin/_internal/exchangelib/ewsdatetime.py +309 -0
  33. package/bin/_internal/exchangelib/extended_properties.py +311 -0
  34. package/bin/_internal/exchangelib/fields.py +1842 -0
  35. package/bin/_internal/exchangelib/folders/__init__.py +249 -0
  36. package/bin/_internal/exchangelib/folders/base.py +954 -0
  37. package/bin/_internal/exchangelib/folders/collections.py +576 -0
  38. package/bin/_internal/exchangelib/folders/known_folders.py +856 -0
  39. package/bin/_internal/exchangelib/folders/queryset.py +187 -0
  40. package/bin/_internal/exchangelib/folders/roots.py +390 -0
  41. package/bin/_internal/exchangelib/indexed_properties.py +96 -0
  42. package/bin/_internal/exchangelib/items/__init__.py +147 -0
  43. package/bin/_internal/exchangelib/items/base.py +241 -0
  44. package/bin/_internal/exchangelib/items/calendar_item.py +466 -0
  45. package/bin/_internal/exchangelib/items/contact.py +263 -0
  46. package/bin/_internal/exchangelib/items/item.py +413 -0
  47. package/bin/_internal/exchangelib/items/message.py +201 -0
  48. package/bin/_internal/exchangelib/items/post.py +38 -0
  49. package/bin/_internal/exchangelib/items/task.py +139 -0
  50. package/bin/_internal/exchangelib/properties.py +2364 -0
  51. package/bin/_internal/exchangelib/protocol.py +823 -0
  52. package/bin/_internal/exchangelib/queryset.py +691 -0
  53. package/bin/_internal/exchangelib/recurrence.py +349 -0
  54. package/bin/_internal/exchangelib/restriction.py +568 -0
  55. package/bin/_internal/exchangelib/services/__init__.py +117 -0
  56. package/bin/_internal/exchangelib/services/archive_item.py +33 -0
  57. package/bin/_internal/exchangelib/services/common.py +983 -0
  58. package/bin/_internal/exchangelib/services/convert_id.py +45 -0
  59. package/bin/_internal/exchangelib/services/copy_item.py +7 -0
  60. package/bin/_internal/exchangelib/services/create_attachment.py +34 -0
  61. package/bin/_internal/exchangelib/services/create_folder.py +45 -0
  62. package/bin/_internal/exchangelib/services/create_item.py +97 -0
  63. package/bin/_internal/exchangelib/services/create_user_configuration.py +19 -0
  64. package/bin/_internal/exchangelib/services/delete_attachment.py +28 -0
  65. package/bin/_internal/exchangelib/services/delete_folder.py +21 -0
  66. package/bin/_internal/exchangelib/services/delete_item.py +51 -0
  67. package/bin/_internal/exchangelib/services/delete_user_configuration.py +19 -0
  68. package/bin/_internal/exchangelib/services/empty_folder.py +25 -0
  69. package/bin/_internal/exchangelib/services/expand_dl.py +21 -0
  70. package/bin/_internal/exchangelib/services/export_items.py +27 -0
  71. package/bin/_internal/exchangelib/services/find_folder.py +80 -0
  72. package/bin/_internal/exchangelib/services/find_item.py +112 -0
  73. package/bin/_internal/exchangelib/services/find_people.py +106 -0
  74. package/bin/_internal/exchangelib/services/get_attachment.py +117 -0
  75. package/bin/_internal/exchangelib/services/get_delegate.py +45 -0
  76. package/bin/_internal/exchangelib/services/get_events.py +39 -0
  77. package/bin/_internal/exchangelib/services/get_folder.py +65 -0
  78. package/bin/_internal/exchangelib/services/get_item.py +41 -0
  79. package/bin/_internal/exchangelib/services/get_mail_tips.py +43 -0
  80. package/bin/_internal/exchangelib/services/get_persona.py +31 -0
  81. package/bin/_internal/exchangelib/services/get_room_lists.py +21 -0
  82. package/bin/_internal/exchangelib/services/get_rooms.py +21 -0
  83. package/bin/_internal/exchangelib/services/get_searchable_mailboxes.py +48 -0
  84. package/bin/_internal/exchangelib/services/get_server_time_zones.py +39 -0
  85. package/bin/_internal/exchangelib/services/get_streaming_events.py +102 -0
  86. package/bin/_internal/exchangelib/services/get_user_availability.py +67 -0
  87. package/bin/_internal/exchangelib/services/get_user_configuration.py +43 -0
  88. package/bin/_internal/exchangelib/services/get_user_oof_settings.py +40 -0
  89. package/bin/_internal/exchangelib/services/get_user_settings.py +87 -0
  90. package/bin/_internal/exchangelib/services/inbox_rules.py +104 -0
  91. package/bin/_internal/exchangelib/services/mark_as_junk.py +27 -0
  92. package/bin/_internal/exchangelib/services/move_folder.py +27 -0
  93. package/bin/_internal/exchangelib/services/move_item.py +28 -0
  94. package/bin/_internal/exchangelib/services/resolve_names.py +104 -0
  95. package/bin/_internal/exchangelib/services/send_item.py +26 -0
  96. package/bin/_internal/exchangelib/services/send_notification.py +43 -0
  97. package/bin/_internal/exchangelib/services/set_user_oof_settings.py +34 -0
  98. package/bin/_internal/exchangelib/services/subscribe.py +125 -0
  99. package/bin/_internal/exchangelib/services/sync_folder_hierarchy.py +95 -0
  100. package/bin/_internal/exchangelib/services/sync_folder_items.py +77 -0
  101. package/bin/_internal/exchangelib/services/unsubscribe.py +21 -0
  102. package/bin/_internal/exchangelib/services/update_folder.py +158 -0
  103. package/bin/_internal/exchangelib/services/update_item.py +113 -0
  104. package/bin/_internal/exchangelib/services/update_user_configuration.py +17 -0
  105. package/bin/_internal/exchangelib/services/upload_items.py +47 -0
  106. package/bin/_internal/exchangelib/settings.py +88 -0
  107. package/bin/_internal/exchangelib/transport.py +214 -0
  108. package/bin/_internal/exchangelib/util.py +894 -0
  109. package/bin/_internal/exchangelib/version.py +320 -0
  110. package/bin/_internal/exchangelib/winzone.py +662 -0
  111. package/bin/_internal/exchangelib-5.6.0.dist-info/INSTALLER +1 -0
  112. package/bin/_internal/exchangelib-5.6.0.dist-info/METADATA +77 -0
  113. package/bin/_internal/exchangelib-5.6.0.dist-info/RECORD +184 -0
  114. package/bin/_internal/exchangelib-5.6.0.dist-info/licenses/LICENSE +21 -0
  115. package/bin/_internal/exchangelib-5.6.0.dist-info/top_level.txt +1 -0
  116. package/bin/_internal/libcrypto.3.dylib +0 -0
  117. package/bin/_internal/libssl.3.dylib +0 -0
  118. package/bin/_internal/lxml/_elementpath.cpython-312-darwin.so +0 -0
  119. package/bin/_internal/lxml/builder.cpython-312-darwin.so +0 -0
  120. package/bin/_internal/lxml/{etree.cpython-314-darwin.so → etree.cpython-312-darwin.so} +0 -0
  121. package/bin/_internal/lxml/html/_difflib.cpython-312-darwin.so +0 -0
  122. package/bin/_internal/lxml/html/diff.cpython-312-darwin.so +0 -0
  123. package/bin/_internal/lxml/{objectify.cpython-314-darwin.so → objectify.cpython-312-darwin.so} +0 -0
  124. package/bin/_internal/lxml/sax.cpython-312-darwin.so +0 -0
  125. package/bin/_internal/python3.12/lib-dynload/_asyncio.cpython-312-darwin.so +0 -0
  126. package/bin/_internal/{python3.14/lib-dynload/termios.cpython-314-darwin.so → python3.12/lib-dynload/_bisect.cpython-312-darwin.so} +0 -0
  127. package/bin/_internal/{python3.14/lib-dynload/_sha2.cpython-314-darwin.so → python3.12/lib-dynload/_blake2.cpython-312-darwin.so} +0 -0
  128. package/bin/_internal/{python3.14/lib-dynload/_bz2.cpython-314-darwin.so → python3.12/lib-dynload/_bz2.cpython-312-darwin.so} +0 -0
  129. package/bin/_internal/{python3.14/lib-dynload/_codecs_cn.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_cn.cpython-312-darwin.so} +0 -0
  130. package/bin/_internal/{python3.14/lib-dynload/_codecs_hk.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_hk.cpython-312-darwin.so} +0 -0
  131. package/bin/_internal/{python3.14/lib-dynload/_interpqueues.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_iso2022.cpython-312-darwin.so} +0 -0
  132. package/bin/_internal/{python3.14/lib-dynload/_codecs_jp.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_jp.cpython-312-darwin.so} +0 -0
  133. package/bin/_internal/{python3.14/lib-dynload/_codecs_kr.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_kr.cpython-312-darwin.so} +0 -0
  134. package/bin/_internal/{python3.14/lib-dynload/_codecs_tw.cpython-314-darwin.so → python3.12/lib-dynload/_codecs_tw.cpython-312-darwin.so} +0 -0
  135. package/bin/_internal/{python3.14/lib-dynload/_statistics.cpython-314-darwin.so → python3.12/lib-dynload/_contextvars.cpython-312-darwin.so} +0 -0
  136. package/bin/_internal/{python3.14/lib-dynload/_csv.cpython-314-darwin.so → python3.12/lib-dynload/_csv.cpython-312-darwin.so} +0 -0
  137. package/bin/_internal/python3.12/lib-dynload/_ctypes.cpython-312-darwin.so +0 -0
  138. package/bin/_internal/python3.12/lib-dynload/_datetime.cpython-312-darwin.so +0 -0
  139. package/bin/_internal/{python3.14/lib-dynload/_dbm.cpython-314-darwin.so → python3.12/lib-dynload/_dbm.cpython-312-darwin.so} +0 -0
  140. package/bin/_internal/python3.12/lib-dynload/_decimal.cpython-312-darwin.so +0 -0
  141. package/bin/_internal/python3.12/lib-dynload/_elementtree.cpython-312-darwin.so +0 -0
  142. package/bin/_internal/python3.12/lib-dynload/_hashlib.cpython-312-darwin.so +0 -0
  143. package/bin/_internal/{python3.14/lib-dynload/_heapq.cpython-314-darwin.so → python3.12/lib-dynload/_heapq.cpython-312-darwin.so} +0 -0
  144. package/bin/_internal/python3.12/lib-dynload/_json.cpython-312-darwin.so +0 -0
  145. package/bin/_internal/python3.12/lib-dynload/_lzma.cpython-312-darwin.so +0 -0
  146. package/bin/_internal/{python3.14/lib-dynload/_md5.cpython-314-darwin.so → python3.12/lib-dynload/_md5.cpython-312-darwin.so} +0 -0
  147. package/bin/_internal/python3.12/lib-dynload/_multibytecodec.cpython-312-darwin.so +0 -0
  148. package/bin/_internal/{python3.14/lib-dynload/_multiprocessing.cpython-314-darwin.so → python3.12/lib-dynload/_multiprocessing.cpython-312-darwin.so} +0 -0
  149. package/bin/_internal/python3.12/lib-dynload/_opcode.cpython-312-darwin.so +0 -0
  150. package/bin/_internal/python3.12/lib-dynload/_pickle.cpython-312-darwin.so +0 -0
  151. package/bin/_internal/{python3.14/lib-dynload/_bisect.cpython-314-darwin.so → python3.12/lib-dynload/_posixshmem.cpython-312-darwin.so} +0 -0
  152. package/bin/_internal/{python3.14/lib-dynload/_posixsubprocess.cpython-314-darwin.so → python3.12/lib-dynload/_posixsubprocess.cpython-312-darwin.so} +0 -0
  153. package/bin/_internal/{python3.14/lib-dynload/_queue.cpython-314-darwin.so → python3.12/lib-dynload/_queue.cpython-312-darwin.so} +0 -0
  154. package/bin/_internal/{python3.14/lib-dynload/_random.cpython-314-darwin.so → python3.12/lib-dynload/_random.cpython-312-darwin.so} +0 -0
  155. package/bin/_internal/{python3.14/lib-dynload/_scproxy.cpython-314-darwin.so → python3.12/lib-dynload/_scproxy.cpython-312-darwin.so} +0 -0
  156. package/bin/_internal/{python3.14/lib-dynload/_sha1.cpython-314-darwin.so → python3.12/lib-dynload/_sha1.cpython-312-darwin.so} +0 -0
  157. package/bin/_internal/python3.12/lib-dynload/_sha2.cpython-312-darwin.so +0 -0
  158. package/bin/_internal/{python3.14/lib-dynload/_blake2.cpython-314-darwin.so → python3.12/lib-dynload/_sha3.cpython-312-darwin.so} +0 -0
  159. package/bin/_internal/python3.12/lib-dynload/_socket.cpython-312-darwin.so +0 -0
  160. package/bin/_internal/python3.12/lib-dynload/_ssl.cpython-312-darwin.so +0 -0
  161. package/bin/_internal/{python3.14/lib-dynload/_posixshmem.cpython-314-darwin.so → python3.12/lib-dynload/_statistics.cpython-312-darwin.so} +0 -0
  162. package/bin/_internal/python3.12/lib-dynload/_struct.cpython-312-darwin.so +0 -0
  163. package/bin/_internal/{python3.14/lib-dynload/_uuid.cpython-314-darwin.so → python3.12/lib-dynload/_uuid.cpython-312-darwin.so} +0 -0
  164. package/bin/_internal/{python3.14/lib-dynload/_zoneinfo.cpython-314-darwin.so → python3.12/lib-dynload/_zoneinfo.cpython-312-darwin.so} +0 -0
  165. package/bin/_internal/python3.12/lib-dynload/array.cpython-312-darwin.so +0 -0
  166. package/bin/_internal/{python3.14/lib-dynload/binascii.cpython-314-darwin.so → python3.12/lib-dynload/binascii.cpython-312-darwin.so} +0 -0
  167. package/bin/_internal/{python3.14/lib-dynload/fcntl.cpython-314-darwin.so → python3.12/lib-dynload/fcntl.cpython-312-darwin.so} +0 -0
  168. package/bin/_internal/{python3.14/lib-dynload/grp.cpython-314-darwin.so → python3.12/lib-dynload/grp.cpython-312-darwin.so} +0 -0
  169. package/bin/_internal/python3.12/lib-dynload/math.cpython-312-darwin.so +0 -0
  170. package/bin/_internal/{python3.14/lib-dynload/_sha3.cpython-314-darwin.so → python3.12/lib-dynload/mmap.cpython-312-darwin.so} +0 -0
  171. package/bin/_internal/python3.12/lib-dynload/pyexpat.cpython-312-darwin.so +0 -0
  172. package/bin/_internal/python3.12/lib-dynload/readline.cpython-312-darwin.so +0 -0
  173. package/bin/_internal/{python3.14/lib-dynload/resource.cpython-314-darwin.so → python3.12/lib-dynload/resource.cpython-312-darwin.so} +0 -0
  174. package/bin/_internal/{python3.14/lib-dynload/select.cpython-314-darwin.so → python3.12/lib-dynload/select.cpython-312-darwin.so} +0 -0
  175. package/bin/_internal/{python3.14/lib-dynload/syslog.cpython-314-darwin.so → python3.12/lib-dynload/syslog.cpython-312-darwin.so} +0 -0
  176. package/bin/_internal/python3.12/lib-dynload/termios.cpython-312-darwin.so +0 -0
  177. package/bin/_internal/python3.12/lib-dynload/unicodedata.cpython-312-darwin.so +0 -0
  178. package/bin/_internal/python3.12/lib-dynload/zlib.cpython-312-darwin.so +0 -0
  179. package/bin/_internal/tzdata/zoneinfo/Africa/Casablanca +0 -0
  180. package/bin/_internal/tzdata/zoneinfo/Africa/El_Aaiun +0 -0
  181. package/bin/_internal/tzdata/zoneinfo/America/Edmonton +0 -0
  182. package/bin/_internal/tzdata/zoneinfo/America/Vancouver +0 -0
  183. package/bin/_internal/tzdata/zoneinfo/America/Yellowknife +0 -0
  184. package/bin/_internal/tzdata/zoneinfo/Asia/Ho_Chi_Minh +0 -0
  185. package/bin/_internal/tzdata/zoneinfo/Asia/Saigon +0 -0
  186. package/bin/_internal/tzdata/zoneinfo/Canada/Mountain +0 -0
  187. package/bin/_internal/tzdata/zoneinfo/Canada/Pacific +0 -0
  188. package/bin/_internal/tzdata/zoneinfo/leapseconds +4 -4
  189. package/bin/_internal/tzdata/zoneinfo/tzdata.zi +11 -131
  190. package/bin/_internal/tzdata/zoneinfo/zone.tab +2 -2
  191. package/bin/_internal/tzdata/zoneinfo/zone1970.tab +2 -2
  192. package/bin/_internal/tzdata/zoneinfo/zonenow.tab +8 -2
  193. package/bin/exchange-cli +0 -0
  194. package/package.json +10 -7
  195. package/bin/_internal/81d243bd2c585b0f4821__mypyc.cpython-314-darwin.so +0 -0
  196. package/bin/_internal/Python.framework/Versions/3.14/Python +0 -0
  197. package/bin/_internal/_cffi_backend.cpython-314-darwin.so +0 -0
  198. package/bin/_internal/click-8.3.2.dist-info/RECORD +0 -40
  199. package/bin/_internal/liblzma.5.dylib +0 -0
  200. package/bin/_internal/libmpdec.4.dylib +0 -0
  201. package/bin/_internal/libzstd.1.dylib +0 -0
  202. package/bin/_internal/lxml/_elementpath.cpython-314-darwin.so +0 -0
  203. package/bin/_internal/lxml/builder.cpython-314-darwin.so +0 -0
  204. package/bin/_internal/lxml/html/_difflib.cpython-314-darwin.so +0 -0
  205. package/bin/_internal/lxml/html/diff.cpython-314-darwin.so +0 -0
  206. package/bin/_internal/lxml/sax.cpython-314-darwin.so +0 -0
  207. package/bin/_internal/python3.14/lib-dynload/_asyncio.cpython-314-darwin.so +0 -0
  208. package/bin/_internal/python3.14/lib-dynload/_codecs_iso2022.cpython-314-darwin.so +0 -0
  209. package/bin/_internal/python3.14/lib-dynload/_ctypes.cpython-314-darwin.so +0 -0
  210. package/bin/_internal/python3.14/lib-dynload/_decimal.cpython-314-darwin.so +0 -0
  211. package/bin/_internal/python3.14/lib-dynload/_elementtree.cpython-314-darwin.so +0 -0
  212. package/bin/_internal/python3.14/lib-dynload/_hashlib.cpython-314-darwin.so +0 -0
  213. package/bin/_internal/python3.14/lib-dynload/_hmac.cpython-314-darwin.so +0 -0
  214. package/bin/_internal/python3.14/lib-dynload/_interpreters.cpython-314-darwin.so +0 -0
  215. package/bin/_internal/python3.14/lib-dynload/_json.cpython-314-darwin.so +0 -0
  216. package/bin/_internal/python3.14/lib-dynload/_lzma.cpython-314-darwin.so +0 -0
  217. package/bin/_internal/python3.14/lib-dynload/_multibytecodec.cpython-314-darwin.so +0 -0
  218. package/bin/_internal/python3.14/lib-dynload/_pickle.cpython-314-darwin.so +0 -0
  219. package/bin/_internal/python3.14/lib-dynload/_socket.cpython-314-darwin.so +0 -0
  220. package/bin/_internal/python3.14/lib-dynload/_ssl.cpython-314-darwin.so +0 -0
  221. package/bin/_internal/python3.14/lib-dynload/_struct.cpython-314-darwin.so +0 -0
  222. package/bin/_internal/python3.14/lib-dynload/_zstd.cpython-314-darwin.so +0 -0
  223. package/bin/_internal/python3.14/lib-dynload/array.cpython-314-darwin.so +0 -0
  224. package/bin/_internal/python3.14/lib-dynload/math.cpython-314-darwin.so +0 -0
  225. package/bin/_internal/python3.14/lib-dynload/mmap.cpython-314-darwin.so +0 -0
  226. package/bin/_internal/python3.14/lib-dynload/pyexpat.cpython-314-darwin.so +0 -0
  227. package/bin/_internal/python3.14/lib-dynload/readline.cpython-314-darwin.so +0 -0
  228. package/bin/_internal/python3.14/lib-dynload/unicodedata.cpython-314-darwin.so +0 -0
  229. package/bin/_internal/python3.14/lib-dynload/zlib.cpython-314-darwin.so +0 -0
  230. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/INSTALLER +0 -1
  231. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/METADATA +0 -133
  232. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/RECORD +0 -21
  233. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/REQUESTED +0 -0
  234. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/licenses/LICENSE +0 -73
  235. package/bin/_internal/setuptools/_vendor/importlib_metadata-8.7.1.dist-info/top_level.txt +0 -1
  236. /package/bin/_internal/{click-8.3.2.dist-info → click-8.4.2.dist-info}/INSTALLER +0 -0
  237. /package/bin/_internal/{click-8.3.2.dist-info → click-8.4.2.dist-info}/WHEEL +0 -0
  238. /package/bin/_internal/{click-8.3.2.dist-info → click-8.4.2.dist-info}/licenses/LICENSE.txt +0 -0
  239. /package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/INSTALLER +0 -0
  240. /package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/licenses/LICENSE +0 -0
  241. /package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/licenses/LICENSE.APACHE +0 -0
  242. /package/bin/_internal/{cryptography-46.0.7.dist-info → cryptography-48.0.1.dist-info}/licenses/LICENSE.BSD +0 -0
  243. /package/bin/_internal/{setuptools/_vendor/importlib_metadata-8.7.1.dist-info → exchangelib-5.6.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,263 @@
1
+ import datetime
2
+ import logging
3
+
4
+ from ..fields import (
5
+ Base64Field,
6
+ BodyContentAttributedValueField,
7
+ BooleanField,
8
+ CharField,
9
+ Choice,
10
+ ChoiceField,
11
+ DateTimeBackedDateField,
12
+ DateTimeField,
13
+ EmailAddressAttributedValueField,
14
+ EmailAddressesField,
15
+ EmailAddressField,
16
+ EWSElementField,
17
+ EWSElementListField,
18
+ IdElementField,
19
+ ImAddressField,
20
+ MailboxField,
21
+ MailboxListField,
22
+ MemberListField,
23
+ PersonaPhoneNumberField,
24
+ PhoneNumberAttributedValueField,
25
+ PhoneNumberField,
26
+ PhysicalAddressField,
27
+ PostalAddressAttributedValueField,
28
+ StringAttributedValueField,
29
+ TextField,
30
+ TextListField,
31
+ URIField,
32
+ )
33
+ from ..properties import Address, Attribution, CompleteName, EmailAddress, FolderId, IdChangeKeyMixIn, PersonaId
34
+ from ..util import TNS
35
+ from ..version import EXCHANGE_2010, EXCHANGE_2010_SP2
36
+ from .item import Item
37
+
38
+ log = logging.getLogger(__name__)
39
+
40
+
41
+ class Contact(Item):
42
+ """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/contact"""
43
+
44
+ ELEMENT_NAME = "Contact"
45
+
46
+ file_as = TextField(field_uri="contacts:FileAs")
47
+ file_as_mapping = ChoiceField(
48
+ field_uri="contacts:FileAsMapping",
49
+ choices={
50
+ Choice("None"),
51
+ Choice("LastCommaFirst"),
52
+ Choice("FirstSpaceLast"),
53
+ Choice("Company"),
54
+ Choice("LastCommaFirstCompany"),
55
+ Choice("CompanyLastFirst"),
56
+ Choice("LastFirst"),
57
+ Choice("LastFirstCompany"),
58
+ Choice("CompanyLastCommaFirst"),
59
+ Choice("LastFirstSuffix"),
60
+ Choice("LastSpaceFirstCompany"),
61
+ Choice("CompanyLastSpaceFirst"),
62
+ Choice("LastSpaceFirst"),
63
+ Choice("DisplayName"),
64
+ Choice("FirstName"),
65
+ Choice("LastFirstMiddleSuffix"),
66
+ Choice("LastName"),
67
+ Choice("Empty"),
68
+ },
69
+ )
70
+ display_name = TextField(field_uri="contacts:DisplayName", is_required=True)
71
+ given_name = CharField(field_uri="contacts:GivenName")
72
+ initials = TextField(field_uri="contacts:Initials")
73
+ middle_name = CharField(field_uri="contacts:MiddleName")
74
+ nickname = TextField(field_uri="contacts:Nickname")
75
+ complete_name = EWSElementField(field_uri="contacts:CompleteName", value_cls=CompleteName, is_read_only=True)
76
+ company_name = TextField(field_uri="contacts:CompanyName")
77
+ email_addresses = EmailAddressesField(field_uri="contacts:EmailAddress")
78
+ physical_addresses = PhysicalAddressField(field_uri="contacts:PhysicalAddress")
79
+ phone_numbers = PhoneNumberField(field_uri="contacts:PhoneNumber")
80
+ assistant_name = TextField(field_uri="contacts:AssistantName")
81
+ birthday = DateTimeBackedDateField(field_uri="contacts:Birthday", default_time=datetime.time(11, 59))
82
+ business_homepage = URIField(field_uri="contacts:BusinessHomePage")
83
+ children = TextListField(field_uri="contacts:Children")
84
+ companies = TextListField(field_uri="contacts:Companies", is_searchable=False)
85
+ contact_source = ChoiceField(
86
+ field_uri="contacts:ContactSource", choices={Choice("Store"), Choice("ActiveDirectory")}, is_read_only=True
87
+ )
88
+ department = TextField(field_uri="contacts:Department")
89
+ generation = TextField(field_uri="contacts:Generation")
90
+ im_addresses = ImAddressField(field_uri="contacts:ImAddress")
91
+ job_title = TextField(field_uri="contacts:JobTitle")
92
+ manager = TextField(field_uri="contacts:Manager")
93
+ mileage = TextField(field_uri="contacts:Mileage")
94
+ office = TextField(field_uri="contacts:OfficeLocation")
95
+ postal_address_index = ChoiceField(
96
+ field_uri="contacts:PostalAddressIndex",
97
+ choices={Choice("Business"), Choice("Home"), Choice("Other"), Choice("None")},
98
+ default="None",
99
+ is_required_after_save=True,
100
+ )
101
+ profession = TextField(field_uri="contacts:Profession")
102
+ spouse_name = TextField(field_uri="contacts:SpouseName")
103
+ surname = CharField(field_uri="contacts:Surname")
104
+ wedding_anniversary = DateTimeBackedDateField(
105
+ field_uri="contacts:WeddingAnniversary", default_time=datetime.time(11, 59)
106
+ )
107
+ has_picture = BooleanField(field_uri="contacts:HasPicture", supported_from=EXCHANGE_2010, is_read_only=True)
108
+ phonetic_full_name = TextField(
109
+ field_uri="contacts:PhoneticFullName", supported_from=EXCHANGE_2010_SP2, is_read_only=True
110
+ )
111
+ phonetic_first_name = TextField(
112
+ field_uri="contacts:PhoneticFirstName", supported_from=EXCHANGE_2010_SP2, is_read_only=True
113
+ )
114
+ phonetic_last_name = TextField(
115
+ field_uri="contacts:PhoneticLastName", supported_from=EXCHANGE_2010_SP2, is_read_only=True
116
+ )
117
+ email_alias = EmailAddressField(field_uri="contacts:Alias", is_read_only=True, supported_from=EXCHANGE_2010_SP2)
118
+ # 'notes' is documented in MSDN but apparently unused. Writing to it raises ErrorInvalidPropertyRequest. OWA
119
+ # put entries into the 'notes' form field into the 'body' field.
120
+ notes = CharField(field_uri="contacts:Notes", supported_from=EXCHANGE_2010_SP2, is_read_only=True)
121
+ # 'photo' is documented in MSDN but apparently unused. Writing to it raises ErrorInvalidPropertyRequest. OWA
122
+ # adds photos as FileAttachments on the contact item (with 'is_contact_photo=True'), which automatically flips
123
+ # the 'has_picture' field.
124
+ photo = Base64Field(field_uri="contacts:Photo", supported_from=EXCHANGE_2010_SP2, is_read_only=True)
125
+ user_smime_certificate = Base64Field(
126
+ field_uri="contacts:UserSMIMECertificate", supported_from=EXCHANGE_2010_SP2, is_read_only=True
127
+ )
128
+ ms_exchange_certificate = Base64Field(
129
+ field_uri="contacts:MSExchangeCertificate", supported_from=EXCHANGE_2010_SP2, is_read_only=True
130
+ )
131
+ directory_id = TextField(field_uri="contacts:DirectoryId", supported_from=EXCHANGE_2010_SP2, is_read_only=True)
132
+ manager_mailbox = MailboxField(
133
+ field_uri="contacts:ManagerMailbox", supported_from=EXCHANGE_2010_SP2, is_read_only=True
134
+ )
135
+ direct_reports = MailboxListField(
136
+ field_uri="contacts:DirectReports", supported_from=EXCHANGE_2010_SP2, is_read_only=True
137
+ )
138
+ # O365 throws ErrorInternalServerError "[0x004f0102] MapiReplyToBlob" if UniqueBody is requested
139
+ unique_body_idx = Item.FIELDS.index_by_name("unique_body")
140
+ FIELDS = Item.FIELDS[:unique_body_idx] + Item.FIELDS[unique_body_idx + 1 :]
141
+
142
+
143
+ class Persona(IdChangeKeyMixIn):
144
+ """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/persona"""
145
+
146
+ ELEMENT_NAME = "Persona"
147
+ ID_ELEMENT_CLS = PersonaId
148
+
149
+ _id = IdElementField(field_uri="persona:PersonaId", value_cls=ID_ELEMENT_CLS, namespace=TNS)
150
+ persona_type = CharField(field_uri="persona:PersonaType")
151
+ persona_object_type = TextField(field_uri="persona:PersonaObjectStatus")
152
+ creation_time = DateTimeField(field_uri="persona:CreationTime")
153
+ bodies = BodyContentAttributedValueField(field_uri="persona:Bodies")
154
+ display_name_first_last_sort_key = TextField(field_uri="persona:DisplayNameFirstLastSortKey")
155
+ display_name_last_first_sort_key = TextField(field_uri="persona:DisplayNameLastFirstSortKey")
156
+ company_sort_key = TextField(field_uri="persona:CompanyNameSortKey")
157
+ home_sort_key = TextField(field_uri="persona:HomeCitySortKey")
158
+ work_city_sort_key = TextField(field_uri="persona:WorkCitySortKey")
159
+ display_name_first_last_header = CharField(field_uri="persona:DisplayNameFirstLastHeader")
160
+ display_name_last_first_header = CharField(field_uri="persona:DisplayNameLastFirstHeader")
161
+ file_as_header = TextField(field_uri="persona:FileAsHeader")
162
+ display_name = CharField(field_uri="persona:DisplayName")
163
+ display_name_first_last = CharField(field_uri="persona:DisplayNameFirstLast")
164
+ display_name_last_first = CharField(field_uri="persona:DisplayNameLastFirst")
165
+ file_as = CharField(field_uri="persona:FileAs")
166
+ file_as_id = TextField(field_uri="persona:FileAsId")
167
+ display_name_prefix = CharField(field_uri="persona:DisplayNamePrefix")
168
+ given_name = CharField(field_uri="persona:GivenName")
169
+ middle_name = CharField(field_uri="persona:MiddleName")
170
+ surname = CharField(field_uri="persona:Surname")
171
+ generation = CharField(field_uri="persona:Generation")
172
+ nickname = TextField(field_uri="persona:Nickname")
173
+ yomi_company_name = TextField(field_uri="persona:YomiCompanyName")
174
+ yomi_first_name = TextField(field_uri="persona:YomiFirstName")
175
+ yomi_last_name = TextField(field_uri="persona:YomiLastName")
176
+ title = CharField(field_uri="persona:Title")
177
+ department = TextField(field_uri="persona:Department")
178
+ company_name = CharField(field_uri="persona:CompanyName")
179
+ email_address = EWSElementField(field_uri="persona:EmailAddress", value_cls=EmailAddress)
180
+ email_addresses = EWSElementListField(field_uri="persona:EmailAddresses", value_cls=Address)
181
+ PhoneNumber = PersonaPhoneNumberField(field_uri="persona:PhoneNumber")
182
+ im_address = CharField(field_uri="persona:ImAddress")
183
+ home_city = CharField(field_uri="persona:HomeCity")
184
+ work_city = CharField(field_uri="persona:WorkCity")
185
+ relevance_score = CharField(field_uri="persona:RelevanceScore")
186
+ folder_ids = EWSElementListField(field_uri="persona:FolderIds", value_cls=FolderId)
187
+ attributions = EWSElementListField(field_uri="persona:Attributions", value_cls=Attribution)
188
+ display_names = StringAttributedValueField(field_uri="persona:DisplayNames")
189
+ file_ases = StringAttributedValueField(field_uri="persona:FileAses")
190
+ file_as_ids = StringAttributedValueField(field_uri="persona:FileAsIds")
191
+ display_name_prefixes = StringAttributedValueField(field_uri="persona:DisplayNamePrefixes")
192
+ given_names = StringAttributedValueField(field_uri="persona:GivenNames")
193
+ middle_names = StringAttributedValueField(field_uri="persona:MiddleNames")
194
+ surnames = StringAttributedValueField(field_uri="persona:Surnames")
195
+ generations = StringAttributedValueField(field_uri="persona:Generations")
196
+ nicknames = StringAttributedValueField(field_uri="persona:Nicknames")
197
+ initials = StringAttributedValueField(field_uri="persona:Initials")
198
+ yomi_company_names = StringAttributedValueField(field_uri="persona:YomiCompanyNames")
199
+ yomi_first_names = StringAttributedValueField(field_uri="persona:YomiFirstNames")
200
+ yomi_last_names = StringAttributedValueField(field_uri="persona:YomiLastNames")
201
+ business_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:BusinessPhoneNumbers")
202
+ business_phone_numbers2 = PhoneNumberAttributedValueField(field_uri="persona:BusinessPhoneNumbers2")
203
+ home_phones = PhoneNumberAttributedValueField(field_uri="persona:HomePhones")
204
+ home_phones2 = PhoneNumberAttributedValueField(field_uri="persona:HomePhones2")
205
+ mobile_phones = PhoneNumberAttributedValueField(field_uri="persona:MobilePhones")
206
+ mobile_phones2 = PhoneNumberAttributedValueField(field_uri="persona:MobilePhones2")
207
+ assistant_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:AssistantPhoneNumbers")
208
+ callback_phones = PhoneNumberAttributedValueField(field_uri="persona:CallbackPhones")
209
+ car_phones = PhoneNumberAttributedValueField(field_uri="persona:CarPhones")
210
+ home_faxes = PhoneNumberAttributedValueField(field_uri="persona:HomeFaxes")
211
+ organization_main_phones = PhoneNumberAttributedValueField(field_uri="persona:OrganizationMainPhones")
212
+ other_faxes = PhoneNumberAttributedValueField(field_uri="persona:OtherFaxes")
213
+ other_telephones = PhoneNumberAttributedValueField(field_uri="persona:OtherTelephones")
214
+ other_phones2 = PhoneNumberAttributedValueField(field_uri="persona:OtherPhones2")
215
+ pagers = PhoneNumberAttributedValueField(field_uri="persona:Pagers")
216
+ radio_phones = PhoneNumberAttributedValueField(field_uri="persona:RadioPhones")
217
+ telex_numbers = PhoneNumberAttributedValueField(field_uri="persona:TelexNumbers")
218
+ tty_tdd_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:TTYTDDPhoneNumbers")
219
+ work_faxes = PhoneNumberAttributedValueField(field_uri="persona:WorkFaxes")
220
+ emails1 = EmailAddressAttributedValueField(field_uri="persona:Emails1")
221
+ emails2 = EmailAddressAttributedValueField(field_uri="persona:Emails2")
222
+ emails3 = EmailAddressAttributedValueField(field_uri="persona:Emails3")
223
+ business_home_pages = StringAttributedValueField(field_uri="persona:BusinessHomePages")
224
+ personal_home_pages = StringAttributedValueField(field_uri="persona:PersonalHomePages")
225
+ office_locations = StringAttributedValueField(field_uri="persona:OfficeLocations")
226
+ im_addresses = StringAttributedValueField(field_uri="persona:ImAddresses")
227
+ im_addresses2 = StringAttributedValueField(field_uri="persona:ImAddresses2")
228
+ im_addresses3 = StringAttributedValueField(field_uri="persona:ImAddresses3")
229
+ business_addresses = PostalAddressAttributedValueField(field_uri="persona:BusinessAddresses")
230
+ home_addresses = PostalAddressAttributedValueField(field_uri="persona:HomeAddresses")
231
+ other_addresses = PostalAddressAttributedValueField(field_uri="persona:OtherAddresses")
232
+ titles = StringAttributedValueField(field_uri="persona:Titles")
233
+ departments = StringAttributedValueField(field_uri="persona:Departments")
234
+ company_names = StringAttributedValueField(field_uri="persona:CompanyNames")
235
+ managers = StringAttributedValueField(field_uri="persona:Managers")
236
+ assistant_names = StringAttributedValueField(field_uri="persona:AssistantNames")
237
+ professions = StringAttributedValueField(field_uri="persona:Professions")
238
+ spouse_names = StringAttributedValueField(field_uri="persona:SpouseNames")
239
+ children = StringAttributedValueField(field_uri="persona:Children")
240
+ schools = StringAttributedValueField(field_uri="persona:Schools")
241
+ hobbies = StringAttributedValueField(field_uri="persona:Hobbies")
242
+ wedding_anniversaries = StringAttributedValueField(field_uri="persona:WeddingAnniversaries")
243
+ birthdays = StringAttributedValueField(field_uri="persona:Birthdays")
244
+ locations = StringAttributedValueField(field_uri="persona:Locations")
245
+ # This class has an additional field of type "ExtendedPropertyAttributedValueField" and
246
+ # field_uri 'persona:ExtendedProperties'
247
+
248
+
249
+ class DistributionList(Item):
250
+ """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/distributionlist"""
251
+
252
+ ELEMENT_NAME = "DistributionList"
253
+
254
+ display_name = CharField(field_uri="contacts:DisplayName", is_required=True)
255
+ file_as = CharField(field_uri="contacts:FileAs", is_read_only=True)
256
+ contact_source = ChoiceField(
257
+ field_uri="contacts:ContactSource", choices={Choice("Store"), Choice("ActiveDirectory")}, is_read_only=True
258
+ )
259
+ members = MemberListField(field_uri="distributionlist:Members")
260
+
261
+ # O365 throws ErrorInternalServerError "[0x004f0102] MapiReplyToBlob" if UniqueBody is requested
262
+ unique_body_idx = Item.FIELDS.index_by_name("unique_body")
263
+ FIELDS = Item.FIELDS[:unique_body_idx] + Item.FIELDS[unique_body_idx + 1 :]
@@ -0,0 +1,413 @@
1
+ import logging
2
+
3
+ from ..fields import (
4
+ AttachmentField,
5
+ BodyField,
6
+ BooleanField,
7
+ CharField,
8
+ CharListField,
9
+ Choice,
10
+ ChoiceField,
11
+ CultureField,
12
+ DateTimeField,
13
+ EffectiveRightsField,
14
+ EWSElementField,
15
+ FieldPath,
16
+ IntegerField,
17
+ MessageHeaderField,
18
+ MimeContentField,
19
+ TextField,
20
+ URIField,
21
+ )
22
+ from ..properties import (
23
+ ConversationId,
24
+ Fields,
25
+ OccurrenceItemId,
26
+ ParentFolderId,
27
+ RecurringMasterItemId,
28
+ ReferenceItemId,
29
+ ResponseObjects,
30
+ )
31
+ from ..util import is_iterable, require_account, require_id
32
+ from ..version import EXCHANGE_2010, EXCHANGE_2013
33
+ from .base import (
34
+ ALL_OCCURRENCES,
35
+ AUTO_RESOLVE,
36
+ HARD_DELETE,
37
+ ID_ONLY,
38
+ MOVE_TO_DELETED_ITEMS,
39
+ SAVE_ONLY,
40
+ SEND_AND_SAVE_COPY,
41
+ SEND_TO_NONE,
42
+ SOFT_DELETE,
43
+ BaseItem,
44
+ )
45
+
46
+ log = logging.getLogger(__name__)
47
+
48
+
49
+ class Item(BaseItem):
50
+ """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/item"""
51
+
52
+ ELEMENT_NAME = "Item"
53
+
54
+ mime_content = MimeContentField(field_uri="item:MimeContent", is_read_only_after_send=True)
55
+ _id = BaseItem.FIELDS["_id"]
56
+ parent_folder_id = EWSElementField(field_uri="item:ParentFolderId", value_cls=ParentFolderId, is_read_only=True)
57
+ item_class = CharField(field_uri="item:ItemClass", is_read_only=True)
58
+ subject = CharField(field_uri="item:Subject")
59
+ sensitivity = ChoiceField(
60
+ field_uri="item:Sensitivity",
61
+ choices={Choice("Normal"), Choice("Personal"), Choice("Private"), Choice("Confidential")},
62
+ is_required=True,
63
+ default="Normal",
64
+ )
65
+ text_body = TextField(field_uri="item:TextBody", is_read_only=True, supported_from=EXCHANGE_2013)
66
+ body = BodyField(field_uri="item:Body") # Accepts and returns Body or HTMLBody instances
67
+ attachments = AttachmentField(field_uri="item:Attachments") # ItemAttachment or FileAttachment
68
+ datetime_received = DateTimeField(field_uri="item:DateTimeReceived", is_read_only=True)
69
+ size = IntegerField(field_uri="item:Size", is_read_only=True) # Item size in bytes
70
+ categories = CharListField(field_uri="item:Categories")
71
+ importance = ChoiceField(
72
+ field_uri="item:Importance",
73
+ choices={Choice("Low"), Choice("Normal"), Choice("High")},
74
+ is_required=True,
75
+ default="Normal",
76
+ )
77
+ in_reply_to = TextField(field_uri="item:InReplyTo")
78
+ is_submitted = BooleanField(field_uri="item:IsSubmitted", is_read_only=True)
79
+ is_draft = BooleanField(field_uri="item:IsDraft", is_read_only=True)
80
+ is_from_me = BooleanField(field_uri="item:IsFromMe", is_read_only=True)
81
+ is_resend = BooleanField(field_uri="item:IsResend", is_read_only=True)
82
+ is_unmodified = BooleanField(field_uri="item:IsUnmodified", is_read_only=True)
83
+ headers = MessageHeaderField(field_uri="item:InternetMessageHeaders", is_read_only=True)
84
+ datetime_sent = DateTimeField(field_uri="item:DateTimeSent", is_read_only=True)
85
+ datetime_created = DateTimeField(field_uri="item:DateTimeCreated", is_read_only=True)
86
+ response_objects = EWSElementField(
87
+ field_uri="item:ResponseObjects",
88
+ value_cls=ResponseObjects,
89
+ is_read_only=True,
90
+ )
91
+ # Placeholder for ResponseObjects
92
+ reminder_due_by = DateTimeField(field_uri="item:ReminderDueBy", is_required_after_save=True, is_searchable=False)
93
+ reminder_is_set = BooleanField(field_uri="item:ReminderIsSet", is_required=True, default=False)
94
+ reminder_minutes_before_start = IntegerField(
95
+ field_uri="item:ReminderMinutesBeforeStart", is_required_after_save=True, min=0, default=0
96
+ )
97
+ display_cc = TextField(field_uri="item:DisplayCc", is_read_only=True)
98
+ display_to = TextField(field_uri="item:DisplayTo", is_read_only=True)
99
+ has_attachments = BooleanField(field_uri="item:HasAttachments", is_read_only=True)
100
+ # ExtendedProperty fields go here
101
+ culture = CultureField(field_uri="item:Culture", is_required_after_save=True, is_searchable=False)
102
+ effective_rights = EffectiveRightsField(field_uri="item:EffectiveRights", is_read_only=True)
103
+ last_modified_name = CharField(field_uri="item:LastModifiedName", is_read_only=True)
104
+ last_modified_time = DateTimeField(field_uri="item:LastModifiedTime", is_read_only=True)
105
+ is_associated = BooleanField(field_uri="item:IsAssociated", is_read_only=True, supported_from=EXCHANGE_2010)
106
+ web_client_read_form_query_string = URIField(
107
+ field_uri="item:WebClientReadFormQueryString", is_read_only=True, supported_from=EXCHANGE_2010
108
+ )
109
+ web_client_edit_form_query_string = URIField(
110
+ field_uri="item:WebClientEditFormQueryString", is_read_only=True, supported_from=EXCHANGE_2010
111
+ )
112
+ conversation_id = EWSElementField(
113
+ field_uri="item:ConversationId", value_cls=ConversationId, is_read_only=True, supported_from=EXCHANGE_2010
114
+ )
115
+ unique_body = BodyField(field_uri="item:UniqueBody", is_read_only=True, supported_from=EXCHANGE_2010)
116
+
117
+ FIELDS = Fields()
118
+
119
+ # Used to register extended properties
120
+ INSERT_AFTER_FIELD = "has_attachments"
121
+
122
+ def __init__(self, **kwargs):
123
+ super().__init__(**kwargs)
124
+ if self.attachments:
125
+ for a in self.attachments:
126
+ if a.parent_item:
127
+ if a.parent_item is not self:
128
+ raise ValueError(f"'parent_item' of attachment {a} must point to this item")
129
+ else:
130
+ a.parent_item = self
131
+ self.attach(self.attachments)
132
+ else:
133
+ self.attachments = []
134
+
135
+ def save(self, update_fields=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE):
136
+ from .task import Task
137
+
138
+ if self.id:
139
+ item_id, changekey = self._update(
140
+ update_fieldnames=update_fields,
141
+ message_disposition=SAVE_ONLY,
142
+ conflict_resolution=conflict_resolution,
143
+ send_meeting_invitations=send_meeting_invitations,
144
+ )
145
+ if (
146
+ self.id != item_id
147
+ and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId))
148
+ and not isinstance(self, Task)
149
+ ):
150
+ # When we update an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so
151
+ # the ID of this item changes.
152
+ #
153
+ # When we update certain fields on a task, the ID may change. A full description is available at
154
+ # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation-task
155
+ raise ValueError("'id' mismatch in returned update response")
156
+ # Don't check that changekeys are different. No-op saves will sometimes leave the changekey intact
157
+ self._id = self.ID_ELEMENT_CLS(item_id, changekey)
158
+ else:
159
+ if update_fields:
160
+ raise ValueError("'update_fields' is only valid for updates")
161
+ tmp_attachments = None
162
+ if self.account and self.account.version.build < EXCHANGE_2013 and self.attachments:
163
+ # At least some versions prior to Exchange 2013 can't save attachments immediately. You need to first
164
+ # save, then attach. Store the attachment of this item temporarily and attach later.
165
+ tmp_attachments, self.attachments = self.attachments, []
166
+ item = self._create(message_disposition=SAVE_ONLY, send_meeting_invitations=send_meeting_invitations)
167
+ self._id = self.ID_ELEMENT_CLS(item.id, item.changekey)
168
+ for old_att, new_att in zip(self.attachments, item.attachments):
169
+ if old_att.attachment_id is not None:
170
+ raise ValueError("Old 'attachment_id' is not empty")
171
+ if new_att.attachment_id is None:
172
+ raise ValueError("New 'attachment_id' is empty")
173
+ old_att.attachment_id = new_att.attachment_id
174
+ if tmp_attachments:
175
+ # Exchange 2007 workaround. See above
176
+ self.attach(tmp_attachments)
177
+ return self
178
+
179
+ @require_account
180
+ def _create(self, message_disposition, send_meeting_invitations):
181
+ # Return a BulkCreateResult because we want to return the ID of both the main item *and* attachments. In send
182
+ # and send-and-save-copy mode, the server does not return an ID, so we just return True.
183
+ from ..services import CreateItem
184
+
185
+ return CreateItem(account=self.account).get(
186
+ items=[self],
187
+ folder=self.folder,
188
+ message_disposition=message_disposition,
189
+ send_meeting_invitations=send_meeting_invitations,
190
+ )
191
+
192
+ def _update_fieldnames(self):
193
+ from .contact import Contact, DistributionList
194
+
195
+ # Return the list of fields we are allowed to update
196
+ update_fieldnames = []
197
+ for f in self.supported_fields(version=self.account.version):
198
+ if f.name == "attachments":
199
+ # Attachments are handled separately after item creation
200
+ continue
201
+ if f.is_read_only:
202
+ # These cannot be changed
203
+ continue
204
+ if (f.is_required or f.is_required_after_save) and (
205
+ getattr(self, f.name) is None or (f.is_list and not getattr(self, f.name))
206
+ ):
207
+ # These are required and cannot be deleted
208
+ continue
209
+ if not self.is_draft and f.is_read_only_after_send:
210
+ # These cannot be changed when the item is no longer a draft
211
+ continue
212
+ if f.name == "message_id" and f.is_read_only_after_send:
213
+ # 'message_id' doesn't support updating, no matter the draft status
214
+ continue
215
+ if f.name == "mime_content" and isinstance(self, (Contact, DistributionList)):
216
+ # Contact and DistributionList don't support updating mime_content, no matter the draft status
217
+ continue
218
+ update_fieldnames.append(f.name)
219
+ return update_fieldnames
220
+
221
+ @require_account
222
+ def _update(self, update_fieldnames, message_disposition, conflict_resolution, send_meeting_invitations):
223
+ from ..services import UpdateItem
224
+
225
+ if not self.changekey:
226
+ raise ValueError(f"{self.__class__.__name__} must have changekey")
227
+ if not update_fieldnames:
228
+ # The fields to update was not specified explicitly. Update all fields where update is possible
229
+ update_fieldnames = self._update_fieldnames()
230
+ return UpdateItem(account=self.account).get(
231
+ items=[(self, update_fieldnames)],
232
+ message_disposition=message_disposition,
233
+ conflict_resolution=conflict_resolution,
234
+ send_meeting_invitations_or_cancellations=send_meeting_invitations,
235
+ suppress_read_receipts=True,
236
+ expect_result=message_disposition != SEND_AND_SAVE_COPY,
237
+ )
238
+
239
+ @require_id
240
+ def refresh(self):
241
+ # Updates the item based on fresh data from EWS
242
+ from ..services import GetItem
243
+
244
+ additional_fields = {FieldPath(field=f) for f in self.supported_fields(version=self.account.version)}
245
+ res = GetItem(account=self.account).get(items=[self], additional_fields=additional_fields, shape=ID_ONLY)
246
+ if self.id != res.id and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId)):
247
+ # When we refresh an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so
248
+ # the ID of this item changes.
249
+ raise ValueError("'id' mismatch in returned update response")
250
+ for f in self.FIELDS:
251
+ setattr(self, f.name, getattr(res, f.name))
252
+ # 'parent_item' should point to 'self', not 'fresh_item'. That way, 'fresh_item' can be garbage collected.
253
+ for a in self.attachments:
254
+ a.parent_item = self
255
+ return self
256
+
257
+ @require_id
258
+ def copy(self, to_folder):
259
+ from ..services import CopyItem
260
+
261
+ # If 'to_folder' is a public folder or a folder in a different mailbox then None is returned
262
+ return CopyItem(account=self.account).get(
263
+ items=[self],
264
+ to_folder=to_folder,
265
+ expect_result=None,
266
+ )
267
+
268
+ @require_id
269
+ def move(self, to_folder):
270
+ from ..services import MoveItem
271
+
272
+ res = MoveItem(account=self.account).get(
273
+ items=[self],
274
+ to_folder=to_folder,
275
+ expect_result=None,
276
+ )
277
+ if res is None:
278
+ # Assume 'to_folder' is a public folder or a folder in a different mailbox
279
+ self._id = None
280
+ return
281
+ self._id = self.ID_ELEMENT_CLS(*res)
282
+ self.folder = to_folder
283
+
284
+ def move_to_trash(
285
+ self,
286
+ send_meeting_cancellations=SEND_TO_NONE,
287
+ affected_task_occurrences=ALL_OCCURRENCES,
288
+ suppress_read_receipts=True,
289
+ ):
290
+ # Delete and move to the trash folder.
291
+ self._delete(
292
+ delete_type=MOVE_TO_DELETED_ITEMS,
293
+ send_meeting_cancellations=send_meeting_cancellations,
294
+ affected_task_occurrences=affected_task_occurrences,
295
+ suppress_read_receipts=suppress_read_receipts,
296
+ )
297
+ self._id = None
298
+ self.folder = self.account.trash
299
+
300
+ def soft_delete(
301
+ self,
302
+ send_meeting_cancellations=SEND_TO_NONE,
303
+ affected_task_occurrences=ALL_OCCURRENCES,
304
+ suppress_read_receipts=True,
305
+ ):
306
+ # Delete and move to the dumpster, if it is enabled.
307
+ self._delete(
308
+ delete_type=SOFT_DELETE,
309
+ send_meeting_cancellations=send_meeting_cancellations,
310
+ affected_task_occurrences=affected_task_occurrences,
311
+ suppress_read_receipts=suppress_read_receipts,
312
+ )
313
+ self._id = None
314
+ self.folder = self.account.recoverable_items_deletions
315
+
316
+ def delete(
317
+ self,
318
+ send_meeting_cancellations=SEND_TO_NONE,
319
+ affected_task_occurrences=ALL_OCCURRENCES,
320
+ suppress_read_receipts=True,
321
+ ):
322
+ # Remove the item permanently. No copies are stored anywhere.
323
+ self._delete(
324
+ delete_type=HARD_DELETE,
325
+ send_meeting_cancellations=send_meeting_cancellations,
326
+ affected_task_occurrences=affected_task_occurrences,
327
+ suppress_read_receipts=suppress_read_receipts,
328
+ )
329
+ self._id, self.folder = None, None
330
+
331
+ @require_id
332
+ def _delete(self, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts):
333
+ from ..services import DeleteItem
334
+
335
+ DeleteItem(account=self.account).get(
336
+ items=[self],
337
+ delete_type=delete_type,
338
+ send_meeting_cancellations=send_meeting_cancellations,
339
+ affected_task_occurrences=affected_task_occurrences,
340
+ suppress_read_receipts=suppress_read_receipts,
341
+ )
342
+
343
+ @require_id
344
+ def archive(self, to_folder):
345
+ from ..services import ArchiveItem
346
+
347
+ return ArchiveItem(account=self.account).get(items=[self], to_folder=to_folder, expect_result=True)
348
+
349
+ def attach(self, attachments):
350
+ """Add an attachment, or a list of attachments, to this item. If the item has already been saved, the
351
+ attachments will be created on the server immediately. If the item has not yet been saved, the attachments will
352
+ be created on the server when the item is saved.
353
+
354
+ Adding attachments to an existing item will update the changekey of the item.
355
+
356
+ :param attachments:
357
+ """
358
+ if not is_iterable(attachments, generators_allowed=True):
359
+ attachments = [attachments]
360
+ for a in attachments:
361
+ if not a.parent_item:
362
+ a.parent_item = self
363
+ if self.id and not a.attachment_id:
364
+ # Already saved object. Attach the attachment server-side now
365
+ a.attach()
366
+ if a not in self.attachments:
367
+ self.attachments.append(a)
368
+
369
+ def detach(self, attachments):
370
+ """Remove an attachment, or a list of attachments, from this item. If the item has already been saved, the
371
+ attachments will be deleted on the server immediately. If the item has not yet been saved, the attachments will
372
+ simply not be created on the server the item is saved.
373
+
374
+ Removing attachments from an existing item will update the changekey of the item.
375
+
376
+ :param attachments:
377
+ """
378
+ if not is_iterable(attachments, generators_allowed=True):
379
+ attachments = [attachments]
380
+ if attachments is self.attachments:
381
+ # Don't remove from the same list we are iterating
382
+ attachments = list(attachments)
383
+ for a in attachments:
384
+ if a.parent_item is not self:
385
+ raise ValueError("Attachment does not belong to this item")
386
+ if self.id:
387
+ # Item is already created. Detach the attachment server-side now
388
+ a.detach()
389
+ if a in self.attachments:
390
+ self.attachments.remove(a)
391
+
392
+ @require_id
393
+ def create_forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None):
394
+ from .message import ForwardItem
395
+
396
+ return ForwardItem(
397
+ account=self.account,
398
+ reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey),
399
+ subject=subject,
400
+ new_body=body,
401
+ to_recipients=to_recipients,
402
+ cc_recipients=cc_recipients,
403
+ bcc_recipients=bcc_recipients,
404
+ )
405
+
406
+ def forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None):
407
+ return self.create_forward(
408
+ subject,
409
+ body,
410
+ to_recipients,
411
+ cc_recipients,
412
+ bcc_recipients,
413
+ ).send()