1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.exchange.graph;
21
22 import davmail.Settings;
23 import davmail.exception.HttpNotFoundException;
24 import davmail.exchange.ExchangeSession;
25 import davmail.exchange.auth.O365Token;
26 import davmail.exchange.ews.EwsExchangeSession;
27 import davmail.exchange.ews.ExtendedFieldURI;
28 import davmail.exchange.ews.Field;
29 import davmail.exchange.ews.FieldURI;
30 import davmail.exchange.ews.IndexedFieldURI;
31 import davmail.http.HttpClientAdapter;
32 import davmail.util.IOUtil;
33 import org.apache.http.HttpStatus;
34 import org.apache.http.client.methods.CloseableHttpResponse;
35 import org.apache.http.client.methods.HttpDelete;
36 import org.apache.http.client.methods.HttpGet;
37 import org.apache.http.client.methods.HttpPatch;
38 import org.apache.http.client.methods.HttpPost;
39 import org.apache.http.client.methods.HttpRequestBase;
40 import org.apache.http.client.utils.URIBuilder;
41 import org.apache.http.entity.ByteArrayEntity;
42 import org.codehaus.jettison.json.JSONArray;
43 import org.codehaus.jettison.json.JSONException;
44 import org.codehaus.jettison.json.JSONObject;
45
46 import javax.mail.MessagingException;
47 import javax.mail.internet.MimeMessage;
48 import javax.mail.util.SharedByteArrayInputStream;
49 import java.io.ByteArrayOutputStream;
50 import java.io.IOException;
51 import java.io.InputStream;
52 import java.net.URI;
53 import java.net.URISyntaxException;
54 import java.nio.charset.StandardCharsets;
55 import java.util.ArrayList;
56 import java.util.Date;
57 import java.util.HashMap;
58 import java.util.HashSet;
59 import java.util.List;
60 import java.util.Map;
61 import java.util.Set;
62 import java.util.zip.GZIPInputStream;
63
64 public class GraphExchangeSessionDraft extends ExchangeSession {
65 HttpClientAdapter httpClient;
66 O365Token token;
67
68
69
70
71 String apiVersion = "beta";
72
73 String baseUrl;
74
75 protected class Folder extends ExchangeSession.Folder {
76 public String lastModified;
77 public String id;
78 }
79
80 protected static final HashSet<FieldURI> FOLDER_PROPERTIES = new HashSet<>();
81
82 static {
83 FOLDER_PROPERTIES.add(Field.get("urlcompname"));
84 FOLDER_PROPERTIES.add(Field.get("folderDisplayName"));
85 FOLDER_PROPERTIES.add(Field.get("lastmodified"));
86 FOLDER_PROPERTIES.add(Field.get("folderclass"));
87 FOLDER_PROPERTIES.add(Field.get("ctag"));
88
89
90
91 FOLDER_PROPERTIES.add(Field.get("uidNext"));
92 FOLDER_PROPERTIES.add(Field.get("highestUid"));
93 }
94
95
96 public GraphExchangeSessionDraft(HttpClientAdapter httpClient, O365Token token, String userName) {
97 this.httpClient = httpClient;
98 this.token = token;
99 this.userName = userName;
100
101 this.baseUrl = Settings.GRAPH_URL;
102 }
103
104
105
106
107
108 public Folder getFolderByName(String folderName) throws URISyntaxException, IOException, JSONException {
109 Folder folder = null;
110
111 HttpRequestBase httpRequest = new GraphRequestBuilder()
112 .setMethod("GET")
113 .setAccessToken(token.getAccessToken())
114 .setObjectType("mailFolders")
115 .setObjectId(folderName)
116 .setExpandFields(FOLDER_PROPERTIES).build();
117
118 JSONObject jsonResponse = executeRequest(httpRequest);
119
120
121 folder = new Folder();
122 folder.folderPath = folderName;
123 folder.displayName = jsonResponse.optString("displayName");
124
125 LOGGER.debug("urlcompname " + Field.get("urlcompname").getGraphId());
126 LOGGER.debug("folderDisplayName " + jsonResponse.optString("displayName"));
127 LOGGER.debug("lastmodified " + Field.get("lastmodified").getGraphId());
128 LOGGER.debug("folderclass " + Field.get("folderclass").getGraphId());
129 LOGGER.debug("ctag " + Field.get("ctag").getGraphId());
130 LOGGER.debug("count " + Field.get("count").getGraphId());
131 LOGGER.debug("unread " + Field.get("unread").getGraphId());
132 LOGGER.debug("hassubs " + Field.get("hassubs").getGraphId());
133 LOGGER.debug("uidNext " + Field.get("uidNext").getGraphId());
134 LOGGER.debug("highestUid " + Field.get("highestUid").getGraphId());
135
136
137 JSONArray singleValueExtendedProperties = jsonResponse.optJSONArray("singleValueExtendedProperties");
138 if (singleValueExtendedProperties != null) {
139 for (int i = 0; i < singleValueExtendedProperties.length(); i++) {
140 JSONObject singleValueProperty = singleValueExtendedProperties.getJSONObject(i);
141 String singleValueId = singleValueProperty.getString("id");
142 String singleValue = singleValueProperty.getString("value");
143 if (Field.get("lastmodified").getGraphId().equals(singleValueId)) {
144
145 folder.lastModified = singleValue;
146 } else if (Field.get("folderclass").getGraphId().equals(singleValueId)) {
147 folder.folderClass = singleValue;
148 } else if (Field.get("uidNext").getGraphId().equals(singleValueId)) {
149 folder.uidNext = Long.parseLong(singleValue);
150 } else if (Field.get("ctag").getGraphId().equals(singleValueId)) {
151 folder.ctag = singleValue;
152
153
154
155
156
157
158
159 } else {
160 LOGGER.warn("Unknown property " + singleValueId);
161 }
162
163 }
164 }
165 folder.count = jsonResponse.getInt("totalItemCount");
166 folder.unreadCount = jsonResponse.getInt("unreadItemCount");
167 folder.hasChildren = jsonResponse.getInt("childFolderCount") > 0;
168
169 return folder;
170 }
171
172
173
174
175
176
177 private String buildExpand(HashSet<FieldURI> fields) {
178 ArrayList<String> singleValueProperties = new ArrayList<>();
179 ArrayList<String> multiValueProperties = new ArrayList<>();
180 for (FieldURI fieldURI : fields) {
181 if (fieldURI instanceof ExtendedFieldURI) {
182 singleValueProperties.add(fieldURI.getGraphId());
183 } else if (fieldURI instanceof IndexedFieldURI) {
184 multiValueProperties.add(fieldURI.getGraphId());
185 }
186 }
187 StringBuilder expand = new StringBuilder();
188 if (!singleValueProperties.isEmpty()) {
189 expand.append("singleValueExtendedProperties($filter=");
190 appendExpandProperties(expand, singleValueProperties);
191 expand.append(")");
192 }
193 if (!multiValueProperties.isEmpty()) {
194 if (!singleValueProperties.isEmpty()) {
195 expand.append(",");
196 }
197 expand.append("multiValueExtendedProperties($filter=");
198 appendExpandProperties(expand, multiValueProperties);
199 expand.append(")");
200 }
201 return expand.toString();
202 }
203
204 public void appendExpandProperties(StringBuilder buffer, List<String> properties) {
205 boolean first = true;
206 for (String id : properties) {
207 if (first) {
208 first = false;
209 } else {
210 buffer.append(" or ");
211 }
212 buffer.append("id eq '").append(id).append("'");
213 }
214 }
215
216
217 @Override
218 public void close() {
219
220 }
221
222 @Override
223 public String formatSearchDate(Date date) {
224 return null;
225 }
226
227 @Override
228 protected void buildSessionInfo(URI uri) throws IOException {
229
230 }
231
232 @Override
233 public Message createMessage(String folderPath, String messageName, HashMap<String, String> properties, MimeMessage mimeMessage) throws IOException {
234 ByteArrayOutputStream baos = new ByteArrayOutputStream();
235 try {
236 mimeMessage.writeTo(baos);
237 } catch (MessagingException e) {
238 throw new IOException(e.getMessage());
239 }
240 baos.close();
241 byte[] mimeContent = IOUtil.encodeBase64(baos.toByteArray());
242
243
244 try {
245 String folderId = getFolderIdIfExists(folderPath);
246 String path = "/beta/me/mailFolders/" + folderId + "/messages";
247 path = "/beta/me/messages";
248 HttpPost httpPost = new HttpPost(new URIBuilder(baseUrl).setPath(path).build());
249 httpPost.setHeader("Content-Type", "text/plain");
250
251
252 httpPost.setEntity(new ByteArrayEntity(mimeContent));
253 JSONObject response = executeRequest(httpPost);
254
255
256 path = "/beta/me/messages/" + response.get("id");
257 HttpPatch httpPatch = new HttpPatch(new URIBuilder(baseUrl).setPath(path).build());
258 httpPatch.setHeader("Content-Type", "application/json");
259
260
261 response.put("singleValueExtendedProperties", new JSONArray().put(
262 new JSONObject()
263 .put("id", Field.get("messageFlags").getGraphId())
264 .put("value", "4")
265 ));
266
267
268 httpPatch.setEntity(new ByteArrayEntity(response.toString().getBytes(StandardCharsets.UTF_8)));
269 response = executeRequest(httpPatch);
270 response = moveMessage(response.getString("id"), folderId);
271 getMessage(response.getString("id"));
272
273
274
275
276
277
278
279
280
281
282 } catch (URISyntaxException | JSONException e) {
283 throw new IOException(e);
284 }
285
286 return null;
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 }
318
319 private JSONObject updateMessage(String id, HashMap<String, String> properties) throws IOException {
320 try {
321 String path = "/beta/me/messages/" + id;
322 HttpPatch httpPatch = new HttpPatch(new URIBuilder(baseUrl).setPath(path).build());
323 httpPatch.setHeader("Content-Type", "application/json");
324
325 JSONObject jsonObject = new JSONObject();
326
327 jsonObject.put("isDraft", false);
328 jsonObject.put("singleValueExtendedProperties", new JSONArray().put(
329 new JSONObject()
330 .put("id", Field.get("messageFlags").getGraphId())
331 .put("value", "4")
332 ));
333
334
335 httpPatch.setEntity(new ByteArrayEntity(jsonObject.toString().getBytes(StandardCharsets.UTF_8)));
336 JSONObject response = executeRequest(httpPatch);
337 return response;
338
339 } catch (URISyntaxException | JSONException e) {
340 throw new IOException(e);
341 }
342 }
343
344 private JSONObject moveMessage(String id, String folderId) throws IOException {
345 try {
346 String path = "/beta/me/messages/" + id + "/move/";
347 HttpPost httpPost = new HttpPost(new URIBuilder(baseUrl).setPath(path).build());
348 httpPost.setHeader("Content-Type", "application/json");
349
350 JSONObject jsonObject = new JSONObject();
351 jsonObject.put("destinationId", folderId);
352
353 httpPost.setEntity(new ByteArrayEntity(jsonObject.toString().getBytes(StandardCharsets.UTF_8)));
354 JSONObject response = executeRequest(httpPost);
355 return response;
356
357 } catch (URISyntaxException | JSONException e) {
358 throw new IOException(e);
359 }
360 }
361
362 private Message getMessage(String id) throws URISyntaxException, IOException, JSONException {
363 HashSet<FieldURI> messageProperties = new HashSet<>();
364 messageProperties.add(Field.get("messageFlags"));
365 messageProperties.add(Field.get("imapUid"));
366 Message message = null;
367 URIBuilder uriBuilder = new URIBuilder(baseUrl)
368 .setPath("/beta/me/messages/" + id)
369 .addParameter("$expand", buildExpand(messageProperties));
370 HttpGet httpGet = new HttpGet(uriBuilder.build());
371 httpGet.setHeader("Authorization", "Bearer " + token.getAccessToken());
372 try (
373 CloseableHttpResponse response = httpClient.execute(httpGet);
374 ) {
375 JSONObject jsonResponse = new JsonResponseHandler().handleResponse(response);
376
377 JSONArray singleValueExtendedProperties = jsonResponse.optJSONArray("singleValueExtendedProperties");
378 if (singleValueExtendedProperties != null) {
379 for (int i = 0; i < singleValueExtendedProperties.length(); i++) {
380 JSONObject singleValueProperty = singleValueExtendedProperties.getJSONObject(i);
381 String singleValueId = singleValueProperty.getString("id");
382 String singleValue = singleValueProperty.getString("value");
383 if (Field.get("messageFlags").getGraphId().equals(singleValueId)) {
384 System.out.println("messageFlags: " + singleValue);
385 } else if (Field.get("imapUid").getGraphId().equals(singleValueId)) {
386 System.out.println("imapUid: " + singleValue);
387 } else {
388 LOGGER.warn("Unknown property " + singleValueId);
389 }
390
391 }
392
393
394 }
395 }
396 return message;
397 }
398
399 public void getMessageBody(String id) throws URISyntaxException, IOException, MessagingException {
400
401
402 MimeMessage mimeMessage = null;
403 URIBuilder uriBuilder = new URIBuilder(baseUrl)
404 .setPath("/beta/me/messages/" + id + "/$value");
405 HttpGet httpGet = new HttpGet(uriBuilder.build());
406 httpGet.setHeader("Authorization", "Bearer " + token.getAccessToken());
407 try (
408 CloseableHttpResponse response = httpClient.execute(httpGet);
409 ) {
410 try (InputStream inputStream = response.getEntity().getContent()) {
411 if (HttpClientAdapter.isGzipEncoded(response)) {
412 mimeMessage = new MimeMessage(null, new SharedByteArrayInputStream(IOUtil.readFully(new GZIPInputStream(inputStream))));
413 } else {
414 mimeMessage = new MimeMessage(null, new SharedByteArrayInputStream(IOUtil.readFully(inputStream)));
415 }
416 } catch (MessagingException e) {
417 throw new IOException(e.getMessage(), e);
418 }
419 ByteArrayOutputStream baos = new ByteArrayOutputStream();
420 mimeMessage.writeTo(baos);
421 System.out.println(baos.toString("UTF-8"));
422
423 }
424 }
425
426 @Override
427 public void updateMessage(Message message, Map<String, String> properties) throws IOException {
428
429 }
430
431 @Override
432 public void deleteMessage(Message message) throws IOException {
433
434 }
435
436 @Override
437 protected byte[] getContent(Message message) throws IOException {
438 return new byte[0];
439 }
440
441 @Override
442 public MessageList searchMessages(String folderName, Set<String> attributes, Condition condition) throws IOException {
443 return null;
444 }
445
446 @Override
447 public MultiCondition and(Condition... condition) {
448 return null;
449 }
450
451 @Override
452 public MultiCondition or(Condition... condition) {
453 return null;
454 }
455
456 @Override
457 public Condition not(Condition condition) {
458 return null;
459 }
460
461 @Override
462 public Condition isEqualTo(String attributeName, String value) {
463 return null;
464 }
465
466 @Override
467 public Condition isEqualTo(String attributeName, int value) {
468 return null;
469 }
470
471 @Override
472 public Condition headerIsEqualTo(String headerName, String value) {
473 return null;
474 }
475
476 @Override
477 public Condition gte(String attributeName, String value) {
478 return null;
479 }
480
481 @Override
482 public Condition gt(String attributeName, String value) {
483 return null;
484 }
485
486 @Override
487 public Condition lt(String attributeName, String value) {
488 return null;
489 }
490
491 @Override
492 public Condition lte(String attributeName, String value) {
493 return null;
494 }
495
496 @Override
497 public Condition contains(String attributeName, String value) {
498 return null;
499 }
500
501 @Override
502 public Condition startsWith(String attributeName, String value) {
503 return null;
504 }
505
506 @Override
507 public Condition isNull(String attributeName) {
508 return null;
509 }
510
511 @Override
512 public Condition exists(String attributeName) {
513 return null;
514 }
515
516 @Override
517 public Condition isTrue(String attributeName) {
518 return null;
519 }
520
521 @Override
522 public Condition isFalse(String attributeName) {
523 return null;
524 }
525
526 @Override
527 public List<ExchangeSession.Folder> getSubFolders(String folderName, Condition condition, boolean recursive) throws IOException {
528
529 ArrayList<ExchangeSession.Folder> folders = new ArrayList<>();
530 try {
531 String folderId = getFolderId(folderName);
532 HttpGet httpGet = new HttpGet(new URIBuilder(baseUrl).setPath("/beta/me/mailFolders/" + folderId + "/childFolders")
533 .addParameter("$expand", buildExpand(FOLDER_PROPERTIES))
534 .build());
535 JSONObject jsonResponse = executeRequest(httpGet);
536 JSONArray jsonValues = jsonResponse.optJSONArray("value");
537 for (int i = 0; i < jsonValues.length(); i++) {
538 Folder folder = buildFolder(jsonValues.getJSONObject(i));
539 folder.folderPath = folderName + '/' + EwsExchangeSession.encodeFolderName(folder.displayName);
540 folders.add(folder);
541 }
542 } catch (JSONException | URISyntaxException e) {
543 throw new IOException(e);
544 }
545 return folders;
546 }
547
548 @Override
549 public void sendMessage(MimeMessage mimeMessage) throws IOException, MessagingException {
550
551 }
552
553 @Override
554 protected Folder internalGetFolder(String folderPath) throws IOException {
555 String folderId = getFolderId(folderPath);
556
557 JSONObject jsonResponse = null;
558 try {
559 URIBuilder uriBuilder = new URIBuilder(baseUrl)
560 .setPath("/beta/me/mailFolders/" + folderId)
561 .addParameter("$expand", buildExpand(FOLDER_PROPERTIES));
562 HttpGet httpGet = new HttpGet(uriBuilder.build());
563 httpGet.setHeader("Authorization", "Bearer " + token.getAccessToken());
564 try (
565 CloseableHttpResponse response = httpClient.execute(httpGet);
566 ) {
567 jsonResponse = new JsonResponseHandler().handleResponse(response);
568 }
569 } catch (URISyntaxException e) {
570 throw new IOException(e);
571 }
572
573 GraphExchangeSessionDraft.Folder folder;
574 if (jsonResponse != null) {
575 folder = buildFolder(jsonResponse);
576 folder.folderPath = folderPath;
577 } else {
578 throw new HttpNotFoundException("Folder " + folderPath + " not found");
579 }
580 return folder;
581 }
582
583 private String internalGetFolderId(String folderName) throws IOException {
584 String folderId;
585 try {
586 URIBuilder uriBuilder = new URIBuilder(baseUrl)
587 .setPath("/beta/me/mailFolders/" + folderName)
588 .addParameter("$select", "id");
589 HttpGet httpGet = new HttpGet(uriBuilder.build());
590 httpGet.setHeader("Authorization", "Bearer " + token.getAccessToken());
591 try (
592 CloseableHttpResponse response = httpClient.execute(httpGet);
593 ) {
594 JSONObject jsonResponse = new JsonResponseHandler().handleResponse(response);
595 folderId = jsonResponse.getString("id");
596 }
597 } catch (URISyntaxException | JSONException e) {
598 throw new IOException(e);
599 }
600 return folderId;
601 }
602
603 protected String getFolderIdIfExists(String folderPath) throws IOException {
604
605
606 String parentFolderId = internalGetFolderId("msgfolderroot");
607 if ("msgfolderroot".equals(folderPath)) {
608 return parentFolderId;
609 }
610 String folderId = null;
611 String[] pathElements = folderPath.split("/");
612 for (String pathElement : pathElements) {
613 try {
614 String displayName = EwsExchangeSession.decodeFolderName(pathElement);
615 URIBuilder uriBuilder = new URIBuilder(baseUrl)
616 .setPath("/beta/me/mailFolders/" + parentFolderId + "/childFolders")
617 .addParameter("$select", "id, displayName")
618
619 .addParameter("$filter", "displayName eq '" + displayName + "'");
620 HttpGet httpGet = new HttpGet(uriBuilder.build());
621 httpGet.setHeader("Authorization", "Bearer " + token.getAccessToken());
622 try (
623 CloseableHttpResponse response = httpClient.execute(httpGet);
624 ) {
625 JSONObject jsonResponse = new JsonResponseHandler().handleResponse(response);
626 JSONArray jsonFolders = jsonResponse.getJSONArray("value");
627 String currentFolderId = null;
628 for (int i = 0; i < jsonFolders.length(); i++) {
629 JSONObject jsonFolder = jsonFolders.getJSONObject(i);
630 if (displayName.equals(jsonFolder.optString("displayName"))) {
631
632 currentFolderId = jsonFolder.getString("id");
633 }
634 }
635 parentFolderId = currentFolderId;
636 if (currentFolderId == null) {
637
638 break;
639 }
640 }
641 } catch (URISyntaxException | JSONException e) {
642 throw new IOException(e);
643 }
644 }
645 return parentFolderId;
646 }
647
648 protected String getFolderId(String folderPath) throws IOException {
649 String folderId = getFolderIdIfExists(folderPath);
650 if (folderId == null) {
651 throw new HttpNotFoundException("Folder '" + folderPath + "' not found");
652 }
653 return folderId;
654 }
655
656 private Folder buildFolder(JSONObject jsonResponse) throws IOException {
657 Folder folder = new Folder();
658 try {
659 folder.displayName = jsonResponse.optString("displayName");
660 folder.count = jsonResponse.getInt("totalItemCount");
661 folder.unreadCount = jsonResponse.getInt("unreadItemCount");
662 folder.hasChildren = jsonResponse.getInt("childFolderCount") > 0;
663
664 folder.id = jsonResponse.getString("id");
665
666
667 JSONArray singleValueExtendedProperties = jsonResponse.optJSONArray("singleValueExtendedProperties");
668 if (singleValueExtendedProperties != null) {
669 for (int i = 0; i < singleValueExtendedProperties.length(); i++) {
670 JSONObject singleValueProperty = singleValueExtendedProperties.getJSONObject(i);
671 String singleValueId = singleValueProperty.getString("id");
672 String singleValue = singleValueProperty.getString("value");
673 if (Field.get("lastmodified").getGraphId().equals(singleValueId)) {
674
675 folder.lastModified = singleValue;
676 } else if (Field.get("folderclass").getGraphId().equals(singleValueId)) {
677 folder.folderClass = singleValue;
678 } else if (Field.get("uidNext").getGraphId().equals(singleValueId)) {
679 folder.uidNext = Long.parseLong(singleValue);
680 } else if (Field.get("ctag").getGraphId().equals(singleValueId)) {
681 folder.ctag = singleValue;
682 } else {
683 LOGGER.warn("Unknown property " + singleValueId);
684 }
685
686 }
687 }
688 } catch (JSONException e) {
689 throw new IOException(e);
690 }
691 return folder;
692 }
693
694
695
696
697 @Override
698 public int createFolder(String folderPath, String folderClass, Map<String, String> properties) throws IOException {
699
700 if ("IPF.Appointment".equals(folderClass) && folderPath.startsWith("calendars")) {
701
702 try {
703 HttpPost httpPost = new HttpPost(new URIBuilder(baseUrl).setPath("/beta/me/calendars").build());
704 httpPost.setHeader("Content-Type", "application/json");
705 JSONObject jsonObject = new JSONObject();
706 jsonObject.put("name", folderPath);
707
708 httpPost.setEntity(new ByteArrayEntity(jsonObject.toString().getBytes(StandardCharsets.UTF_8)));
709 executeRequest(httpPost);
710
711 } catch (URISyntaxException | JSONException e) {
712 throw new IOException(e);
713 }
714 } else {
715 String parentFolderId;
716 String folderName;
717 if (folderPath.contains("/")) {
718 String parentFolderPath = folderPath.substring(0, folderPath.lastIndexOf('/'));
719 parentFolderId = getFolderId(parentFolderPath);
720 folderName = EwsExchangeSession.decodeFolderName(folderPath.substring(folderPath.lastIndexOf('/') + 1));
721 } else {
722 parentFolderId = getFolderId("msgfolderroot");
723 folderName = EwsExchangeSession.decodeFolderName(folderPath);
724 }
725
726 try {
727 HttpPost httpPost = new HttpPost(new URIBuilder(baseUrl).setPath("/beta/me/mailFolders/" + parentFolderId + "/childFolders").build());
728 httpPost.setHeader("Content-Type", "application/json");
729 JSONObject jsonObject = new JSONObject();
730 jsonObject.put("displayName", folderName);
731 if (folderClass != null) {
732 JSONArray singleValueExtendedProperties = new JSONArray();
733 singleValueExtendedProperties.put(new JSONObject().put("id", Field.get("folderclass").getGraphId()).put("value", folderClass));
734 jsonObject.put("singleValueExtendedProperties", singleValueExtendedProperties);
735 }
736
737 httpPost.setEntity(new ByteArrayEntity(jsonObject.toString().getBytes(StandardCharsets.UTF_8)));
738 executeRequest(httpPost);
739
740 } catch (URISyntaxException | JSONException e) {
741 throw new IOException(e);
742 }
743 }
744
745 return HttpStatus.SC_CREATED;
746 }
747
748 @Override
749 public int updateFolder(String folderName, Map<String, String> properties) throws IOException {
750 return 0;
751 }
752
753 @Override
754 public void deleteFolder(String folderPath) throws IOException {
755 String folderId = getFolderId(folderPath);
756
757 try {
758 HttpDelete httpDelete = new HttpDelete(new URIBuilder(baseUrl).setPath("/beta/me/mailFolders/" + folderId).build());
759 executeRequest(httpDelete);
760
761 } catch (URISyntaxException e) {
762 throw new IOException(e);
763 }
764 }
765
766 @Override
767 public void copyMessage(Message message, String targetFolder) throws IOException {
768
769 }
770
771 @Override
772 public void moveMessage(Message message, String targetFolder) throws IOException {
773
774 }
775
776 @Override
777 public void moveFolder(String folderName, String targetName) throws IOException {
778
779 }
780
781 @Override
782 public void moveItem(String sourcePath, String targetPath) throws IOException {
783
784 }
785
786 @Override
787 protected void moveToTrash(Message message) throws IOException {
788
789 }
790
791 @Override
792 protected Set<String> getItemProperties() {
793 return null;
794 }
795
796 @Override
797 public List<Contact> searchContacts(String folderPath, Set<String> attributes, Condition condition, int maxCount) throws IOException {
798 return null;
799 }
800
801 @Override
802 public List<Event> getEventMessages(String folderPath) throws IOException {
803 return null;
804 }
805
806 @Override
807 protected Condition getCalendarItemCondition(Condition dateCondition) {
808 return null;
809 }
810
811 @Override
812 public List<Event> searchEvents(String folderPath, Set<String> attributes, Condition condition) throws IOException {
813 return null;
814 }
815
816 @Override
817 public Item getItem(String folderPath, String itemName) throws IOException {
818 return null;
819 }
820
821 @Override
822 public ContactPhoto getContactPhoto(Contact contact) throws IOException {
823 return null;
824 }
825
826 @Override
827 public void deleteItem(String folderPath, String itemName) throws IOException {
828
829 }
830
831 @Override
832 public void processItem(String folderPath, String itemName) throws IOException {
833
834 }
835
836 @Override
837 public int sendEvent(String icsBody) throws IOException {
838 return 0;
839 }
840
841 @Override
842 protected Contact buildContact(String folderPath, String itemName, Map<String, String> properties, String etag, String noneMatch) throws IOException {
843 return null;
844 }
845
846 @Override
847 protected ItemResult internalCreateOrUpdateEvent(String folderPath, String itemName, String contentClass, String icsBody, String etag, String noneMatch) throws IOException {
848 return null;
849 }
850
851 @Override
852 public boolean isSharedFolder(String folderPath) {
853 return false;
854 }
855
856 @Override
857 public boolean isMainCalendar(String folderPath) throws IOException {
858 return false;
859 }
860
861 @Override
862 public Map<String, Contact> galFind(Condition condition, Set<String> returningAttributes, int sizeLimit) throws IOException {
863 return null;
864 }
865
866 @Override
867 protected String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException {
868 return null;
869 }
870
871
872 @Override
873 protected void loadVtimezone() {
874 try {
875 String timezoneId = null;
876
877 JSONObject mailboxSettings = getMailboxSettings();
878 if (mailboxSettings != null) {
879 timezoneId = mailboxSettings.optString("timeZone", null);
880 }
881
882 if (timezoneId == null) {
883 timezoneId = Settings.getProperty("davmail.timezoneId");
884 }
885
886 if (timezoneId == null) {
887 LOGGER.warn("Unable to get user timezone, using GMT Standard Time. Set davmail.timezoneId setting to override this.");
888 timezoneId = "GMT Standard Time";
889 }
890
891
892 deleteFolder("davmailtemp");
893 createCalendarFolder("davmailtemp", null);
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920 } catch (IOException e) {
921 LOGGER.warn("Unable to get VTIMEZONE info: " + e, e);
922 } catch (URISyntaxException e) {
923 LOGGER.warn("Unable to get VTIMEZONE info: " + e, e);
924 }
925 }
926
927 public JSONObject getMailboxSettings() throws IOException, URISyntaxException {
928 URIBuilder uriBuilder = new URIBuilder(baseUrl)
929 .setPath("/beta/me/mailboxsettings");
930 return executeRequest(new HttpGet(uriBuilder.build()));
931 }
932
933
934
935
936
937
938
939
940 public JSONArray getSupportedTimeZones(String timeZoneStandard) throws IOException, URISyntaxException, JSONException {
941 if (timeZoneStandard == null) {
942 timeZoneStandard = "Windows";
943 }
944 URIBuilder uriBuilder = new URIBuilder(baseUrl)
945 .setPath("/beta/me/outlook/supportedTimeZones(TimeZoneStandard=microsoft.graph.timeZoneStandard'" + timeZoneStandard + "')");
946 JSONObject response = executeRequest(new HttpGet(uriBuilder.build()));
947 return response.getJSONArray("value");
948 }
949
950 private JSONObject executeRequest(HttpRequestBase request) throws IOException {
951 JSONObject jsonResponse;
952 request.setHeader("Authorization", "Bearer " + token.getAccessToken());
953
954
955 try (
956 CloseableHttpResponse response = httpClient.execute(request);
957 ) {
958 jsonResponse = new JsonResponseHandler().handleResponse(response);
959 }
960 return jsonResponse;
961 }
962
963 }