kopano-set-oof 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #!/usr/bin/python -u
  2. import os
  3. import locale
  4. import sys
  5. import getopt
  6. import datetime
  7. import time
  8. import json
  9. try:
  10. import MAPI
  11. from MAPI.Util import *
  12. from MAPI.Time import *
  13. from MAPI.Struct import *
  14. except ImportError as e:
  15. print("Not all modules can be loaded. The following modules are required:")
  16. print("- MAPI")
  17. print("")
  18. print(e)
  19. sys.exit(1)
  20. PR_EC_OUTOFOFFICE = PROP_TAG(PT_BOOLEAN, PR_EC_BASE+0x60)
  21. PR_EC_OUTOFOFFICE_MSG = PROP_TAG(PT_TSTRING, PR_EC_BASE+0x61)
  22. PR_EC_OUTOFOFFICE_SUBJECT = PROP_TAG(PT_TSTRING, PR_EC_BASE+0x62)
  23. PR_EC_OUTOFOFFICE_FROM = PROP_TAG(PT_SYSTIME, PR_EC_BASE+0x63)
  24. PR_EC_OUTOFOFFICE_UNTIL = PROP_TAG(PT_SYSTIME, PR_EC_BASE+0x64)
  25. MODE_ENABLE = 1
  26. MODE_DISABLE = 2
  27. MODE_UPDATE_ONLY = 3
  28. def print_help():
  29. print("Usage: %s -u [username of mailbox]" % sys.argv[0])
  30. print("")
  31. print("Manage out of office messages of users")
  32. print("")
  33. print("Required arguments:")
  34. print(" -u, --user user to set out of office message for")
  35. print(" -m, --mode 0 to disable out of office (default), 1 to enable")
  36. print("")
  37. print("optional arguments:")
  38. print(" --from specify the date/time when oof should become active")
  39. print(" --until specify the date/time when oof should become inactive again")
  40. print(" -t, --subject specify the subject to be set in oof message")
  41. print(" -n, --message text file containing body of out of office message")
  42. print(" -h, --host Host to connect with. Default: file:///var/run/kopano/server.sock")
  43. print(" -s, --sslkey-file SSL key file to authenticate as admin.")
  44. print(" -p, --sslkey-pass Password for the SSL key file.")
  45. print(" --dump-json Dumps the current status as JSON.")
  46. print(" --help Show this help message and exit.")
  47. print("")
  48. print("")
  49. print("Example:")
  50. print(" Enable out of office message of mailbox user1 with subject 'test' and body from file /tmp/oof-message")
  51. print(" $ %s --user user1 --mode 1 --subject 'test' --message /tmp/oof-message" % sys.argv[0])
  52. print("")
  53. print(" Enable out of office message of mailbox user1 with subject 'test' and body from file /tmp/oof-message in a multi-server-environment")
  54. print(" $ %s --user user1 --mode 1 --subject 'test' --message /tmp/oof-message --host https://127.0.0.1:237/ --sslkey-file /etc/kopano/ssl/client.pem --sslkey-pass password" % sys.argv[0])
  55. print("")
  56. print(" Disable out of office message of mailbox user1 in a multi-server-environment")
  57. print(" $ %s --user user1 --mode 0 --sslkey-file /etc/kopano/ssl/client.pem --host https://127.0.0.1:237/ --sslkey-pass password" % sys.argv[0])
  58. def PrintSubject(subject):
  59. if subject.ulPropTag == PR_EC_OUTOFOFFICE_SUBJECT:
  60. print("Current subject: '%s'" % subject.Value)
  61. else:
  62. print("Current subject: No subject set")
  63. def main(argv = None):
  64. if argv is None:
  65. argv = sys.argv
  66. try:
  67. opts, args = getopt.gnu_getopt(argv, "h:s:p:u:m:t:n:he", ['from=', 'until=', 'host=', 'sslkey-file=', 'sslkey-pass=', 'user=', 'mode=', 'subject=', 'message=', 'dump-json', 'help', ])
  68. except getopt.GetoptError as err:
  69. # print help information and exit:
  70. print(str(err))
  71. print("")
  72. print_help()
  73. return 1
  74. # defaults
  75. host = os.getenv("KOPANO_SOCKET", "default:")
  76. sslkey_file = None
  77. sslkey_pass = None
  78. mode = MODE_UPDATE_ONLY
  79. date_from = None
  80. date_until = None
  81. username = None
  82. subject = None
  83. message = None
  84. dump_json = False
  85. for o, a in opts:
  86. if o in ('-h', '--host'):
  87. host = a
  88. elif o in ('-s', '--sslkey-file'):
  89. sslkey_file = a
  90. elif o in ('-p', '--sslkey-pass'):
  91. sslkey_pass = a
  92. elif o in ('-u', '--user'):
  93. username = a
  94. elif o in ('-m', '--mode'):
  95. if a == '-':
  96. mode = MODE_UPDATE_ONLY
  97. elif a == '1':
  98. enabled = True
  99. mode = MODE_ENABLE
  100. else:
  101. enabled = False
  102. mode = MODE_DISABLE
  103. elif o == "--from":
  104. date_from = datetime.datetime.strptime(a, "%Y-%m-%d %H:%M")
  105. elif o == "--until":
  106. date_until = datetime.datetime.strptime(a, "%Y-%m-%d %H:%M")
  107. elif o in ('-t', '--subject'):
  108. subject = a
  109. elif o in ('-n', '--message'):
  110. message = a
  111. elif o == '--dump-json':
  112. dump_json = True
  113. elif o == '--help':
  114. print_help()
  115. return 0
  116. else:
  117. assert False, ("unhandled option '%s'" % o)
  118. if not username:
  119. print("No username specified.")
  120. print("")
  121. print_help()
  122. sys.exit(1)
  123. try:
  124. session = OpenECSession(username, '', host, sslkey_file = sslkey_file, sslkey_pass = sslkey_pass)
  125. except MAPIError as err:
  126. if err.hr == MAPI_E_LOGON_FAILED:
  127. print("Failed to logon. Make sure your SSL certificate is correct.")
  128. elif err.hr == MAPI_E_NETWORK_ERROR:
  129. print("Unable to connect to server. Make sure you specified the correct server.")
  130. else:
  131. print("Unexpected error occurred. hr=0x%08x" % err.hr)
  132. sys.exit(1)
  133. try:
  134. st = GetDefaultStore(session)
  135. except:
  136. print("Unable to open store for user '%s'" % username)
  137. try:
  138. oldstatus = st.GetProps([PR_EC_OUTOFOFFICE], 0)[0].Value
  139. if oldstatus == MAPI_E_NOT_FOUND:
  140. oldstatus = False
  141. except Exception:
  142. print("Unable to read out of office status of user '%s'" % username)
  143. try:
  144. oldsubject = st.GetProps([PR_EC_OUTOFOFFICE_SUBJECT], 0)[0].Value
  145. if oldsubject == MAPI_E_NOT_FOUND:
  146. oldsubject = None
  147. except Exception:
  148. print("Unable to read out of office subject of user '%s'" % username)
  149. try:
  150. oldmsg = st.GetProps([PR_EC_OUTOFOFFICE_MSG], 0)[0].Value
  151. if oldmsg == MAPI_E_NOT_FOUND:
  152. oldmsg = None
  153. except Exception:
  154. print("Unable to read out of office message of user '%s'" % username)
  155. try:
  156. oldfrom = st.GetProps([PR_EC_OUTOFOFFICE_FROM], 0)[0].Value
  157. if oldfrom == MAPI_E_NOT_FOUND:
  158. oldfrom = None
  159. else:
  160. oldfrom = oldfrom.datetime().isoformat()
  161. except Exception:
  162. oldfrom = None
  163. try:
  164. olduntil = st.GetProps([PR_EC_OUTOFOFFICE_UNTIL], 0)[0].Value
  165. if olduntil == MAPI_E_NOT_FOUND:
  166. olduntil = None
  167. else:
  168. olduntil = olduntil.datetime().isoformat()
  169. except Exception:
  170. olduntil = None
  171. if dump_json:
  172. result = json.dumps({
  173. 'set': bool(oldstatus),
  174. 'subject': oldsubject,
  175. 'message': oldmsg,
  176. 'from': oldfrom,
  177. 'until': olduntil,
  178. })
  179. print(result)
  180. sys.exit(0)
  181. if mode != MODE_UPDATE_ONLY:
  182. try:
  183. if oldstatus == enabled and not enabled:
  184. print("Out of office for user '%s' already disabled, skipping." % username)
  185. elif enabled:
  186. st.SetProps([SPropValue(PR_EC_OUTOFOFFICE, enabled)])
  187. if date_from or date_until:
  188. props = []
  189. if date_from:
  190. t1 = MAPI.Time.FileTime(0)
  191. t1.unixtime = time.mktime(date_from.timetuple())
  192. p1 = SPropValue(PR_EC_OUTOFOFFICE_FROM, t1)
  193. props.append(p1)
  194. if date_until:
  195. t2 = MAPI.Time.FileTime(0)
  196. t2.unixtime = time.mktime(date_until.timetuple())
  197. p2 = SPropValue(PR_EC_OUTOFOFFICE_UNTIL, t2)
  198. props.append(p2)
  199. st.SetProps(props)
  200. else:
  201. st.DeleteProps([PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL])
  202. print("Out of office enabled for user '%s'" % username)
  203. else:
  204. st.SetProps([SPropValue(PR_EC_OUTOFOFFICE, enabled)])
  205. print("Out of office disabled for user '%s'" % username)
  206. except:
  207. print("Unable to set out of office for user '%s'" % username)
  208. raise
  209. if mode != MODE_DISABLE:
  210. if date_from or date_until:
  211. try:
  212. props = []
  213. deleted_props = []
  214. if date_from:
  215. t1 = MAPI.Time.FileTime(0)
  216. t1.unixtime = time.mktime(date_from.timetuple())
  217. p1 = SPropValue(PR_EC_OUTOFOFFICE_FROM, t1)
  218. props.append(p1)
  219. else:
  220. deleted_props.append(PR_EC_OUTOFOFFICE_FROM)
  221. if date_until:
  222. t2 = MAPI.Time.FileTime(0)
  223. t2.unixtime = time.mktime(date_until.timetuple())
  224. p2 = SPropValue(PR_EC_OUTOFOFFICE_UNTIL, t2)
  225. props.append(p2)
  226. else:
  227. deleted_props.append(PR_EC_OUTOFOFFICE_UNTIL)
  228. st.DeleteProps(deleted_props)
  229. st.SetProps(props)
  230. except:
  231. print("Unable to update OOF date restriction for user '%s'" % username)
  232. raise
  233. if subject:
  234. try:
  235. if oldsubject == subject:
  236. print("Not changing subject for user '%s' as it was not updated" % username)
  237. else:
  238. print("Setting new subject '%s' for user '%s'" % (subject, username))
  239. st.SetProps([SPropValue(PR_EC_OUTOFOFFICE_SUBJECT, subject)])
  240. except:
  241. print("Unable to set out of office subject for user '%s'" % username)
  242. newsubject = st.GetProps([PR_EC_OUTOFOFFICE_SUBJECT], 0)
  243. PrintSubject(newsubject[0])
  244. if message:
  245. try:
  246. f = open(message, 'rt')
  247. except IOError:
  248. print("The specified file '%s' does not exist - Please specify a valid message file." % message)
  249. sys.exit(1)
  250. msg = f.read()
  251. f.close()
  252. try:
  253. if oldmsg == msg:
  254. print("Not updating message, already matching with input file.")
  255. else:
  256. print("Setting new out of office message for user '%s'" % username)
  257. st.SetProps([SPropValue(PR_EC_OUTOFOFFICE_MSG, msg)])
  258. except:
  259. print("Unable to set out of office message.")
  260. if __name__ == '__main__':
  261. locale.setlocale(locale.LC_ALL, '')
  262. sys.exit(main())