1 /*
2 * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "evolution-config.h"
19
20 #include <string.h>
21 #include <stdio.h>
22
23 #include <glib.h>
24 #include <glib/gi18n-lib.h>
25 #include <gtk/gtk.h>
26
27 #include <camel/camel.h>
28 #include <e-util/e-util.h>
29 #include <libemail-engine/libemail-engine.h>
30
31 #include "e-mail-notes.h"
32
33 #define E_TYPE_MAIL_NOTES_EDITOR \
34 (e_mail_notes_editor_get_type ())
35 #define E_MAIL_NOTES_EDITOR(obj) \
36 (G_TYPE_CHECK_INSTANCE_CAST \
37 ((obj), E_TYPE_MAIL_NOTES_EDITOR, EMailNotesEditor))
38 #define E_IS_MAIL_NOTES_EDITOR(obj) \
39 (G_TYPE_CHECK_INSTANCE_TYPE \
40 ((obj), E_TYPE_MAIL_NOTES_EDITOR))
41
42 typedef struct _EMailNotesEditor EMailNotesEditor;
43 typedef struct _EMailNotesEditorClass EMailNotesEditorClass;
44
45 struct _EMailNotesEditor {
46 GtkWindow parent;
47
48 EHTMLEditor *editor; /* not referenced */
49 EAttachmentPaned *attachment_paned; /* not referenced */
50 EFocusTracker *focus_tracker;
51 GtkActionGroup *action_group;
52
53 gboolean had_message;
54 CamelMimeMessage *message;
55 CamelFolder *folder;
56 gchar *uid;
57 };
58
59 struct _EMailNotesEditorClass {
60 GtkWindowClass parent_class;
61 };
62
63 GType e_mail_notes_editor_get_type (void);
64
G_DEFINE_TYPE(EMailNotesEditor,e_mail_notes_editor,GTK_TYPE_WINDOW)65 G_DEFINE_TYPE (EMailNotesEditor, e_mail_notes_editor, GTK_TYPE_WINDOW)
66
67 static gchar *
68 e_mail_notes_extract_text_content (CamelMimePart *part)
69 {
70 CamelDataWrapper *content;
71 CamelStream *stream;
72 GByteArray *byte_array;
73 gchar *text = NULL;
74
75 g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
76
77 content = camel_medium_get_content (CAMEL_MEDIUM (part));
78 g_return_val_if_fail (content != NULL, NULL);
79
80 stream = camel_stream_mem_new ();
81 camel_data_wrapper_decode_to_stream_sync (content, stream, NULL, NULL);
82 camel_stream_close (stream, NULL, NULL);
83
84 byte_array = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream));
85
86 if (byte_array->data)
87 text = g_strndup ((const gchar *) byte_array->data, byte_array->len);
88
89 g_object_unref (stream);
90
91 return text;
92 }
93
94 static void
e_mail_notes_extract_text_from_multipart_alternative(EContentEditor * cnt_editor,CamelMultipart * in_multipart)95 e_mail_notes_extract_text_from_multipart_alternative (EContentEditor *cnt_editor,
96 CamelMultipart *in_multipart)
97 {
98 guint ii, nparts;
99
100 g_return_if_fail (E_IS_CONTENT_EDITOR (cnt_editor));
101 g_return_if_fail (CAMEL_IS_MULTIPART (in_multipart));
102
103 nparts = camel_multipart_get_number (in_multipart);
104
105 for (ii = 0; ii < nparts; ii++) {
106 CamelMimePart *part;
107 CamelContentType *ct;
108
109 /* Traverse from the end, where the best format available is stored */
110 part = camel_multipart_get_part (in_multipart, nparts - ii - 1);
111 if (!part)
112 continue;
113
114 ct = camel_mime_part_get_content_type (part);
115 if (!ct)
116 continue;
117
118 if (camel_content_type_is (ct, "text", "html")) {
119 gchar *text;
120
121 text = e_mail_notes_extract_text_content (part);
122 if (text) {
123 e_content_editor_set_html_mode (cnt_editor, TRUE);
124 e_content_editor_insert_content (
125 cnt_editor,
126 text,
127 E_CONTENT_EDITOR_INSERT_TEXT_HTML |
128 E_CONTENT_EDITOR_INSERT_REPLACE_ALL);
129 g_free (text);
130 break;
131 }
132 } else if (camel_content_type_is (ct, "text", "plain")) {
133 gchar *text;
134
135 text = e_mail_notes_extract_text_content (part);
136 if (text) {
137 e_content_editor_insert_content (
138 cnt_editor,
139 text,
140 E_CONTENT_EDITOR_INSERT_TEXT_PLAIN |
141 E_CONTENT_EDITOR_INSERT_REPLACE_ALL);
142 g_free (text);
143 }
144 break;
145 }
146 }
147 }
148
149 static void
e_mail_notes_editor_extract_text_from_multipart_related(EMailNotesEditor * notes_editor,CamelMultipart * multipart)150 e_mail_notes_editor_extract_text_from_multipart_related (EMailNotesEditor *notes_editor,
151 CamelMultipart *multipart)
152 {
153 guint ii, nparts;
154
155 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
156 g_return_if_fail (CAMEL_IS_MULTIPART (multipart));
157
158 nparts = camel_multipart_get_number (multipart);
159
160 for (ii = 0; ii < nparts; ii++) {
161 CamelMimePart *part;
162 CamelContentType *ct;
163 CamelDataWrapper *content;
164
165 part = camel_multipart_get_part (multipart, ii);
166 if (!part)
167 continue;
168
169 ct = camel_mime_part_get_content_type (part);
170 if (!ct)
171 continue;
172
173 if (camel_content_type_is (ct, "image", "*")) {
174 e_html_editor_add_cid_part (notes_editor->editor, part);
175 } else if (camel_content_type_is (ct, "multipart", "alternative")) {
176 content = camel_medium_get_content (CAMEL_MEDIUM (part));
177
178 if (CAMEL_IS_MULTIPART (content)) {
179 e_mail_notes_extract_text_from_multipart_alternative (
180 e_html_editor_get_content_editor (notes_editor->editor), CAMEL_MULTIPART (content));
181 }
182 }
183 }
184 }
185
186 static void
e_mail_notes_editor_extract_text_from_part(EMailNotesEditor * notes_editor,CamelMimePart * part)187 e_mail_notes_editor_extract_text_from_part (EMailNotesEditor *notes_editor,
188 CamelMimePart *part)
189 {
190 CamelContentType *ct;
191 CamelDataWrapper *content;
192 EContentEditor *cnt_editor;
193
194 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
195 g_return_if_fail (CAMEL_IS_MIME_PART (part));
196
197 content = camel_medium_get_content (CAMEL_MEDIUM (part));
198 ct = camel_data_wrapper_get_mime_type_field (content);
199
200 g_return_if_fail (content != NULL);
201 g_return_if_fail (ct != NULL);
202
203 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
204
205 if (camel_content_type_is (ct, "multipart", "related")) {
206 g_return_if_fail (CAMEL_IS_MULTIPART (content));
207
208 e_mail_notes_editor_extract_text_from_multipart_related (notes_editor, CAMEL_MULTIPART (content));
209 } else if (camel_content_type_is (ct, "multipart", "alternative")) {
210 if (CAMEL_IS_MULTIPART (content)) {
211 e_mail_notes_extract_text_from_multipart_alternative (cnt_editor, CAMEL_MULTIPART (content));
212 }
213 } else if (camel_content_type_is (ct, "text", "plain")) {
214 gchar *text;
215
216 text = e_mail_notes_extract_text_content (part);
217 if (text) {
218 e_content_editor_insert_content (
219 cnt_editor,
220 text,
221 E_CONTENT_EDITOR_INSERT_TEXT_PLAIN |
222 E_CONTENT_EDITOR_INSERT_REPLACE_ALL);
223 g_free (text);
224 }
225 }
226 }
227
228 static void
e_mail_notes_editor_extract_text_from_message(EMailNotesEditor * notes_editor,CamelMimeMessage * message)229 e_mail_notes_editor_extract_text_from_message (EMailNotesEditor *notes_editor,
230 CamelMimeMessage *message)
231 {
232 CamelContentType *ct;
233 CamelDataWrapper *content;
234 EContentEditor *cnt_editor;
235
236 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
237 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
238
239 content = camel_medium_get_content (CAMEL_MEDIUM (message));
240 ct = camel_data_wrapper_get_mime_type_field (content);
241
242 g_return_if_fail (content != NULL);
243 g_return_if_fail (ct != NULL);
244
245 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
246
247 if (camel_content_type_is (ct, "multipart", "mixed")) {
248 EAttachmentStore *attachment_store;
249 CamelMultipart *multipart;
250 guint ii, nparts;
251
252 g_return_if_fail (CAMEL_IS_MULTIPART (content));
253
254 attachment_store = e_attachment_view_get_store (E_ATTACHMENT_VIEW (notes_editor->attachment_paned));
255 multipart = CAMEL_MULTIPART (content);
256 nparts = camel_multipart_get_number (multipart);
257
258 /* The first part is the note text, the rest are attachments */
259 for (ii = 0; ii < nparts; ii++) {
260 CamelMimePart *part;
261
262 part = camel_multipart_get_part (multipart, ii);
263 if (!part)
264 continue;
265
266 ct = camel_mime_part_get_content_type (part);
267 if (!ct)
268 continue;
269
270 if (ii == 0) {
271 e_mail_notes_editor_extract_text_from_part (notes_editor, part);
272 } else {
273 EAttachment *attachment;
274
275 attachment = e_attachment_new ();
276
277 e_attachment_set_mime_part (attachment, part);
278 e_attachment_store_add_attachment (attachment_store, attachment);
279 e_attachment_load_async (attachment, (GAsyncReadyCallback)
280 e_attachment_load_handle_error, notes_editor);
281
282 g_object_unref (attachment);
283 }
284 }
285 } else {
286 e_mail_notes_editor_extract_text_from_part (notes_editor, CAMEL_MIME_PART (message));
287 }
288
289 e_content_editor_set_changed (cnt_editor, FALSE);
290 }
291
292 static CamelMimeMessage *
e_mail_notes_editor_encode_text_to_message(EMailNotesEditor * notes_editor,EContentEditorContentHash * content_hash)293 e_mail_notes_editor_encode_text_to_message (EMailNotesEditor *notes_editor,
294 EContentEditorContentHash *content_hash)
295 {
296 EContentEditor *cnt_editor;
297 EAttachmentStore *attachment_store;
298 CamelMimeMessage *message = NULL;
299 gchar *message_uid;
300 const gchar *username;
301 CamelInternetAddress *address;
302 gboolean has_text = FALSE, has_attachments;
303
304 g_return_val_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor), NULL);
305 g_return_val_if_fail (notes_editor->editor, NULL);
306 g_return_val_if_fail (content_hash != NULL, NULL);
307
308 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
309 g_return_val_if_fail (E_IS_CONTENT_EDITOR (cnt_editor), NULL);
310
311 message = camel_mime_message_new ();
312 username = g_get_user_name ();
313 if (!username || !*username)
314 username = g_get_real_name ();
315 address = camel_internet_address_new ();
316 camel_internet_address_add (address, NULL, username);
317
318 message_uid = camel_header_msgid_generate (g_get_host_name ());
319
320 camel_mime_message_set_from (message, address);
321 camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
322 camel_mime_message_set_subject (message, _("Message Note"));
323 camel_mime_message_set_message_id (message, message_uid);
324
325 g_object_unref (address);
326 g_free (message_uid);
327
328 attachment_store = e_attachment_view_get_store (E_ATTACHMENT_VIEW (notes_editor->attachment_paned));
329 has_attachments = e_attachment_store_get_num_attachments (attachment_store) > 0;
330
331 if (e_content_editor_get_html_mode (cnt_editor)) {
332 CamelMultipart *multipart_alternative;
333 CamelMultipart *multipart_body;
334 CamelMimePart *part;
335 GSList *inline_images_parts = NULL;
336 const gchar *text;
337
338 multipart_alternative = camel_multipart_new ();
339 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_alternative), "multipart/alternative");
340 camel_multipart_set_boundary (multipart_alternative, NULL);
341
342 text = e_content_editor_util_get_content_data (content_hash, E_CONTENT_EDITOR_GET_TO_SEND_PLAIN);
343
344 if (text && *text) {
345 gchar *tmp = NULL;
346
347 if (!g_str_has_suffix (text, "\r\n") && !g_str_has_suffix (text, "\n")) {
348 tmp = g_strconcat (text, "\r\n", NULL);
349 text = tmp;
350 }
351
352 part = camel_mime_part_new ();
353 camel_mime_part_set_content (part, text, strlen (text), "text/plain");
354 camel_multipart_add_part (multipart_alternative, part);
355
356 g_object_unref (part);
357 g_free (tmp);
358
359 has_text = TRUE;
360 }
361
362 text = e_content_editor_util_get_content_data (content_hash, E_CONTENT_EDITOR_GET_TO_SEND_HTML);
363 inline_images_parts = e_content_editor_util_get_content_data (content_hash, E_CONTENT_EDITOR_GET_INLINE_IMAGES);
364
365 if (has_attachments && !has_text && (!text || !*text)) {
366 /* Text is required, thus if there are attachments,
367 but no text, then store at least a space. */
368 text = "\r\n";
369 }
370
371 if (text && *text) {
372 gchar *tmp = NULL;
373
374 if (!g_str_has_suffix (text, "\r\n") && !g_str_has_suffix (text, "\n")) {
375 tmp = g_strconcat (text, "\r\n", NULL);
376 text = tmp;
377 }
378
379 part = camel_mime_part_new ();
380 camel_mime_part_set_content (part, text, strlen (text), "text/html");
381 camel_multipart_add_part (multipart_alternative, part);
382
383 g_object_unref (part);
384 g_free (tmp);
385
386 has_text = TRUE;
387 } else {
388 inline_images_parts = NULL;
389 }
390
391 if (inline_images_parts) {
392 GSList *link;
393
394 multipart_body = camel_multipart_new ();
395 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/related");
396 camel_multipart_set_boundary (multipart_body, NULL);
397
398 part = camel_mime_part_new ();
399 camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (multipart_alternative));
400 camel_multipart_add_part (multipart_body, part);
401 g_object_unref (part);
402
403 for (link = inline_images_parts; link; link = g_slist_next (link)) {
404 CamelMimePart *part = link->data;
405
406 if (!part)
407 continue;
408
409 camel_multipart_add_part (multipart_body, part);
410 }
411 } else {
412 multipart_body = multipart_alternative;
413 multipart_alternative = NULL;
414 }
415
416 if (has_attachments) {
417 CamelMultipart *multipart;
418
419 multipart = camel_multipart_new ();
420 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/mixed");
421 camel_multipart_set_boundary (multipart, NULL);
422
423 part = camel_mime_part_new ();
424 camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (multipart_body));
425 camel_multipart_add_part (multipart, part);
426 g_object_unref (part);
427
428 e_attachment_store_add_to_multipart (attachment_store, multipart, "UTF-8");
429
430 g_object_unref (multipart_body);
431 multipart_body = multipart;
432 }
433
434 camel_medium_set_content (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (multipart_body));
435
436 g_clear_object (&multipart_alternative);
437 g_clear_object (&multipart_body);
438 } else {
439 const gchar *text;
440
441 text = e_content_editor_util_get_content_data (content_hash, E_CONTENT_EDITOR_GET_TO_SEND_PLAIN);
442
443 if (has_attachments && !has_text && (!text || !*text)) {
444 /* Text is required, thus if there are attachments,
445 but no text, then store at least a space. */
446 text = "\r\n";
447 }
448
449 if (text && *text) {
450 gchar *tmp = NULL;
451
452 if (!g_str_has_suffix (text, "\r\n") && !g_str_has_suffix (text, "\n")) {
453 tmp = g_strconcat (text, "\r\n", NULL);
454 text = tmp;
455 }
456
457 if (has_attachments) {
458 CamelMultipart *multipart;
459 CamelMimePart *part;
460
461 multipart = camel_multipart_new ();
462 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/mixed");
463 camel_multipart_set_boundary (multipart, NULL);
464
465 part = camel_mime_part_new ();
466 camel_mime_part_set_content (part, text, strlen (text), "text/plain");
467 camel_multipart_add_part (multipart, part);
468 g_object_unref (part);
469
470 e_attachment_store_add_to_multipart (attachment_store, multipart, "UTF-8");
471
472 camel_medium_set_content (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (multipart));
473
474 g_object_unref (multipart);
475 } else {
476 camel_mime_part_set_content (CAMEL_MIME_PART (message), text, strlen (text), "text/plain");
477 }
478
479 has_text = TRUE;
480
481 g_free (tmp);
482 }
483 }
484
485 if (has_text) {
486 camel_mime_message_encode_8bit_parts (message);
487 } else {
488 g_clear_object (&message);
489 }
490
491 return message;
492 }
493
494 static void
e_mail_notes_retrieve_message_thread(EAlertSinkThreadJobData * job_data,gpointer user_data,GCancellable * cancellable,GError ** error)495 e_mail_notes_retrieve_message_thread (EAlertSinkThreadJobData *job_data,
496 gpointer user_data,
497 GCancellable *cancellable,
498 GError **error)
499 {
500 EMailNotesEditor *notes_editor = user_data;
501 CamelMimeMessage *message;
502
503 if (g_cancellable_set_error_if_cancelled (cancellable, error))
504 return;
505
506 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
507
508 message = camel_folder_get_message_sync (notes_editor->folder, notes_editor->uid, cancellable, error);
509 if (!g_cancellable_is_cancelled (cancellable))
510 notes_editor->message = message;
511 else
512 g_clear_object (&message);
513 }
514
515 static void
e_mail_notes_retrieve_message_done(gpointer ptr)516 e_mail_notes_retrieve_message_done (gpointer ptr)
517 {
518 EMailNotesEditor *notes_editor = ptr;
519
520 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
521
522 if (notes_editor->message) {
523 EActivityBar *activity_bar;
524 CamelDataWrapper *content;
525 CamelContentType *ct;
526
527 content = camel_medium_get_content (CAMEL_MEDIUM (notes_editor->message));
528 ct = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (notes_editor->message));
529
530 if (ct && camel_content_type_is (ct, "multipart", "mixed") && CAMEL_IS_MULTIPART (content)) {
531 CamelMultipart *multipart = CAMEL_MULTIPART (content);
532 guint nparts, ii;
533
534 nparts = camel_multipart_get_number (multipart);
535 for (ii = 0; ii < nparts; ii++) {
536 CamelMimePart *part;
537 CamelContentType *ct;
538 const gchar *x_evolution_note;
539
540 part = camel_multipart_get_part (multipart, ii);
541 if (!part)
542 continue;
543
544 ct = camel_mime_part_get_content_type (part);
545 if (!ct || !camel_content_type_is (ct, "message", "rfc822"))
546 continue;
547
548 x_evolution_note = camel_medium_get_header (CAMEL_MEDIUM (part), E_MAIL_NOTES_HEADER);
549 if (x_evolution_note) {
550 content = camel_medium_get_content (CAMEL_MEDIUM (part));
551 if (CAMEL_IS_MIME_MESSAGE (content)) {
552 e_mail_notes_editor_extract_text_from_message (notes_editor,
553 CAMEL_MIME_MESSAGE (content));
554 }
555 break;
556 }
557 }
558 }
559
560 g_clear_object (¬es_editor->message);
561 notes_editor->had_message = TRUE;
562
563 activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
564 e_activity_bar_set_activity (activity_bar, NULL);
565 } else {
566 GtkAction *action;
567
568 action = gtk_action_group_get_action (notes_editor->action_group, "save-and-close");
569 gtk_action_set_sensitive (action, FALSE);
570 }
571
572 g_object_unref (notes_editor);
573 }
574
575 static gboolean
mail_notes_editor_delete_event_cb(EMailNotesEditor * notes_editor,GdkEvent * event)576 mail_notes_editor_delete_event_cb (EMailNotesEditor *notes_editor,
577 GdkEvent *event)
578 {
579 GtkActionGroup *action_group;
580 GtkAction *action;
581
582 action_group = notes_editor->action_group;
583 action = gtk_action_group_get_action (action_group, "close");
584 gtk_action_activate (action);
585
586 return TRUE;
587 }
588
589 static void
notes_editor_activity_notify_cb(EActivityBar * activity_bar,GParamSpec * param,EMailNotesEditor * notes_editor)590 notes_editor_activity_notify_cb (EActivityBar *activity_bar,
591 GParamSpec *param,
592 EMailNotesEditor *notes_editor)
593 {
594 EContentEditor *cnt_editor;
595 GtkAction *action;
596 gboolean can_edit;
597
598 g_return_if_fail (E_IS_ACTIVITY_BAR (activity_bar));
599 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
600
601 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
602 can_edit = notes_editor->had_message && !e_activity_bar_get_activity (activity_bar);
603
604 g_object_set (cnt_editor, "editable", can_edit, NULL);
605
606 action = gtk_action_group_get_action (notes_editor->action_group, "save-and-close");
607 gtk_action_set_sensitive (action, can_edit);
608 }
609
610 static gboolean
e_mail_notes_replace_message_in_folder_sync(CamelFolder * folder,const gchar * uid,CamelMimeMessage * message,gboolean has_note,GCancellable * cancellable,GError ** error)611 e_mail_notes_replace_message_in_folder_sync (CamelFolder *folder,
612 const gchar *uid,
613 CamelMimeMessage *message,
614 gboolean has_note,
615 GCancellable *cancellable,
616 GError **error)
617 {
618 CamelMessageInfo *mi;
619 gboolean success = FALSE;
620
621 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
622 g_return_val_if_fail (uid != NULL, FALSE);
623 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
624
625 mi = camel_folder_get_message_info (folder, uid);
626 if (mi) {
627 CamelMessageInfo *clone;
628 gchar *appended_uid = NULL;
629
630 clone = camel_message_info_clone (mi, NULL);
631 camel_message_info_set_abort_notifications (clone, TRUE);
632
633 camel_message_info_set_user_flag (clone, E_MAIL_NOTES_USER_FLAG, has_note);
634
635 success = camel_folder_append_message_sync (folder, message, clone,
636 &appended_uid, cancellable, error);
637
638 if (success)
639 camel_message_info_set_flags (mi, CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
640
641 g_clear_object (&clone);
642 g_clear_object (&mi);
643 g_free (appended_uid);
644 } else {
645 g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot find message in its folder summary"));
646 }
647
648 return success;
649 }
650
651 static gboolean
e_mail_notes_replace_note(CamelMimeMessage * message,CamelMimeMessage * note)652 e_mail_notes_replace_note (CamelMimeMessage *message,
653 CamelMimeMessage *note)
654 {
655 CamelMultipart *multipart;
656 CamelMimePart *part;
657 CamelDataWrapper *orig_content;
658 CamelContentType *ct;
659
660 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
661 if (note)
662 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (note), FALSE);
663
664 orig_content = camel_medium_get_content (CAMEL_MEDIUM (message));
665 ct = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
666 if (ct && camel_content_type_is (ct, "multipart", "mixed") && CAMEL_IS_MULTIPART (orig_content)) {
667 CamelMimePart *content_adept = NULL;
668 CamelMultipart *multipart = CAMEL_MULTIPART (orig_content);
669 guint nparts, ii;
670
671 nparts = camel_multipart_get_number (multipart);
672 for (ii = 0; ii < nparts; ii++) {
673 CamelMimePart *part;
674 CamelContentType *ct;
675 const gchar *x_evolution_note;
676
677 part = camel_multipart_get_part (multipart, ii);
678 if (!part)
679 continue;
680
681 ct = camel_mime_part_get_content_type (part);
682 if (!ct || !camel_content_type_is (ct, "message", "rfc822")) {
683 if (content_adept) {
684 content_adept = NULL;
685 break;
686 }
687 content_adept = part;
688 continue;
689 }
690
691 x_evolution_note = camel_medium_get_header (CAMEL_MEDIUM (part), E_MAIL_NOTES_HEADER);
692 if (x_evolution_note)
693 break;
694
695 if (content_adept) {
696 content_adept = NULL;
697 break;
698 }
699 content_adept = part;
700 }
701
702 if (content_adept)
703 orig_content = camel_medium_get_content (CAMEL_MEDIUM (content_adept));
704 }
705
706 if (!orig_content)
707 return FALSE;
708
709 g_object_ref (orig_content);
710
711 camel_medium_remove_header (CAMEL_MEDIUM (message), "Content-Transfer-Encoding");
712
713 if (note) {
714 multipart = camel_multipart_new ();
715 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/mixed");
716 camel_multipart_set_boundary (multipart, NULL);
717
718 part = camel_mime_part_new ();
719 camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (orig_content));
720 camel_multipart_add_part (multipart, part);
721 g_object_unref (part);
722
723 part = camel_mime_part_new ();
724 /* Value doesn't matter, it's checked for an existence only */
725 camel_medium_add_header (CAMEL_MEDIUM (part), E_MAIL_NOTES_HEADER, "True");
726 camel_mime_part_set_disposition (CAMEL_MIME_PART (part), "inline");
727 camel_mime_part_set_description (CAMEL_MIME_PART (part), _("Message Note"));
728 camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (note));
729
730 camel_mime_part_set_content_type (part, "message/rfc822");
731
732 camel_multipart_add_part (multipart, part);
733 g_object_unref (part);
734
735 camel_medium_set_content (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (multipart));
736 } else {
737 camel_medium_set_content (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (orig_content));
738 }
739
740 g_clear_object (&orig_content);
741
742 return TRUE;
743 }
744
745 static void
action_close_cb(GtkAction * action,EMailNotesEditor * notes_editor)746 action_close_cb (GtkAction *action,
747 EMailNotesEditor *notes_editor)
748 {
749 EContentEditor *cnt_editor;
750 gboolean something_changed = FALSE;
751
752 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
753
754 something_changed = e_content_editor_get_changed (cnt_editor);
755
756 if (something_changed) {
757 gint response;
758
759 response = e_alert_run_dialog_for_args (
760 GTK_WINDOW (notes_editor),
761 "mail:ask-mail-note-changed", NULL);
762 if (response == GTK_RESPONSE_YES) {
763 GtkActionGroup *action_group;
764
765 action_group = notes_editor->action_group;
766 action = gtk_action_group_get_action (
767 action_group, "save-and-close");
768 gtk_action_activate (action);
769 return;
770 } else if (response == GTK_RESPONSE_CANCEL)
771 return;
772 }
773
774 gtk_widget_destroy (GTK_WIDGET (notes_editor));
775 }
776
777 typedef struct {
778 EMailNotesEditor *notes_editor;
779 CamelMimeMessage *inner_message;
780 EActivity *activity;
781 GError *error;
782 gboolean success;
783 } SaveAndCloseData;
784
785 static SaveAndCloseData *
save_and_close_data_new(EMailNotesEditor * notes_editor)786 save_and_close_data_new (EMailNotesEditor *notes_editor)
787 {
788 SaveAndCloseData *scd;
789
790 scd = g_slice_new0 (SaveAndCloseData);
791 scd->notes_editor = g_object_ref (notes_editor);
792
793 return scd;
794 }
795
796 static void
save_and_close_data_free(gpointer ptr)797 save_and_close_data_free (gpointer ptr)
798 {
799 SaveAndCloseData *scd = ptr;
800
801 if (scd) {
802 if (scd->success)
803 gtk_widget_destroy (GTK_WIDGET (scd->notes_editor));
804 else
805 g_clear_object (&scd->notes_editor);
806 g_clear_object (&scd->inner_message);
807 g_clear_object (&scd->activity);
808 g_clear_error (&scd->error);
809 g_slice_free (SaveAndCloseData, scd);
810 }
811 }
812
813 static void
e_mail_notes_store_changes_thread(EAlertSinkThreadJobData * job_data,gpointer user_data,GCancellable * cancellable,GError ** error)814 e_mail_notes_store_changes_thread (EAlertSinkThreadJobData *job_data,
815 gpointer user_data,
816 GCancellable *cancellable,
817 GError **error)
818 {
819 CamelMimeMessage *message;
820 SaveAndCloseData *scd = user_data;
821
822 g_return_if_fail (scd != NULL);
823
824 if (scd->error) {
825 g_propagate_error (error, scd->error);
826 scd->error = NULL;
827 return;
828 }
829
830 if (g_cancellable_set_error_if_cancelled (cancellable, error))
831 return;
832
833 if (!scd->inner_message) {
834 scd->success = e_mail_notes_remove_sync (scd->notes_editor->folder,
835 scd->notes_editor->uid, cancellable, error);
836 return;
837 }
838
839 message = camel_folder_get_message_sync (scd->notes_editor->folder, scd->notes_editor->uid, cancellable, error);
840 if (!message)
841 return;
842
843 e_mail_notes_replace_note (message, scd->inner_message);
844
845 scd->success = e_mail_notes_replace_message_in_folder_sync (scd->notes_editor->folder,
846 scd->notes_editor->uid, message, TRUE, cancellable, error);
847
848 g_clear_object (&message);
849 }
850
851 static void
mail_notes_get_content_ready_cb(GObject * source_object,GAsyncResult * result,gpointer user_data)852 mail_notes_get_content_ready_cb (GObject *source_object,
853 GAsyncResult *result,
854 gpointer user_data)
855 {
856 SaveAndCloseData *scd = user_data;
857 EContentEditorContentHash *content_hash;
858 EActivityBar *activity_bar;
859 EActivity *activity;
860 gchar *full_display_name;
861 GError *error = NULL;
862
863 g_return_if_fail (scd != NULL);
864 g_return_if_fail (E_IS_CONTENT_EDITOR (source_object));
865
866 content_hash = e_content_editor_get_content_finish (E_CONTENT_EDITOR (source_object), result, &error);
867
868 if (content_hash) {
869 scd->inner_message = e_mail_notes_editor_encode_text_to_message (scd->notes_editor, content_hash);
870
871 if (!scd->inner_message)
872 scd->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to convert text to message"));
873 } else {
874 scd->error = error;
875
876 if (!scd->error)
877 scd->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, _("Unknown error"));
878 }
879
880 g_clear_object (&scd->activity);
881
882 full_display_name = e_mail_folder_to_full_display_name (scd->notes_editor->folder, NULL);
883
884 activity_bar = e_html_editor_get_activity_bar (scd->notes_editor->editor);
885 activity = e_alert_sink_submit_thread_job (E_ALERT_SINK (scd->notes_editor->editor),
886 _("Storing changes…"), "mail:failed-store-note",
887 full_display_name ? full_display_name : camel_folder_get_display_name (scd->notes_editor->folder),
888 e_mail_notes_store_changes_thread,
889 scd, save_and_close_data_free);
890 e_activity_bar_set_activity (activity_bar, activity);
891 g_clear_object (&activity);
892
893 e_content_editor_util_free_content_hash (content_hash);
894 g_free (full_display_name);
895 }
896
897 static void
action_save_and_close_cb(GtkAction * action,EMailNotesEditor * notes_editor)898 action_save_and_close_cb (GtkAction *action,
899 EMailNotesEditor *notes_editor)
900 {
901 SaveAndCloseData *scd;
902 EActivity *activity;
903 EContentEditor *cnt_editor;
904
905 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor));
906
907 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
908 g_return_if_fail (E_IS_CONTENT_EDITOR (cnt_editor));
909
910 activity = e_html_editor_new_activity (notes_editor->editor);
911 e_activity_set_text (activity, _("Storing changes…"));
912
913 scd = save_and_close_data_new (notes_editor);
914 scd->activity = activity; /* takes ownership */
915
916 e_content_editor_get_content (cnt_editor,
917 E_CONTENT_EDITOR_GET_INLINE_IMAGES | E_CONTENT_EDITOR_GET_TO_SEND_HTML | E_CONTENT_EDITOR_GET_TO_SEND_PLAIN,
918 g_get_host_name (), e_activity_get_cancellable (activity),
919 mail_notes_get_content_ready_cb, scd);
920 }
921
922 static void
e_mail_notes_editor_dispose(GObject * object)923 e_mail_notes_editor_dispose (GObject *object)
924 {
925 EMailNotesEditor *notes_editor = E_MAIL_NOTES_EDITOR (object);
926
927 if (notes_editor->editor) {
928 EActivityBar *activity_bar;
929
930 activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
931 g_signal_handlers_disconnect_by_func (activity_bar,
932 G_CALLBACK (notes_editor_activity_notify_cb), notes_editor);
933
934 notes_editor->editor = NULL;
935 }
936
937 g_clear_object (¬es_editor->focus_tracker);
938 g_clear_object (¬es_editor->action_group);
939
940 /* Chain up to parent's method */
941 G_OBJECT_CLASS (e_mail_notes_editor_parent_class)->dispose (object);
942 }
943
944 static void
e_mail_notes_editor_finalize(GObject * object)945 e_mail_notes_editor_finalize (GObject *object)
946 {
947 EMailNotesEditor *notes_editor = E_MAIL_NOTES_EDITOR (object);
948
949 g_clear_object (¬es_editor->focus_tracker);
950 g_clear_object (¬es_editor->folder);
951 g_clear_object (¬es_editor->message);
952 g_free (notes_editor->uid);
953
954 /* Chain up to parent's method */
955 G_OBJECT_CLASS (e_mail_notes_editor_parent_class)->finalize (object);
956 }
957
958 static void
e_mail_notes_editor_class_init(EMailNotesEditorClass * klass)959 e_mail_notes_editor_class_init (EMailNotesEditorClass *klass)
960 {
961 GObjectClass *object_class;
962
963 object_class = G_OBJECT_CLASS (klass);
964 object_class->dispose = e_mail_notes_editor_dispose;
965 object_class->finalize = e_mail_notes_editor_finalize;
966 }
967
968 static void
e_mail_notes_editor_init(EMailNotesEditor * notes_editor)969 e_mail_notes_editor_init (EMailNotesEditor *notes_editor)
970 {
971 }
972
973 static void
set_preformatted_block_format_on_load_finished_cb(EContentEditor * cnt_editor,gpointer user_data)974 set_preformatted_block_format_on_load_finished_cb (EContentEditor *cnt_editor,
975 gpointer user_data)
976 {
977 g_return_if_fail (E_IS_CONTENT_EDITOR (cnt_editor));
978
979 if (!e_content_editor_get_html_mode (cnt_editor)) {
980 e_content_editor_set_block_format (cnt_editor, E_CONTENT_EDITOR_BLOCK_FORMAT_PRE);
981 e_content_editor_set_changed (cnt_editor, FALSE);
982 e_content_editor_clear_undo_redo_history (cnt_editor);
983 }
984
985 g_signal_handlers_disconnect_by_func (cnt_editor,
986 G_CALLBACK (set_preformatted_block_format_on_load_finished_cb), NULL);
987 }
988
989 static EMailNotesEditor *
e_mail_notes_editor_new_with_editor(EHTMLEditor * html_editor,GtkWindow * parent,CamelFolder * folder,const gchar * uid)990 e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor,
991 GtkWindow *parent,
992 CamelFolder *folder,
993 const gchar *uid)
994 {
995 const gchar *ui =
996 "<ui>\n"
997 " <menubar name='main-menu'>\n"
998 " <placeholder name='pre-edit-menu'>\n"
999 " <menu action='file-menu'>\n"
1000 " <menuitem action='save-and-close'/>\n"
1001 " <separator/>"
1002 " <menuitem action='close'/>\n"
1003 " </menu>\n"
1004 " </placeholder>\n"
1005 " </menubar>\n"
1006 " <toolbar name='main-toolbar'>\n"
1007 " <placeholder name='pre-main-toolbar'>\n"
1008 " <toolitem action='save-and-close'/>\n"
1009 " </placeholder>\n"
1010 " </toolbar>\n"
1011 "</ui>";
1012
1013 GtkActionEntry entries[] = {
1014
1015 { "close",
1016 "window-close",
1017 N_("_Close"),
1018 "<Control>w",
1019 N_("Close"),
1020 G_CALLBACK (action_close_cb) },
1021
1022 { "save-and-close",
1023 "document-save",
1024 N_("_Save and Close"),
1025 "<Control>Return",
1026 N_("Save and Close"),
1027 G_CALLBACK (action_save_and_close_cb) },
1028
1029 { "file-menu",
1030 NULL,
1031 N_("_File"),
1032 NULL,
1033 NULL,
1034 NULL }
1035 };
1036
1037 EMailNotesEditor *notes_editor;
1038 EContentEditor *cnt_editor;
1039 EFocusTracker *focus_tracker;
1040 EActivityBar *activity_bar;
1041 GtkUIManager *ui_manager;
1042 GtkWidget *widget, *content;
1043 GtkActionGroup *action_group;
1044 GtkAction *action;
1045 GSettings *settings;
1046 GError *local_error = NULL;
1047
1048 notes_editor = g_object_new (E_TYPE_MAIL_NOTES_EDITOR, NULL);
1049
1050 g_object_set (G_OBJECT (notes_editor),
1051 "transient-for", parent,
1052 "destroy-with-parent", TRUE,
1053 "window-position", GTK_WIN_POS_CENTER_ON_PARENT,
1054 "title", _("Edit Message Note"),
1055 NULL);
1056
1057 gtk_window_set_default_size (GTK_WINDOW (notes_editor), 600, 440);
1058
1059 widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1060 gtk_container_add (GTK_CONTAINER (notes_editor), widget);
1061 gtk_widget_show (widget);
1062
1063 content = widget;
1064
1065 notes_editor->editor = html_editor;
1066 cnt_editor = e_html_editor_get_content_editor (notes_editor->editor);
1067 ui_manager = e_html_editor_get_ui_manager (notes_editor->editor);
1068
1069 /* Because we are loading from a hard-coded string, there is
1070 * no chance of I/O errors. Failure here implies a malformed
1071 * UI definition. Full stop. */
1072 gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &local_error);
1073 if (local_error != NULL)
1074 g_error ("%s: Failed to load built-in UI definition: %s", G_STRFUNC, local_error->message);
1075
1076 action_group = gtk_action_group_new ("notes");
1077 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1078 gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), notes_editor);
1079 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1080 notes_editor->action_group = g_object_ref (action_group);
1081
1082 /* Hide page properties because it is not inherited in the mail. */
1083 action = e_html_editor_get_action (notes_editor->editor, "properties-page");
1084 gtk_action_set_visible (action, FALSE);
1085
1086 action = e_html_editor_get_action (notes_editor->editor, "context-properties-page");
1087 gtk_action_set_visible (action, FALSE);
1088
1089 gtk_ui_manager_ensure_update (ui_manager);
1090
1091 /* Construct the window content. */
1092
1093 widget = e_html_editor_get_managed_widget (notes_editor->editor, "/main-menu");
1094 gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
1095 gtk_widget_show (widget);
1096
1097 widget = e_html_editor_get_managed_widget (notes_editor->editor, "/main-toolbar");
1098 gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
1099 gtk_widget_show (widget);
1100
1101 widget = GTK_WIDGET (notes_editor->editor);
1102 g_object_set (G_OBJECT (widget),
1103 "halign", GTK_ALIGN_FILL,
1104 "hexpand", TRUE,
1105 "valign", GTK_ALIGN_FILL,
1106 "vexpand", TRUE,
1107 NULL);
1108 gtk_box_pack_start (GTK_BOX (content), widget, TRUE, TRUE, 0);
1109 gtk_widget_show (widget);
1110
1111 widget = e_attachment_paned_new ();
1112 gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
1113 notes_editor->attachment_paned = E_ATTACHMENT_PANED (widget);
1114 gtk_widget_show (widget);
1115
1116 e_binding_bind_property (
1117 cnt_editor, "editable",
1118 widget, "sensitive",
1119 G_BINDING_SYNC_CREATE);
1120
1121 /* Configure an EFocusTracker to manage selection actions. */
1122 focus_tracker = e_focus_tracker_new (GTK_WINDOW (notes_editor));
1123
1124 action = e_html_editor_get_action (notes_editor->editor, "cut");
1125 e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
1126
1127 action = e_html_editor_get_action (notes_editor->editor, "copy");
1128 e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
1129
1130 action = e_html_editor_get_action (notes_editor->editor, "paste");
1131 e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
1132
1133 action = e_html_editor_get_action (notes_editor->editor, "select-all");
1134 e_focus_tracker_set_select_all_action (focus_tracker, action);
1135
1136 notes_editor->focus_tracker = focus_tracker;
1137
1138 gtk_widget_grab_focus (GTK_WIDGET (cnt_editor));
1139
1140 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1141 e_content_editor_set_html_mode (cnt_editor, g_settings_get_boolean (settings, "composer-send-html"));
1142 if (g_settings_get_boolean (settings, "composer-plain-text-starts-preformatted")) {
1143 g_signal_connect (cnt_editor, "load-finished",
1144 G_CALLBACK (set_preformatted_block_format_on_load_finished_cb), NULL);
1145 }
1146 g_object_unref (settings);
1147
1148 g_signal_connect (
1149 notes_editor, "delete-event",
1150 G_CALLBACK (mail_notes_editor_delete_event_cb), NULL);
1151
1152 activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
1153
1154 g_signal_connect (activity_bar, "notify::activity",
1155 G_CALLBACK (notes_editor_activity_notify_cb), notes_editor);
1156
1157 notes_editor->folder = g_object_ref (folder);
1158 notes_editor->uid = g_strdup (uid);
1159 notes_editor->had_message = FALSE;
1160
1161 return notes_editor;
1162 }
1163
1164 typedef struct _AsyncData {
1165 GtkWindow *parent;
1166 CamelFolder *folder;
1167 gchar *uid;
1168 } AsyncData;
1169
1170 static void
async_data_free(gpointer ptr)1171 async_data_free (gpointer ptr)
1172 {
1173 AsyncData *ad = ptr;
1174
1175 if (ad) {
1176 g_clear_object (&ad->parent);
1177 g_clear_object (&ad->folder);
1178 g_free (ad->uid);
1179 g_slice_free (AsyncData, ad);
1180 }
1181 }
1182
1183 static void
e_mail_notes_editor_ready_cb(GObject * source_object,GAsyncResult * result,gpointer user_data)1184 e_mail_notes_editor_ready_cb (GObject *source_object,
1185 GAsyncResult *result,
1186 gpointer user_data)
1187 {
1188 AsyncData *ad = user_data;
1189 GtkWidget *html_editor;
1190 GError *error = NULL;
1191
1192 g_return_if_fail (result != NULL);
1193 g_return_if_fail (ad != NULL);
1194
1195 html_editor = e_html_editor_new_finish (result, &error);
1196 if (error) {
1197 g_warning ("%s: Failed to create HTML editor: %s", G_STRFUNC, error->message);
1198 g_clear_error (&error);
1199 } else {
1200 EMailNotesEditor *notes_editor;
1201 EActivityBar *activity_bar;
1202 EActivity *activity;
1203
1204 notes_editor = e_mail_notes_editor_new_with_editor (E_HTML_EDITOR (html_editor),
1205 ad->parent, ad->folder, ad->uid);
1206
1207 activity_bar = e_html_editor_get_activity_bar (notes_editor->editor);
1208 activity = e_alert_sink_submit_thread_job (E_ALERT_SINK (notes_editor->editor),
1209 _("Retrieving message…"), "mail:no-retrieve-message", NULL,
1210 e_mail_notes_retrieve_message_thread,
1211 g_object_ref (notes_editor), e_mail_notes_retrieve_message_done);
1212 e_activity_bar_set_activity (activity_bar, activity);
1213 g_clear_object (&activity);
1214
1215 gtk_widget_show (GTK_WIDGET (notes_editor));
1216 }
1217
1218 async_data_free (ad);
1219 }
1220
1221 void
e_mail_notes_edit(GtkWindow * parent,CamelFolder * folder,const gchar * uid)1222 e_mail_notes_edit (GtkWindow *parent,
1223 CamelFolder *folder,
1224 const gchar *uid)
1225 {
1226 AsyncData *ad;
1227
1228 g_return_if_fail (CAMEL_IS_FOLDER (folder));
1229 g_return_if_fail (uid != NULL);
1230
1231 ad = g_slice_new0 (AsyncData);
1232 ad->parent = parent ? g_object_ref (parent) : NULL;
1233 ad->folder = g_object_ref (folder);
1234 ad->uid = g_strdup (uid);
1235
1236 e_html_editor_new (e_mail_notes_editor_ready_cb, ad);
1237 }
1238
1239 gboolean
e_mail_notes_remove_sync(CamelFolder * folder,const gchar * uid,GCancellable * cancellable,GError ** error)1240 e_mail_notes_remove_sync (CamelFolder *folder,
1241 const gchar *uid,
1242 GCancellable *cancellable,
1243 GError **error)
1244 {
1245 CamelMimeMessage *message;
1246 gboolean success;
1247
1248 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
1249 g_return_val_if_fail (uid != NULL, FALSE);
1250
1251 message = camel_folder_get_message_sync (folder, uid, cancellable, error);
1252 if (!message)
1253 return FALSE;
1254
1255 success = e_mail_notes_replace_note (message, NULL);
1256 if (success) {
1257 success = e_mail_notes_replace_message_in_folder_sync (folder,
1258 uid, message, FALSE, cancellable, error);
1259 } else {
1260 /* There was no note found in the message, thus it was successfully removed */
1261 success = TRUE;
1262 }
1263
1264 g_clear_object (&message);
1265
1266 return success;
1267 }
1268