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