f5cb15c0251f8b117daa2d8138f9b7c3e6332321
[modest] / src / modest-mail-operation.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-mail-operation.h"
31 /* include other impl specific header files */
32 #include <string.h>
33 #include <stdarg.h>
34 #include <tny-mime-part.h>
35 #include <tny-store-account.h>
36 #include <tny-folder-store.h>
37 #include <tny-folder-store-query.h>
38 #include <glib/gi18n.h>
39 #include "modest-tny-platform-factory.h"
40
41 /* 'private'/'protected' functions */
42 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
43 static void modest_mail_operation_init       (ModestMailOperation *obj);
44 static void modest_mail_operation_finalize   (GObject *obj);
45
46 #define MODEST_ERROR modest_error_quark ()
47
48 typedef enum _ModestMailOperationErrorCode ModestMailOperationErrorCode;
49 enum _ModestMailOperationErrorCode {
50         MODEST_MAIL_OPERATION_ERROR_BAD_ACCOUNT,
51         MODEST_MAIL_OPERATION_ERROR_MISSING_PARAMETER,
52
53         MODEST_MAIL_OPERATION_NUM_ERROR_CODES
54 };
55
56 static void       set_error          (ModestMailOperation *mail_operation, 
57                                       ModestMailOperationErrorCode error_code,
58                                       const gchar *fmt, ...);
59 static void       status_update_cb   (TnyFolder *folder, 
60                                       const gchar *what, 
61                                       gint status, 
62                                       gpointer user_data);
63 static void       folder_refresh_cb  (TnyFolder *folder, 
64                                       gboolean cancelled, 
65                                       gpointer user_data);
66 static void       add_attachments    (TnyMsg *msg, 
67                                       const GList *attachments_list);
68
69
70 static TnyMimePart *         add_body_part    (TnyMsg *msg, 
71                                                const gchar *body,
72                                                const gchar *content_type, 
73                                                gboolean has_attachments);
74
75
76 /* list my signals  */
77 enum {
78         /* MY_SIGNAL_1, */
79         /* MY_SIGNAL_2, */
80         LAST_SIGNAL
81 };
82
83 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
84 struct _ModestMailOperationPrivate {
85         TnyAccount                *account;
86         ModestMailOperationStatus  status;
87         GError                    *error;
88 };
89 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
90                                                    MODEST_TYPE_MAIL_OPERATION, \
91                                                    ModestMailOperationPrivate))
92
93 /* some utility functions */
94 static char * get_content_type(const gchar *s);
95 static gboolean is_ascii(const gchar *s);
96
97 /* globals */
98 static GObjectClass *parent_class = NULL;
99
100 /* uncomment the following if you have defined any signals */
101 /* static guint signals[LAST_SIGNAL] = {0}; */
102
103 GType
104 modest_mail_operation_get_type (void)
105 {
106         static GType my_type = 0;
107         if (!my_type) {
108                 static const GTypeInfo my_info = {
109                         sizeof(ModestMailOperationClass),
110                         NULL,           /* base init */
111                         NULL,           /* base finalize */
112                         (GClassInitFunc) modest_mail_operation_class_init,
113                         NULL,           /* class finalize */
114                         NULL,           /* class data */
115                         sizeof(ModestMailOperation),
116                         1,              /* n_preallocs */
117                         (GInstanceInitFunc) modest_mail_operation_init,
118                         NULL
119                 };
120                 my_type = g_type_register_static (G_TYPE_OBJECT,
121                                                   "ModestMailOperation",
122                                                   &my_info, 0);
123         }
124         return my_type;
125 }
126
127 static void
128 modest_mail_operation_class_init (ModestMailOperationClass *klass)
129 {
130         GObjectClass *gobject_class;
131         gobject_class = (GObjectClass*) klass;
132
133         parent_class            = g_type_class_peek_parent (klass);
134         gobject_class->finalize = modest_mail_operation_finalize;
135
136         g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
137
138         /* signal definitions go here, e.g.: */
139 /*      signals[MY_SIGNAL_1] = */
140 /*              g_signal_new ("my_signal_1",....); */
141 /*      signals[MY_SIGNAL_2] = */
142 /*              g_signal_new ("my_signal_2",....); */
143 /*      etc. */
144 }
145
146 static void
147 modest_mail_operation_init (ModestMailOperation *obj)
148 {
149         ModestMailOperationPrivate *priv;
150
151         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
152
153         priv->account = NULL;
154         priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
155         priv->error = NULL;
156 }
157
158 static void
159 modest_mail_operation_finalize (GObject *obj)
160 {
161         ModestMailOperationPrivate *priv;
162
163         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
164
165         if (priv->account) {
166                 g_object_unref (priv->account);
167                 priv->account = NULL;
168         }
169         if (priv->error) {
170                 g_error_free (priv->error);
171                 priv->error = NULL;
172         }
173
174         G_OBJECT_CLASS(parent_class)->finalize (obj);
175 }
176
177 ModestMailOperation*
178 modest_mail_operation_new (TnyAccount *account)
179 {
180         ModestMailOperation *mail_operation;
181         ModestMailOperationPrivate *priv;
182
183         mail_operation = 
184                 MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
185         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
186
187         priv->account = g_object_ref (account);
188
189         return mail_operation;
190 }
191
192
193 void
194 modest_mail_operation_send_mail (ModestMailOperation *mail_operation,
195                                  TnyMsg* msg)
196 {
197         ModestMailOperationPrivate *priv;
198         TnyTransportAccount *transport_account;
199
200         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
201
202         if (!TNY_IS_TRANSPORT_ACCOUNT (priv->account)) {
203                 set_error (mail_operation,
204                            MODEST_MAIL_OPERATION_ERROR_BAD_ACCOUNT,
205                            _("Error trying to send a mail. Use a transport account"));
206         }
207
208         transport_account = TNY_TRANSPORT_ACCOUNT (priv->account);
209
210         mail_operation = modest_mail_operation_new (NULL);
211         tny_transport_account_send (transport_account, msg);
212 }
213
214 void
215 modest_mail_operation_send_new_mail (ModestMailOperation *mail_operation,
216                                      const gchar *from,
217                                      const gchar *to,
218                                      const gchar *cc,
219                                      const gchar *bcc,
220                                      const gchar *subject,
221                                      const gchar *body,
222                                      const GList *attachments_list)
223 {
224         TnyMsg *new_msg;
225         TnyHeader *header;
226         TnyTransportAccount *transport_account;
227         ModestMailOperationPrivate *priv;
228         gchar *content_type;
229
230         g_return_if_fail (mail_operation);
231
232         /* Check parametters */
233         if (to == NULL) {
234                 set_error (mail_operation,
235                            MODEST_MAIL_OPERATION_ERROR_MISSING_PARAMETER,
236                            _("Error trying to send a mail. You need to set almost one a recipient"));
237                 return;
238         }
239
240         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
241
242         if (!TNY_IS_TRANSPORT_ACCOUNT (priv->account)) {
243                 set_error (mail_operation,
244                            MODEST_MAIL_OPERATION_ERROR_BAD_ACCOUNT,
245                            _("Error trying to send a mail. Use a transport account"));
246                 return;
247         }
248
249         /* Create new msg */
250         transport_account = TNY_TRANSPORT_ACCOUNT (priv->account);
251
252         new_msg          = TNY_MSG (tny_camel_msg_new ());
253         header           = TNY_HEADER (tny_camel_header_new ());
254
255         /* WARNING: set the header before assign values to it */
256         tny_msg_set_header (new_msg, header);
257         tny_header_set_from (TNY_HEADER (header), from);
258         tny_header_set_to (TNY_HEADER (header), to);
259         tny_header_set_cc (TNY_HEADER (header), cc);
260         tny_header_set_bcc (TNY_HEADER (header), bcc);
261         tny_header_set_subject (TNY_HEADER (header), subject);
262
263         content_type = get_content_type(body);
264
265         /* Add the body of the new mail */      
266         add_body_part (new_msg, body, (const gchar *) content_type,
267                        (attachments_list == NULL) ? FALSE : TRUE);
268
269         /* Add attachments */
270         add_attachments (new_msg, attachments_list);
271
272         /* Send mail */ 
273         tny_transport_account_send (transport_account, new_msg);
274
275         /* Clean */
276         g_object_unref (header);
277         g_object_unref (new_msg);
278         g_free(content_type);
279 }
280
281 /**
282  * modest_mail_operation_create_forward_mail:
283  * @msg: a valid #TnyMsg instance
284  * @forward_type: the type of forwarded message
285  * 
286  * creates a forwarded message from an existing one
287  * 
288  * Returns: a new #TnyMsg, or NULL in case of error
289  **/
290 TnyMsg* 
291 modest_mail_operation_create_forward_mail (TnyMsg *msg, 
292                                            const gchar *from,
293                                            ModestMailOperationForwardType forward_type)
294 {
295         TnyMsg *new_msg;
296         TnyHeader *new_header, *header;
297         TnyStream *attachment_stream;
298         gchar *new_subject, *new_body, *content_type, *quoted;
299         TnyMimePart *text_body_part = NULL;
300         GList *attachments_list;
301         TnyList *parts;
302         TnyIterator *iter;
303
304         /* Create new objects */
305         new_msg          = TNY_MSG (tny_camel_msg_new ());
306         new_header       = TNY_HEADER (tny_camel_header_new ());
307
308         header = tny_msg_get_header (msg);
309
310         /* Fill the header */
311         tny_msg_set_header (new_msg, new_header);
312         tny_header_set_from (new_header, from);
313
314         /* Change the subject */
315         new_subject = (gchar *) modest_text_utils_create_forward_subject (tny_header_get_subject(header));
316         tny_header_set_subject (new_header, (const gchar *) new_subject);
317         g_free (new_subject);
318
319         /* Get body from original msg */
320         new_body = (gchar *) modest_tny_msg_actions_find_body (msg, FALSE);
321         if (!new_body) {
322                 g_object_unref (new_msg);
323                 return NULL;
324         }
325         content_type = get_content_type(new_body);
326
327         /* Create the list of attachments */
328         parts = TNY_LIST (tny_simple_list_new());
329         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
330         iter = tny_list_create_iterator (parts);
331         attachments_list = NULL;
332
333         while (!tny_iterator_is_done(iter)) {
334                 TnyMimePart *part;
335
336                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
337                 if (tny_mime_part_is_attachment (part))
338                         attachments_list = g_list_prepend (attachments_list, part);
339
340                 tny_iterator_next (iter);
341         }
342
343         /* Add attachments */
344         add_attachments (new_msg, attachments_list);
345
346         switch (forward_type) {
347                 TnyMimePart *attachment_part;
348                 gchar *inlined_text;
349
350         case MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE:
351                 /* Prepend "Original message" text */
352                 inlined_text = (gchar *) 
353                         modest_text_utils_create_inlined_text (tny_header_get_from (header),
354                                                                tny_header_get_date_sent (header),
355                                                                tny_header_get_to (header),
356                                                                tny_header_get_subject (header),
357                                                                (const gchar*) new_body);
358                 g_free (new_body);
359                 new_body = inlined_text;
360
361                 /* Add body part */
362                 add_body_part (new_msg, new_body, 
363                                (const gchar *) content_type, 
364                                (tny_list_get_length (parts) > 0) ? TRUE : FALSE);
365
366                 break;
367         case MODEST_MAIL_OPERATION_FORWARD_TYPE_ATTACHMENT:
368                 attachment_part = add_body_part (new_msg, new_body, 
369                                                  (const gchar *) content_type, TRUE);
370
371                 /* Set the subject as the name of the attachment */
372                 tny_mime_part_set_filename (attachment_part, tny_header_get_subject (header));
373                 
374                 break;
375         }
376
377         /* Clean */
378         if (attachments_list) g_list_free (attachments_list);
379         g_object_unref (parts);
380         if (text_body_part) g_free (text_body_part);
381         g_free (content_type);
382         g_free (new_body);
383
384         return new_msg;
385 }
386
387 /**
388  * modest_mail_operation_create_reply_mail:
389  * @msg: a valid #TnyMsg instance
390  * @reply_type: the format of the new message
391  * @reply_mode: the mode of reply, to the sender only, to a mail list or to all
392  * 
393  * creates a new message to reply to an existing one
394  * 
395  * Returns: Returns: a new #TnyMsg, or NULL in case of error
396  **/
397 TnyMsg* 
398 modest_mail_operation_create_reply_mail (TnyMsg *msg, 
399                                          const gchar *from,
400                                          ModestMailOperationReplyType reply_type,
401                                          ModestMailOperationReplyMode reply_mode)
402 {
403         TnyMsg *new_msg;
404         TnyHeader *new_header, *header;
405         TnyStream *attachment_stream;
406         gchar *new_subject, *new_body, *content_type, *quoted;
407         TnyList *parts;
408         TnyMimePart *text_body_part;
409
410         /* Create new objects */
411         new_msg          = TNY_MSG (tny_camel_msg_new ());
412         new_header       = TNY_HEADER (tny_camel_header_new ());
413         header           = tny_msg_get_header (msg);
414
415         /* Fill the header */
416         tny_msg_set_header (new_msg, new_header);
417         tny_header_set_to (new_header, tny_header_get_from (header));
418         tny_header_set_from (new_header, from);
419
420         switch (reply_mode) {
421                 gchar *new_cc = NULL;
422                 const gchar *cc = NULL, *bcc = NULL;
423                 GString *tmp = NULL;
424
425         case MODEST_MAIL_OPERATION_REPLY_MODE_SENDER:
426                 /* Do not fill neither cc nor bcc */
427                 break;
428         case MODEST_MAIL_OPERATION_REPLY_MODE_LIST:
429                 /* TODO */
430                 break;
431         case MODEST_MAIL_OPERATION_REPLY_MODE_ALL:
432                 /* Concatenate to, cc and bcc */
433                 cc = tny_header_get_cc (header);
434                 bcc = tny_header_get_bcc (header);
435
436                 tmp = g_string_new (tny_header_get_to (header));
437                 if (cc)  g_string_append_printf (tmp, ",%s",cc);
438                 if (bcc) g_string_append_printf (tmp, ",%s",bcc);
439
440                 /* Remove my own address from the cc list */
441                 new_cc = (gchar *) 
442                         modest_text_utils_remove_mail_from_mail_list ((const gchar *) tmp->str, 
443                                                                       (const gchar *) from);
444                 /* FIXME: remove also the mails from the new To: */
445                 tny_header_set_cc (new_header, new_cc);
446
447                 /* Clean */
448                 g_string_free (tmp, TRUE);
449                 g_free (new_cc);
450                 break;
451         }
452
453         /* Change the subject */
454         new_subject = (gchar*) modest_text_utils_create_reply_subject (tny_header_get_subject(header));
455         tny_header_set_subject (new_header, (const gchar *) new_subject);
456         g_free (new_subject);
457
458         /* Get body from original msg */
459         new_body = (gchar*) modest_tny_msg_actions_find_body (msg, FALSE);
460         if (!new_body) {
461                 g_object_unref (new_msg);
462                 return NULL;
463         }
464         content_type = get_content_type(new_body);
465
466         switch (reply_type) {
467                 gchar *cited_text;
468
469         case MODEST_MAIL_OPERATION_REPLY_TYPE_CITE:
470                 /* Prepend "Original message" text */
471                 cited_text = (gchar *) modest_text_utils_create_cited_text (tny_header_get_from (header),
472                                                                             tny_header_get_date_sent (header),
473                                                                             (const gchar*) new_body);
474                 g_free (new_body);
475                 new_body = cited_text;
476                 break;
477         case MODEST_MAIL_OPERATION_REPLY_TYPE_QUOTE:
478                 /* FIXME: replace 80 with a value from ModestConf */
479                 quoted = (gchar*) modest_text_utils_quote (new_body, 
480                                                            tny_header_get_from (header),
481                                                            tny_header_get_date_sent (header),
482                                                            80);
483                 g_free (new_body);
484                 new_body = quoted;
485                 break;
486         }
487         /* Add body part */
488         text_body_part = add_body_part (new_msg, new_body, 
489                                         (const gchar *) content_type, TRUE);
490
491         /* Clean */
492 /*      g_free (text_body_part); */
493         g_free (content_type);
494         g_free (new_body);
495
496         return new_msg;
497 }
498
499 void
500 modest_mail_operation_update_account (ModestMailOperation *mail_operation)
501 {
502         TnyStoreAccount *storage_account;
503         ModestMailOperationPrivate *priv;
504         TnyList *folders;
505         TnyIterator *ifolders;
506         TnyFolder *cur_folder;
507         TnyFolderStoreQuery *query;
508
509         g_return_if_fail (mail_operation);
510         g_return_if_fail (MODEST_IS_MAIL_OPERATION (mail_operation));
511
512         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
513
514         /* Check that it is a store account */
515         if (!TNY_IS_STORE_ACCOUNT (priv->account)) {
516                 set_error (mail_operation,
517                            MODEST_MAIL_OPERATION_ERROR_BAD_ACCOUNT,
518                            _("Error trying to update an account. Use a store account"));
519                 return;
520         }
521         storage_account = TNY_STORE_ACCOUNT (priv->account);
522
523         /* Get subscribed folders */
524         folders = TNY_LIST (tny_simple_list_new ());
525         query = tny_folder_store_query_new ();
526         tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
527         tny_folder_store_get_folders (TNY_FOLDER_STORE (storage_account),
528                                       folders, query);
529         g_object_unref (query);
530         
531         ifolders = tny_list_create_iterator (folders);
532
533         /* Async refresh folders */     
534         for (tny_iterator_first (ifolders); 
535              !tny_iterator_is_done (ifolders); 
536              tny_iterator_next (ifolders)) {
537                 
538                 cur_folder = TNY_FOLDER (tny_iterator_get_current (ifolders));
539                 tny_folder_refresh_async (cur_folder, folder_refresh_cb,
540                                           status_update_cb, mail_operation);
541         }
542         
543         g_object_unref (ifolders);
544 }
545
546 ModestMailOperationStatus
547 modest_mail_operation_get_status (ModestMailOperation *mail_operation)
548 {
549         ModestMailOperationPrivate *priv;
550
551 /*      g_return_val_if_fail (mail_operation, MODEST_MAIL_OPERATION_STATUS_INVALID); */
552 /*      g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (mail_operation),  */
553 /*                            MODEST_MAIL_OPERATION_STATUS_INVALID); */
554
555         priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_operation);
556         return priv->status;
557 }
558
559 const GError *
560 modest_mail_operation_get_error (ModestMailOperation *mail_operation)
561 {
562         ModestMailOperationPrivate *priv;
563
564 /*      g_return_val_if_fail (mail_operation, NULL); */
565 /*      g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (mail_operation), NULL); */
566
567         priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_operation);
568         return priv->error;
569 }
570
571 void 
572 modest_mail_operation_cancel (ModestMailOperation *mail_operation)
573 {
574         /* TODO */
575 }
576
577 static gboolean
578 is_ascii(const gchar *s)
579 {
580         while (s[0]) {
581                 if (s[0] & 128 || s[0] < 32)
582                         return FALSE;
583                 s++;
584         }
585         return TRUE;
586 }
587
588 static char *
589 get_content_type(const gchar *s)
590 {
591         GString *type;
592         
593         type = g_string_new("text/plain");
594         if (!is_ascii(s)) {
595                 if (g_utf8_validate(s, -1, NULL)) {
596                         g_string_append(type, "; charset=\"utf-8\"");
597                 } else {
598                         /* it should be impossible to reach this, but better safe than sorry */
599                         g_warning("invalid utf8 in message");
600                         g_string_append(type, "; charset=\"latin1\"");
601                 }
602         }
603         return g_string_free(type, FALSE);
604 }
605
606 static GQuark 
607 modest_error_quark (void)
608 {
609   static GQuark err_q = 0;
610
611   if (err_q == 0)
612     err_q = g_quark_from_static_string ("modest-error-quark");
613
614   return err_q;
615 }
616
617
618 static void 
619 set_error (ModestMailOperation *mail_operation, 
620            ModestMailOperationErrorCode error_code,
621            const gchar *fmt, ...)
622 {
623         ModestMailOperationPrivate *priv;
624         GError* error;
625         va_list args;
626         gchar* orig;
627
628         priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
629
630         va_start (args, fmt);
631
632         orig = g_strdup_vprintf(fmt, args);
633         error = g_error_new (MODEST_ERROR, error_code, orig);
634
635         va_end (args);
636
637         if (priv->error)
638                 g_object_unref (priv->error);
639
640         priv->error = error;
641         priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
642 }
643
644 static void
645 status_update_cb (TnyFolder *folder, const gchar *what, gint status, gpointer user_data) 
646 {
647         /* TODO: update main window progress bar */
648 }
649
650 static void
651 folder_refresh_cb (TnyFolder *folder, gboolean cancelled, gpointer user_data) 
652 {
653         if (cancelled) {
654                 ModestMailOperation *mail_operation;
655                 ModestMailOperationPrivate *priv;
656
657                 mail_operation = MODEST_MAIL_OPERATION (user_data);
658                 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_operation);
659
660                 priv->status =  MODEST_MAIL_OPERATION_STATUS_CANCELLED;
661         }
662 }
663
664 static void
665 add_attachments (TnyMsg *msg, const GList *attachments_list)
666 {
667         GList *pos;
668         TnyMimePart *attachment_part, *old_attachment;
669         const gchar *attachment_content_type;
670         const gchar *attachment_filename;
671         TnyStream *attachment_stream;
672
673         for (pos = (GList *)attachments_list; pos; pos = pos->next) {
674
675                 old_attachment = pos->data;
676                 attachment_filename = tny_mime_part_get_filename (old_attachment);
677                 attachment_stream = tny_mime_part_get_stream (old_attachment);
678                 attachment_part = TNY_MIME_PART (tny_camel_mime_part_new (camel_mime_part_new()));
679                 
680                 attachment_content_type = tny_mime_part_get_content_type (old_attachment);
681                                  
682                 tny_mime_part_construct_from_stream (attachment_part,
683                                                      attachment_stream,
684                                                      attachment_content_type);
685                 tny_stream_reset (attachment_stream);
686                 
687                 tny_mime_part_set_filename (attachment_part, attachment_filename);
688                 
689                 tny_mime_part_add_part (TNY_MIME_PART (msg), attachment_part);
690 /*              g_object_unref (attachment_part); */
691         }
692 }
693
694 static TnyMimePart *
695 add_body_part (TnyMsg *msg, 
696                const gchar *body,
697                const gchar *content_type,
698                gboolean has_attachments)
699 {
700         TnyMimePart *text_body_part = NULL;
701         TnyStream *text_body_stream;
702
703         /* Create the stream */
704         text_body_stream = TNY_STREAM (tny_camel_stream_new
705                                        (camel_stream_mem_new_with_buffer
706                                         (body, strlen(body))));
707
708         /* Create body part if needed */
709         if (has_attachments)
710                 text_body_part = 
711                         TNY_MIME_PART (tny_camel_mime_part_new (camel_mime_part_new()));
712         else
713                 text_body_part = TNY_MIME_PART(msg);
714
715         /* Construct MIME part */
716         tny_stream_reset (text_body_stream);
717         tny_mime_part_construct_from_stream (text_body_part,
718                                              text_body_stream,
719                                              content_type);
720         tny_stream_reset (text_body_stream);
721
722         /* Add part if needed */
723         if (has_attachments) {
724                 tny_mime_part_add_part (TNY_MIME_PART (msg), text_body_part);
725                 g_object_unref (G_OBJECT(text_body_part));
726         }
727
728         /* Clean */
729         g_object_unref (text_body_stream);
730
731         return text_body_part;
732 }