update for beta universally
[framework/messaging/email-service.git] / email-core / em-core-smtp.c
1 /*
2 *  email-service
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
7
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <time.h>
29 #include "em-core-types.h"
30 #include "c-client.h"
31 #include "em-core-global.h"
32 #include "em-core-utils.h"
33 #include "em-storage.h"
34 #include "em-core-api.h"
35 #include "em-core-smtp.h"
36 #include "em-core-event.h"
37 #include "em-core-mailbox.h"
38 #include "em-core-mesg.h"
39 #include "em-core-mime.h"
40 #include "em-core-account.h" 
41 #include "em-core-imap-mailbox.h"
42 #include "em-core-mailbox-sync.h"
43 #include "Msg_Convert.h"
44
45
46 #include <unistd.h>
47 #include "emf-dbglog.h"
48
49
50 /* Functions from uw-imap-toolkit */
51 /* extern void *fs_get(size_t size); */
52 extern void rfc822_date(char *date);
53 extern long smtp_soutr(void *stream, char *s);
54 extern long smtp_send(SENDSTREAM *stream, char *command, char *args);
55 extern long smtp_rcpt(SENDSTREAM *stream, ADDRESS *adr, long* error);
56
57 #ifdef __FEATURE_SEND_OPTMIZATION__
58 extern long smtp_soutr_test(void *stream, char *s);
59 #endif
60
61
62 static int em_core_mail_get_report_body(ENVELOPE *envelope, BODY **multipart_body, int *err_code);
63 static int em_core_mail_send_smtp(SENDSTREAM *stream, ENVELOPE *env, char *data_file, int account_id, int mail_id,  int *err_code);
64
65 void mail_send_notify(emf_send_status_t status, int total, int sent, int account_id, int mail_id,  int err_code)
66 {
67         EM_DEBUG_FUNC_BEGIN("status[%d], total[%d], sent[%d], account_id[%d], mail_id[%d], err_code[%d]", status, total, sent, account_id, mail_id, err_code);
68         
69         switch (status) {
70                 case EMF_SEND_CONNECTION_FAIL: 
71                 case EMF_SEND_FINISH:
72                 case EMF_SEND_FAIL: 
73                         break;
74                 
75                 case EMF_SEND_PROGRESS:
76                 default:
77                         break;
78         }
79         em_core_execute_event_callback(EMF_ACTION_SEND_MAIL, total, sent, status, account_id, mail_id, -1, err_code);
80         EM_DEBUG_FUNC_END();
81 }
82
83 /* ------ rfc822 handle ---------------------------------------------------*/
84 long buf_flush(void *stream, char *string)
85 {
86         EM_DEBUG_FUNC_BEGIN("stream[%p], string[%s]", stream, string);
87         EM_DEBUG_FUNC_END();
88         return 1;
89 }
90
91
92 #define RFC822_READ_BLOCK_SIZE    1024
93 #define RFC822_STRING_BUFFER_SIZE 1536
94
95 static char *em_core_find_img_tag(char *source_string)
96 {
97         EM_DEBUG_FUNC_BEGIN("source_string[%p]", source_string);
98         
99         int cur = 0, string_length;
100         if (!source_string)
101                 return false;
102
103         string_length = strlen(source_string);
104
105         for (cur = 0; cur < string_length; cur++) {
106                 if (source_string[cur] == 'I' || source_string[cur] == 'i') {
107                         cur++;
108                         if (source_string[cur] == 'M' || source_string[cur] == 'm') {
109                                 cur++;
110                                 if (source_string[cur] == 'G' || source_string[cur] == 'g') {
111                                         EM_DEBUG_FUNC_END("%s", source_string + cur - 2);
112                                         return source_string + cur - 2;
113                                 }
114                         }
115                 }
116         }
117         EM_DEBUG_FUNC_END("Can't find");
118         return NULL;
119 }
120
121 #define CONTENT_ID_BUFFER_SIZE 512
122 static char *em_core_replace_inline_image_path_with_content_id(char *source_string, BODY *html_body, int *err_code)
123 {
124         EM_DEBUG_FUNC_BEGIN("source_string[%p], html_body[%p], err_code[%p]", source_string, html_body, err_code);
125
126         int  err = EMF_ERROR_NONE;
127         char content_id_buffer[CONTENT_ID_BUFFER_SIZE], file_name_buffer[512], new_string[512], *result_string = NULL, *input_string = NULL;
128         BODY *cur_body = NULL;
129         PART *cur_part = NULL;
130
131         if (!source_string || !html_body) {
132                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
133                 err = EMF_ERROR_INVALID_PARAM;
134                 goto FINISH_OFF;
135         }
136
137         input_string = EM_SAFE_STRDUP(source_string); 
138
139         cur_part = html_body->nested.part;
140
141         while (cur_part) {
142                 cur_body = &(cur_part->body);
143                 if (cur_body) {
144                         EM_DEBUG_LOG("Has body. id[%s]", cur_body->disposition.type);
145                         if (cur_body->disposition.type && cur_body->disposition.type[0] == 'i') {   /*  Is inline content? */
146                                 EM_DEBUG_LOG("Has inline content");
147                                 memset(content_id_buffer, 0, CONTENT_ID_BUFFER_SIZE);
148                                 if (cur_body->id) {
149                                         EM_SAFE_STRNCPY(content_id_buffer, cur_body->id + 1, CONTENT_ID_BUFFER_SIZE - 1); /*  Removing <, > */
150                                         content_id_buffer[strlen(content_id_buffer) - 1] = NULL_CHAR;
151                                         /* if (em_core_get_attribute_value_of_body_part(cur_body->parameter, "name", file_name_buffer, CONTENT_ID_BUFFER_SIZE, false, &err)) { */
152                                         if (em_core_get_attribute_value_of_body_part(cur_body->parameter, "name", file_name_buffer, CONTENT_ID_BUFFER_SIZE, true, &err)) {
153                                                 EM_DEBUG_LOG("Content-ID[%s], filename[%s]", content_id_buffer, file_name_buffer);
154                                                 SNPRINTF(new_string, CONTENT_ID_BUFFER_SIZE, "cid:%s", content_id_buffer);
155                                                 result_string = em_core_replace_string(input_string, file_name_buffer, new_string);
156                                                 if (input_string)
157                                                         EM_SAFE_FREE(input_string);
158                                         }
159                                 }
160                         }
161                 }
162                 if (result_string)
163                         input_string = result_string;
164                 cur_part = cur_part->next;
165         }
166
167         if (input_string)
168                 result_string = EM_SAFE_STRDUP(input_string);
169 FINISH_OFF:
170
171         EM_SAFE_FREE(input_string);
172         if (err_code)
173                 *err_code = err;
174         
175         EM_DEBUG_FUNC_END("ret[%s]", result_string);
176         return result_string;
177 }
178
179 static int em_core_write_rfc822_body(BODY *body, BODY *html_body, FILE *fp, int *err_code)
180 {
181         EM_DEBUG_FUNC_BEGIN("body[%p], html_body[%p], fp[%p], err_code[%p]", body, html_body, fp, err_code);
182         
183         PARAMETER *param = NULL;
184         PART *part = NULL;
185         char *p = NULL, *bndry = NULL, buf[1025], *replaced_string = NULL;
186         int fd, nread, nwrite, error = EMF_ERROR_NONE;
187         
188         switch (body->type)  {
189                 case TYPEMULTIPART:
190                         EM_DEBUG_LOG("body->type = TYPEMULTIPART");
191                         part = body->nested.part;
192                         
193                         for (param = body->parameter; param; param = param->next)  {
194                                 if (strcasecmp(param->attribute, "BOUNDARY") == 0) {
195                                         bndry = param->value;
196                                         break;
197                                 }
198                         }
199                         
200                         do  {
201                                 p = buf; p[0] = '\0';
202                                 
203                                 rfc822_write_body_header(&p, &part->body);
204                                 
205                                 fprintf(fp, "--%s"CRLF_STRING, bndry);
206                                 fprintf(fp, "%s"CRLF_STRING, buf);
207                                 
208                                 em_core_write_rfc822_body(&part->body, html_body, fp, err_code);
209                         } while ((part = part->next));
210                         
211                         fprintf(fp, "--%s--"CRLF_STRING, bndry);
212                         break;
213                 
214                 default:  {
215                         EM_DEBUG_LOG("body->type is not TYPEMULTIPART");
216
217                         char *file_path = body->sparep;
218                         char buf[RFC822_STRING_BUFFER_SIZE + 1] = { 0, }, *img_tag_pos = NULL;
219                         unsigned long len;
220                         
221                         p = NULL;
222                         
223                         if (!file_path || strlen(file_path) == 0)  {
224                                 EM_DEBUG_LOG("There is no file path");
225                                 switch (body->encoding)  {
226                                         case 0:
227                                                 break;
228                                         default:
229                                                 p = cpystr((const char *)body->contents.text.data);
230                                                 len = body->contents.text.size;
231                                                 break;
232                                 }
233                                 
234                                 if (p)  {       
235                                         EM_DEBUG_LOG("p[%s]", p);
236                                         fprintf(fp, "%s"CRLF_STRING CRLF_STRING, p);
237                                         EM_SAFE_FREE(p);
238                                 }
239                                 
240                                 EM_SAFE_FREE(body->sparep);
241                                 EM_DEBUG_FUNC_END();
242                                 return true;
243                         }
244                         
245                         EM_DEBUG_LOG("Opening a file[%s]", file_path);
246                         fd = open(file_path, O_RDONLY);
247
248                         if (fd < 0)  {
249                                 EM_DEBUG_EXCEPTION("open(\"%s\") failed...", file_path);
250                                 return false;
251                         }
252                         
253                         while (1)  {
254                                 nread = read(fd, buf, (body->encoding == ENCBASE64 ? 57 : RFC822_READ_BLOCK_SIZE - 2));
255
256                                 if (nread < 0)  {
257                                         close(fd);
258                                         return false;
259                                 }
260                                 
261                                 if (nread == 0) {
262                                         close(fd);
263                                         break;
264                                 }
265                         
266                                 p = NULL;
267                                 len = nread;
268
269                                 /*  EM_DEBUG_LOG("body->type[%d], body->subtype[%c]", body->type, body->subtype[0]); */
270                                 if (body->type == TYPETEXT && (body->subtype && (body->subtype[0] == 'H' || body->subtype[0] == 'h'))) {   
271                                         EM_DEBUG_LOG("HTML Part");
272                                         img_tag_pos = em_core_find_img_tag(buf);
273
274                                         if (img_tag_pos) {
275                                                 replaced_string = em_core_replace_inline_image_path_with_content_id(buf, html_body, &error);
276                                                 if (replaced_string) {
277                                                         EM_DEBUG_LOG("em_core_replace_inline_image_path_with_content_id succeeded");
278                                                         strcpy(buf, replaced_string);
279                                                         nread = len = strlen(buf);
280                                                         EM_DEBUG_LOG("buf[%s], nread[%d], len[%d]", buf, nread, len);
281                                                 }
282                                                 else
283                                                         EM_DEBUG_LOG("em_core_replace_inline_image_path_with_content_id failed[%d]", error);
284                                         }
285                                 }
286
287                                 switch (body->encoding)  {
288                                         case ENCQUOTEDPRINTABLE:
289                                                 p = (char *)rfc822_8bit((unsigned char *)buf, (unsigned long)nread, (unsigned long *)&len);
290                                                 break;
291                                         case ENCBASE64:
292                                                 p = (char *)rfc822_binary((void *)buf, (unsigned long)nread, (unsigned long *)&len);
293                                                 break;
294                                         default:
295                                                 buf[len] = '\0';
296                                                 break;
297                                 }
298                                 
299                                 
300                                 nwrite = fprintf(fp, "%s", (p ? p : buf));
301                                 
302                                 if (nwrite != len)  {
303                                         fclose(fp);
304                                         close(fd);
305                                         EM_SAFE_FREE(p);
306                                         EM_DEBUG_EXCEPTION("fprintf failed nwrite[%d], len[%d]", nwrite, len);
307                                         return false;
308                                 }
309                                 EM_SAFE_FREE(p);
310                         }
311                         
312                         if (body->encoding == ENCQUOTEDPRINTABLE || body->encoding == ENCBASE64)
313                                 fprintf(fp, CRLF_STRING);
314                         
315                         fprintf(fp, CRLF_STRING);
316                         
317                         if (body->sparep)  {
318                                 free(body->sparep);
319                                 body->sparep = NULL;
320                         }
321                         
322                         break;
323                 }       /*  default: */
324         }
325         EM_DEBUG_FUNC_END();
326         return true;
327 }
328
329 static int em_core_write_rfc822(ENVELOPE *env, BODY *body, BODY *html_body, emf_extra_flag_t flag, char **data, int *err_code)
330 {
331         EM_DEBUG_FUNC_BEGIN("env[%p], body[%p], data[%p], err_code[%p]", env, body, data, err_code);
332         
333         int ret = false;
334         int error = EMF_ERROR_NONE;
335         
336         FILE *fp = NULL;
337         char *fname = NULL;
338         char *p = NULL;
339         size_t p_len = 0;
340         
341         if (!env || !data)  {
342                 EM_DEBUG_EXCEPTION("Invalid Parameters");
343                 error = EMF_ERROR_INVALID_PARAM;
344                 goto FINISH_OFF;
345         }
346         
347         srand(time(NULL));
348         
349         rfc822_encode_body_7bit(env, body); /*  if contents.text.data isn't NULL, the data will be encoded. */
350         
351         /*  FIXME : create memory map for this file */
352         p_len = (env->subject ? strlen(env->subject) : 0) + 8192;
353         
354         if (!(p = em_core_malloc(p_len)))  {            /* (env->subject ? strlen(env->subject) : 0) + 8192))) */
355                 EM_DEBUG_EXCEPTION(" malloc failed...");
356                 error = EMF_ERROR_OUT_OF_MEMORY;
357                 goto FINISH_OFF;
358         }
359         
360
361         RFC822BUFFER buf;
362         
363         /* write at start of buffer */
364         buf.end = (buf.beg = buf.cur = p) + p_len - 1;
365         /* buf.f = NIL; */
366         buf.f = buf_flush;
367         buf.s = NIL;
368         
369         /*  rfc822_output_header(&buf, env, body, NIL, T); */           /*  including BCC  */
370         rfc822_output_header(&buf, env, body, NIL, NIL);                /*  Excluding BCC */
371         
372         *buf.cur = '\0';                /* tie off buffer */
373         {
374                 gchar **tokens = g_strsplit(p, "CHARSET=X-UNKNOWN", 2);
375                 
376                 if (g_strv_length(tokens) > 1)  {
377                         gchar *charset;
378
379                         if (body->sparep) {
380                                 charset = g_path_get_basename(body->sparep);
381                                 char *pHtml = NULL;
382                                 if (charset != NULL) {
383                                         if ((pHtml = strstr(charset, ".htm")) != NULL)
384                                                 charset[pHtml-charset] = '\0';
385                                 }
386
387                                 SNPRINTF(p, p_len, "%sCHARSET=%s%s", tokens[0], charset, tokens[1]);
388                                 g_free(charset);
389                         }
390                         else
391                                 EM_DEBUG_EXCEPTION("body->sparep is NULL");
392                 } 
393                 
394                 g_strfreev(tokens);
395         } {
396                 gchar **tokens = g_strsplit(p, "To: undisclosed recipients: ;\015\012", 2);
397                 if (g_strv_length(tokens) > 1) 
398                         SNPRINTF(p, p_len, "%s%s", tokens[0], tokens[1]);
399                 g_strfreev(tokens);
400         }
401
402         
403         EM_DEBUG_LOG(" =============================================================================== "
404                 LF_STRING"%s"LF_STRING
405                 " =============================================================================== ", p);
406
407         if (strlen(p) > 2)              
408                 *(p + strlen(p) - 2) = '\0';
409         
410
411         if (flag.report)  {
412                 char buf[512] = {0x00, };
413                 switch (flag.report)  {
414                         case EMF_MAIL_REPORT_DSN: /*  DSN (delivery status) */
415                                 /*  change content-type */
416                                 /*  Content-Type: multipart/report; */
417                                 /*              report-type= delivery-status; */
418                                 /*              boundary="----=_NextPart_000_004F_01C76EFF.54275C50" */
419                                 break;
420                         
421                         case EMF_MAIL_REPORT_MDN: /*  MDN (read receipt) */
422                                 /*  Content-Type: multipart/report; */
423                                 /*              report-type= disposition-notification; */
424                                 /*              boundary="----=_NextPart_000_004F_01C76EFF.54275C50" */
425                                 break;
426                         
427                         case EMF_MAIL_REPORT_REQUEST: /*  require read status */
428                                 rfc822_address(buf, env->from);
429                                 if (strlen(buf))
430                                         SNPRINTF(p + strlen(p), p_len-(strlen(p)), "Disposition-Notification-To: %s"CRLF_STRING, buf);
431                                 break;
432                                 
433                         default:
434                                 break;
435                 }
436         }
437         
438         if (flag.priority)  {           /*  priority (1:high 3:normal 5:low) */
439                 SNPRINTF(p + strlen(p), p_len-(strlen(p)), "X-Priority: %d"CRLF_STRING, flag.priority);
440                 
441                 switch (flag.priority)  {
442                         case EMF_MAIL_PRIORITY_HIGH:
443                                 SNPRINTF(p + strlen(p), p_len-(strlen(p)), "X-MSMail-Priority: HIgh"CRLF_STRING);
444                                 break;
445                         case EMF_MAIL_PRIORITY_NORMAL:
446                                 SNPRINTF(p + strlen(p), p_len-(strlen(p)), "X-MSMail-Priority: Normal"CRLF_STRING);
447                                 break;
448                         case EMF_MAIL_PRIORITY_LOW:
449                                 SNPRINTF(p + strlen(p), p_len-(strlen(p)), "X-MSMail-Priority: Low"CRLF_STRING);
450                                 break;
451                 }
452         }
453         
454         SNPRINTF(p + strlen(p), p_len-(strlen(p)), CRLF_STRING);
455         
456         if (!em_core_get_temp_file_name(&fname, &error))  {
457                 EM_DEBUG_EXCEPTION(" em_core_get_temp_file_name failed[%d]", error);
458                 goto FINISH_OFF;
459         }
460         
461         if (!(fp = fopen(fname, "w+")))  {
462                 EM_DEBUG_EXCEPTION("fopen failed[%s]", fname);
463                 error = EMF_ERROR_SYSTEM_FAILURE;
464                 goto FINISH_OFF;
465         }
466         
467         fprintf(fp, "%s", p);
468         
469         if (body)  {
470                 if (!em_core_write_rfc822_body(body, html_body, fp, &error))  {
471                         EM_DEBUG_EXCEPTION("em_core_write_rfc822_body failed[%d]", error);
472                         goto FINISH_OFF;
473                 }
474         }
475
476         ret = true;
477
478         
479 FINISH_OFF:
480         if (fp != NULL)
481                 fclose(fp);
482
483 #ifdef USE_SYNC_LOG_FILE
484         em_storage_copy_file(fname, "/tmp/phone2pc.eml", false, NULL);  
485 #endif
486         
487         if (ret == true)
488                 *data = fname;
489         else if (fname != NULL)  {
490                 remove(fname);
491                 EM_SAFE_FREE(fname);
492         }
493         
494         EM_SAFE_FREE(p);
495         
496         if (err_code != NULL)
497                 *err_code = error;
498         EM_DEBUG_FUNC_END();
499         return ret;
500 }
501
502 static int em_core_set_current_time_to_mail_header(emf_mail_head_t *head, int *err)
503 {
504         EM_DEBUG_FUNC_BEGIN("head[%p], err [%p]", head, err);
505         
506         int err_code = EMF_ERROR_NONE, ret = false;
507         time_t t = time(NULL);
508         struct tm *p_tm = NULL;         
509         
510         if(!head) {
511                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
512                 err_code = EMF_ERROR_INVALID_PARAM;
513                 goto FINISH_OFF;
514         }
515
516         p_tm = gmtime(&t);
517
518         if (!p_tm)  {
519                 EM_DEBUG_EXCEPTION("localtime failed...");
520                 err_code = EMF_ERROR_SYSTEM_FAILURE;
521                 goto FINISH_OFF;
522         }
523         
524         head->datetime.year   = p_tm->tm_year + 1900;
525         head->datetime.month  = p_tm->tm_mon + 1;
526         head->datetime.day    = p_tm->tm_mday;
527         head->datetime.hour   = p_tm->tm_hour;
528         head->datetime.minute = p_tm->tm_min;
529         head->datetime.second = p_tm->tm_sec;
530
531         ret = true;
532
533 FINISH_OFF:
534
535         if(err)
536                 *err = err_code;
537
538         EM_DEBUG_FUNC_END();
539         return ret;
540 }
541
542
543
544 EXPORT_API int em_core_mail_save(int account_id, char *mailbox_name, emf_mail_t *mail_src, emf_meeting_request_t *meeting_req, int from_composer, int *err_code)
545 {
546         EM_DEBUG_FUNC_BEGIN("account_id[%d], mailbox_name[%p], mail_src[%p], from_composer[%d], err_code[%p]", account_id, mailbox_name, mail_src, from_composer, err_code);
547         
548         int ret = false, err = EMF_ERROR_NONE;
549         int attachment_id = 0, mail_id = 0, thread_id = -1, thread_item_count = 0, latest_mail_id_in_thread = -1;
550         int rule_len, rule_matched = -1, local_attachment_count = 0, local_inline_content_count = 0;
551         char *ext = NULL, *mailbox_name_spam = NULL, *mailbox_name_target = NULL;
552         char name_buf[MAX_PATH] = {0x00, }, html_body[MAX_PATH] = {0x00, };
553         char datetime[DATETIME_LENGTH] = { 0, };
554         emf_mail_tbl_t *mail_table_data = NULL;
555         emf_mailbox_tbl_t *mailbox_tbl_data = NULL;
556         emf_attachment_info_t *atch = NULL;
557         emf_mail_account_tbl_t *account_tbl_item = NULL;
558         emf_mail_rule_tbl_t *rule = NULL;
559         emf_mail_attachment_tbl_t attachment_tbl = { 0 };
560         struct stat st_buf = { 0 };
561
562         /* Validating parameters */
563         
564         if (!account_id || !mailbox_name || !mail_src || !mail_src->info || !mail_src->head)  { 
565                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
566                 err = EMF_ERROR_INVALID_PARAM;
567                 goto FINISH_OFF;
568         }
569
570         if (!em_storage_get_account_by_id(account_id, EMF_ACC_GET_OPT_DEFAULT | EMF_ACC_GET_OPT_OPTIONS, &account_tbl_item, true, &err)) {
571                 EM_DEBUG_EXCEPTION("em_storage_get_account_by_id failed. account_id[%d] err[%d]", account_id, err);
572                 err = EMF_ERROR_INVALID_ACCOUNT;
573                 goto FINISH_OFF;
574         }
575
576         if (from_composer) {
577                 if (!mail_src->head->from) 
578                         mail_src->head->from = EM_SAFE_STRDUP(account_tbl_item->email_addr);
579
580                 /* check for email_address validation */
581                 if (!em_core_verify_email_address_of_mail_header(mail_src->head, false, &err)) {
582                         EM_DEBUG_EXCEPTION("em_core_verify_email_address_of_mail_header failed [%d]", err);
583                         goto FINISH_OFF;
584                 }
585                 
586                 if (mail_src->info->extra_flags.report == EMF_MAIL_REPORT_MDN)  {       
587                         /* check read-report mail */
588                         if(!mail_src->head->to) { /* A report mail should have 'to' address */
589                                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
590                                 err = EMF_ERROR_INVALID_PARAM;
591                                 goto FINISH_OFF;
592                         }
593                         /* Create report mail body */
594                         if (!em_core_mail_get_rfc822(mail_src, NULL, NULL, NULL, &err))  {
595                                 EM_DEBUG_EXCEPTION("em_core_mail_get_rfc822 failed [%d]", err);
596                                 goto FINISH_OFF;
597                         }
598                 }
599
600                 mailbox_name_target = EM_SAFE_STRDUP(mailbox_name);
601         }
602         else {  /*  For Spam handling */
603                 emf_option_t *opt = &account_tbl_item->options;
604                 EM_DEBUG_LOG("block_address [%d], block_subject [%d]", opt->block_address, opt->block_subject);
605                 
606                 if (opt->block_address || opt->block_subject)  {
607                         int is_completed = false;
608                         int type = 0;
609                         
610                         if (!opt->block_address)
611                                 type = EMF_FILTER_SUBJECT;
612                         else if (!opt->block_subject)
613                                 type = EMF_FILTER_FROM;
614                         
615                         if (!em_storage_get_rule(ALL_ACCOUNT, type, 0, &rule_len, &is_completed, &rule, true, &err) || !rule) 
616                                 EM_DEBUG_LOG("No proper rules. em_storage_get_rule returnes [%d]", err);
617                 }
618
619                 if (rule) {
620                         if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_SPAMBOX, &mailbox_name_spam, false, &err))  {
621                                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
622                                 err = em_storage_get_emf_error_from_em_storage_error(err);
623                                 mailbox_name_spam = NULL;
624                         }
625
626                         if (mailbox_name_spam && !em_core_mail_check_rule(mail_src->head, rule, rule_len, &rule_matched, &err))  {
627                                 EM_DEBUG_EXCEPTION("em_core_mail_check_rule failed [%d]", err);
628                                 goto FINISH_OFF;
629                         }
630                 }
631
632                 if (rule_matched >= 0 && mailbox_name_spam) 
633                         mailbox_name_target = EM_SAFE_STRDUP(mailbox_name_spam);
634                 else
635                         mailbox_name_target = EM_SAFE_STRDUP(mailbox_name);
636         }
637         
638         if (!em_storage_get_mailbox_by_name(account_id, -1, mailbox_name_target, (emf_mailbox_tbl_t **)&mailbox_tbl_data, false, &err)) {
639                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);              
640                 err = em_storage_get_emf_error_from_em_storage_error(err);
641                 goto FINISH_OFF;
642         }
643
644         if (!em_storage_increase_mail_id(&mail_id, true, &err)) {
645                 EM_DEBUG_EXCEPTION("em_storage_increase_mail_id failed [%d]", err);
646                 goto FINISH_OFF;
647         }
648
649         mail_table_data = (emf_mail_tbl_t  *)em_core_malloc(sizeof(emf_mail_tbl_t));
650
651         if(!mail_table_data) {
652                 EM_DEBUG_EXCEPTION("em_core_malloc failed");
653                 err = EMF_ERROR_OUT_OF_MEMORY;
654                 goto FINISH_OFF;
655         }
656
657         mail_table_data->account_id           = account_id;
658         mail_table_data->mail_id              = mail_id;
659         mail_table_data->mailbox_name         = EM_SAFE_STRDUP(mailbox_name_target);
660         mail_table_data->mail_size            = mail_src->info->rfc822_size;
661         mail_table_data->server_mail_status   = !from_composer;
662         mail_table_data->server_mail_id       = EM_SAFE_STRDUP(mail_src->info->sid);
663         mail_table_data->full_address_from    = EM_SAFE_STRDUP(mail_src->head->from);
664         mail_table_data->full_address_to      = EM_SAFE_STRDUP(mail_src->head->to);
665         mail_table_data->full_address_cc      = EM_SAFE_STRDUP(mail_src->head->cc);
666         mail_table_data->full_address_bcc     = EM_SAFE_STRDUP(mail_src->head->bcc);
667         mail_table_data->full_address_reply   = EM_SAFE_STRDUP(mail_src->head->reply_to);
668         mail_table_data->full_address_return  = EM_SAFE_STRDUP(mail_src->head->return_path);
669         mail_table_data->subject              = EM_SAFE_STRDUP(mail_src->head->subject);
670         mail_table_data->body_download_status = mail_src->info->extra_flags.text_download_yn;   
671         mail_table_data->mailbox_type         = mailbox_tbl_data->mailbox_type;
672
673         em_core_fill_address_information_of_mail_tbl(mail_table_data);
674
675         EM_DEBUG_LOG("mail_table_data->mail_size [%d]", mail_table_data->mail_size);
676         if(mail_table_data->mail_size == 0)
677                 mail_table_data->mail_size = em_core_get_mail_size(mail_src, &err); /*  Getting file size before file moved.  */
678  
679         if (mail_src->body)  {  
680                 if (from_composer || mail_table_data->body_download_status) {
681                         if (!em_storage_create_dir(account_id, mail_id, 0, &err))  {
682                                 EM_DEBUG_EXCEPTION("em_storage_create_dir failed [%d]", err);
683                                 goto FINISH_OFF;
684                         }
685
686                         if (mail_src->body->plain) {
687                                 EM_DEBUG_LOG("mail_src->body->plain [%s]", mail_src->body->plain);
688                                 if (!em_storage_get_save_name(account_id, mail_id, 0, mail_src->body->plain_charset ? mail_src->body->plain_charset  :  "UTF-8", name_buf, &err))  {
689                                         EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
690                                         goto FINISH_OFF;
691                                 }
692                         
693                                 if (!em_storage_move_file(mail_src->body->plain, name_buf, from_composer, &err)) {
694                                         EM_DEBUG_EXCEPTION("em_storage_move_file failed [%d]", err);
695                                         goto FINISH_OFF;
696                                 }
697                                 if (mail_table_data->body_download_status == 0)
698                                         mail_table_data->body_download_status = 1;
699                                 mail_table_data->file_path_plain = EM_SAFE_STRDUP(name_buf);            
700                                 EM_SAFE_FREE(mail_src->body->plain);
701                                 mail_src->body->plain = EM_SAFE_STRDUP(name_buf);
702                         }
703
704                         if (mail_src->body->html) {
705                                 EM_DEBUG_LOG("mail_src->body->html [%s]", mail_src->body->html);
706                                 if (mail_src->body->plain_charset != NULL && mail_src->body->plain_charset[0] != NULL_CHAR) {
707                                         memcpy(html_body, mail_src->body->plain_charset, strlen(mail_src->body->plain_charset));
708                                         strcat(html_body, ".htm");
709                                 }
710                                 else {
711                                         memcpy(html_body, "UTF-8.htm", strlen("UTF-8.htm"));
712                                 }
713                                         
714                                 if (!em_storage_get_save_name(account_id, mail_id, 0, html_body, name_buf, &err))  {
715                                         EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
716                                         goto FINISH_OFF;
717                                 }
718
719                                 if (!em_storage_move_file(mail_src->body->html, name_buf, from_composer, &err))  {
720                                         EM_DEBUG_EXCEPTION("em_storage_move_file failed [%d]", err);
721                                         goto FINISH_OFF;
722                                 }
723
724                                 if (mail_table_data->body_download_status == EMF_BODY_DOWNLOAD_STATUS_NONE)
725                                         mail_table_data->body_download_status = EMF_BODY_DOWNLOAD_STATUS_FULLY_DOWNLOADED;
726
727                                 mail_table_data->file_path_html = EM_SAFE_STRDUP(name_buf);
728                                 EM_SAFE_FREE(mail_src->body->html);
729                                 mail_src->body->html = EM_SAFE_STRDUP(name_buf);
730                         }
731                 }
732         }
733
734         
735         if (!mail_src->head->datetime.year && !mail_src->head->datetime.month && !mail_src->head->datetime.day)  {
736                 /* time isn't set */
737                 if(!em_core_set_current_time_to_mail_header(mail_src->head, &err)) {
738                         EM_DEBUG_EXCEPTION("em_core_set_current_time_to_mail_header failed [%d]", err);
739                         goto FINISH_OFF;
740                 }
741         }
742         
743         SNPRINTF(datetime, sizeof(datetime), "%04d%02d%02d%02d%02d%02d", 
744         mail_src->head->datetime.year, mail_src->head->datetime.month, mail_src->head->datetime.day, mail_src->head->datetime.hour, mail_src->head->datetime.minute, mail_src->head->datetime.second);
745         
746         mail_table_data->datetime = EM_SAFE_STRDUP(datetime);
747         mail_table_data->message_id = EM_SAFE_STRDUP(mail_src->head->mid);
748
749         if (mail_src->info)  {
750                 mail_src->info->flags.draft = 1;
751                 if(!em_convert_mail_flag_to_mail_tbl(&(mail_src->info->flags), mail_table_data, &err)) {
752                         EM_DEBUG_EXCEPTION("em_convert_mail_flag_to_mail_tbl failed [%d]", err);
753                         goto FINISH_OFF;
754                 }
755                 mail_table_data->priority = mail_src->info->extra_flags.priority;
756                 mail_table_data->lock_status = mail_src->info->extra_flags.lock;
757                 mail_table_data->report_status = mail_src->info->extra_flags.report;
758         }
759         mail_table_data->save_status = EMF_MAIL_STATUS_SAVED;
760         
761         mail_id = mail_table_data->mail_id;
762         mail_src->info->uid = mail_id;
763
764         mail_table_data->meeting_request_status = mail_src->info->is_meeting_request;
765         
766         if(mail_src->info->thread_id == 0) {
767                 if (em_storage_get_thread_id_of_thread_mails(mail_table_data, &thread_id, &latest_mail_id_in_thread, &thread_item_count) != EMF_ERROR_NONE)
768                         EM_DEBUG_LOG(" em_storage_get_thread_id_of_thread_mails is failed");
769                 
770                 if (thread_id == -1) {
771                         mail_table_data->thread_id = mail_id;
772                         mail_table_data->thread_item_count = thread_item_count = 1;
773                 }
774                 else  {
775                         mail_table_data->thread_id = thread_id;
776                         thread_item_count++;
777                 }
778         }
779         else {
780                 mail_table_data->thread_id = mail_src->info->thread_id;
781                 thread_item_count = 2;
782         }
783
784         /*  Getting attachment count */
785         if (mail_src->body)     
786                 atch = mail_src->body->attachment;
787         while (atch)  {
788                 if (atch->inline_content)
789                         local_inline_content_count++;
790                 local_attachment_count++;
791                 atch = atch->next;
792         }
793
794         mail_table_data->inline_content_count = local_inline_content_count;
795         mail_table_data->attachment_count     = local_attachment_count;
796
797         EM_DEBUG_LOG("inline_content_count [%d]", local_inline_content_count);
798         EM_DEBUG_LOG("attachment_count [%d]", local_attachment_count);
799         
800         EM_DEBUG_LOG("preview_text[%p]", mail_table_data->preview_text);
801         if (mail_table_data->preview_text == NULL) {
802                 if ( (err = em_core_get_preview_text_from_file(mail_table_data->file_path_plain, mail_table_data->file_path_html, MAX_PREVIEW_TEXT_LENGTH, &(mail_table_data->preview_text))) != EMF_ERROR_NONE) {
803                         EM_DEBUG_EXCEPTION("em_core_get_preview_text_from_file failed[%d]", err);
804                         goto FINISH_OFF;
805                 }
806         }
807
808         em_storage_begin_transaction(NULL, NULL, NULL);
809
810         /*  insert mail to mail table */
811         if (!em_storage_add_mail(mail_table_data, 0, false, &err))  {
812                 EM_DEBUG_EXCEPTION("em_storage_add_mail failed [%d]", err);
813                 /*  ROLLBACK TRANSACTION; */
814                 em_storage_rollback_transaction(NULL, NULL, NULL);
815                 err = em_storage_get_emf_error_from_em_storage_error(err);
816                 goto FINISH_OFF;
817         }
818
819         EM_DEBUG_LOG("thread_item_count [%d]", thread_item_count);
820         if (thread_item_count > 1) {
821                 if (!em_storage_update_latest_thread_mail(mail_table_data->account_id, mail_table_data->thread_id, 0, 0, false, &err)) {
822                         EM_DEBUG_EXCEPTION("em_storage_update_latest_thread_mail failed [%d]", err);
823                         em_storage_rollback_transaction(NULL, NULL, NULL);
824                         err = em_storage_get_emf_error_from_em_storage_error(err);
825                         goto FINISH_OFF;
826                 }
827         }
828
829         /*  Insert attachment information to DB */
830         if (mail_src->body)     
831                 atch = mail_src->body->attachment;
832         EM_DEBUG_LOG("atch [%p]", atch);
833         while (atch)  {
834                 if (from_composer && stat(atch->savename, &st_buf) < 0)  {
835                         atch = atch->next;
836                         continue;
837                 }
838                 
839                 if (!atch->inline_content) {
840                         if (!em_storage_get_new_attachment_no(&attachment_id, &err)) {
841                                 EM_DEBUG_EXCEPTION("em_storage_get_new_attachment_no failed [%d]", err);
842                                 em_storage_rollback_transaction(NULL, NULL, NULL);
843                                 goto FINISH_OFF;
844                         }
845                 }
846
847                 if (!em_storage_create_dir(account_id, mail_id, atch->inline_content ? 0  :  attachment_id, &err))  {
848                         EM_DEBUG_EXCEPTION("em_storage_create_dir failed [%d]", err);
849                         em_storage_rollback_transaction(NULL, NULL, NULL);
850                         goto FINISH_OFF;
851                 }
852                 
853                 if (!em_storage_get_save_name(account_id, mail_id, atch->inline_content ? 0  :  attachment_id, atch->name, name_buf, &err))  {
854                         EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
855                         em_storage_rollback_transaction(NULL, NULL, NULL);
856                         goto FINISH_OFF;
857                 }
858                 
859                 if (from_composer || atch->downloaded) {        
860                         if (!em_storage_copy_file(atch->savename, name_buf, from_composer, &err))  {
861                                 EM_DEBUG_EXCEPTION("em_storage_copy_file failed [%d]", err);
862                                 em_storage_rollback_transaction(NULL, NULL, NULL);
863                                 goto FINISH_OFF;
864                         }
865                         
866                         if ((ext = strrchr(atch->name, '.'))) { 
867                                 if (!strncmp(ext, ".vcs", strlen(".vcs")))
868                                         remove(atch->savename);
869                                 else if (!strncmp(ext, ".vcf", strlen(".vcf")))
870                                         remove(atch->savename);
871                                 else if (!strncmp(ext, ".vnt", strlen(".vnt")))
872                                         remove(atch->savename);
873                         }
874                 }
875                 
876                 memset(&attachment_tbl, 0x00, sizeof(emf_mail_attachment_tbl_t));
877                 
878                 attachment_tbl.mail_id         = mail_id;
879                 attachment_tbl.account_id      = account_id;
880                 attachment_tbl.mailbox_name    = mailbox_name_target;
881                 attachment_tbl.file_yn         = atch->downloaded;
882                 attachment_tbl.flag2           = mail_src->body->attachment->drm;  
883                 attachment_tbl.attachment_name = atch->name;
884                 attachment_tbl.attachment_path = name_buf;
885                 attachment_tbl.flag3           = atch->inline_content;
886                 if (from_composer)
887                         attachment_tbl.attachment_size = st_buf.st_size;
888                 else
889                         attachment_tbl.attachment_size = atch->size;
890
891                 if (!em_storage_add_attachment(&attachment_tbl, 0, false, &err))  {
892                         EM_DEBUG_EXCEPTION("em_storage_add_attachment failed [%d]", err);
893                         em_storage_rollback_transaction(NULL, NULL, NULL);
894                         err = em_storage_get_emf_error_from_em_storage_error(err);
895                         goto FINISH_OFF;
896                 }
897                 atch->attachment_id = attachment_tbl.attachment_id;             
898                 atch = atch->next;
899         }
900
901         /*  Insert Meeting request to DB */
902         if (mail_src->info->is_meeting_request == EMF_MAIL_TYPE_MEETING_REQUEST
903                 || mail_src->info->is_meeting_request == EMF_MAIL_TYPE_MEETING_RESPONSE
904                 || mail_src->info->is_meeting_request == EMF_MAIL_TYPE_MEETING_ORIGINATINGREQUEST) {
905                 EM_DEBUG_LOG("This mail has the meeting request");
906                 meeting_req->mail_id = mail_id;
907                 if (!em_storage_add_meeting_request(account_id, mailbox_name_target, meeting_req, false, &err))  {
908                         EM_DEBUG_EXCEPTION("em_storage_add_meeting_request failed [%d]", err);
909                         err = em_storage_get_emf_error_from_em_storage_error(err);
910                         goto FINISH_OFF;
911                 }                       
912         }
913
914         em_storage_commit_transaction(NULL, NULL, NULL);
915
916         if (!em_storage_notify_storage_event(NOTI_MAIL_ADD, account_id, mail_id, mailbox_name_target, mail_table_data->thread_id))
917                         EM_DEBUG_LOG("em_storage_notify_storage_event [NOTI_MAIL_ADD] failed.");
918
919         if (account_tbl_item->receiving_server_type != EMF_SERVER_TYPE_ACTIVE_SYNC) {
920                 if (!em_core_mailbox_remove_overflowed_mails(mailbox_tbl_data, &err)) {
921                         if (err == EM_STORAGE_ERROR_MAIL_NOT_FOUND || err == EMF_ERROR_NOT_SUPPORTED)
922                                 err = EMF_ERROR_NONE;
923                         else
924                                 EM_DEBUG_LOG("em_core_mailbox_remove_overflowed_mails failed [%d]", err);
925                 }       
926         }
927
928         if ( !from_composer && (mail_src->info->flags.seen == 0) 
929                                 && mail_table_data->mailbox_type != EMF_MAILBOX_TYPE_TRASH 
930                                 && mail_table_data->mailbox_type != EMF_MAILBOX_TYPE_SPAMBOX) { /* 0x01 fSeen */
931                 if (!em_storage_update_sync_status_of_account(account_id, SET_TYPE_SET, SYNC_STATUS_SYNCING | SYNC_STATUS_HAVE_NEW_MAILS, true, &err)) 
932                                 EM_DEBUG_LOG("em_storage_update_sync_status_of_account failed [%d]", err);
933                 em_core_add_notification_for_unread_mail_by_mail_header(account_id, mail_id, mail_src->head);
934                 em_core_check_unread_mail();
935         }
936
937         ret = true;
938         
939 FINISH_OFF: 
940         if (mail_table_data)
941                 em_storage_free_mail(&mail_table_data, 1, NULL);
942
943         if (account_tbl_item)
944                 em_storage_free_account(&account_tbl_item, 1, NULL);
945
946         if (mailbox_tbl_data)
947                 em_storage_free_mailbox(&mailbox_tbl_data, 1, NULL);
948         
949         EM_SAFE_FREE(mailbox_name_spam);
950         EM_SAFE_FREE(mailbox_name_target);
951         
952         if (err_code)
953                 *err_code = err;
954
955         EM_DEBUG_FUNC_END();
956         return ret;
957 }
958
959
960 EXPORT_API int em_core_add_mail(emf_mail_data_t *input_mail_data, emf_attachment_data_t *input_attachment_data_list, int input_attachment_count, emf_meeting_request_t *input_meeting_request, int input_sync_server)
961 {
962         EM_DEBUG_FUNC_BEGIN("input_mail_data[%p], input_attachment_data_list [%p], input_attachment_count [%d], input_meeting_request [%p], input_sync_server[%d]", input_mail_data, input_attachment_data_list, input_attachment_count, input_meeting_request, input_sync_server);
963         
964         int err = EMF_ERROR_NONE;
965         int attachment_id = 0, thread_id = -1, thread_item_count = 0, latest_mail_id_in_thread = -1;
966         int i = 0, rule_len, rule_matched = -1, local_attachment_count = 0, local_inline_content_count = 0;
967         char *ext = NULL, *mailbox_name_spam = NULL, *mailbox_name_target = NULL;
968         char name_buf[MAX_PATH] = {0x00, }, html_body[MAX_PATH] = {0x00, };
969         emf_mail_tbl_t    *converted_mail_tbl = NULL;
970         emf_mailbox_tbl_t *mailbox_tbl = NULL;
971         emf_mail_attachment_tbl_t attachment_tbl = { 0 };
972         emf_mail_account_tbl_t *account_tbl_item = NULL;
973         emf_mail_rule_tbl_t *rule = NULL;
974         struct stat st_buf = { 0 };
975
976         /* Validating parameters */
977         
978         if (!input_mail_data || !(input_mail_data->account_id) || !(input_mail_data->mailbox_name))  {  
979                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
980                 err = EMF_ERROR_INVALID_PARAM;
981                 goto FINISH_OFF;
982         }
983
984         if (!em_storage_get_account_by_id(input_mail_data->account_id, EMF_ACC_GET_OPT_DEFAULT | EMF_ACC_GET_OPT_OPTIONS, &account_tbl_item, true, &err)) {
985                 EM_DEBUG_EXCEPTION("em_storage_get_account_by_id failed. account_id[%d] err[%d]", input_mail_data->account_id, err);
986                 err = EMF_ERROR_INVALID_ACCOUNT;
987                 goto FINISH_OFF;
988         }
989
990         if(input_sync_server) {
991                 if (input_mail_data->file_path_plain)  {
992                         if (stat(input_mail_data->file_path_plain, &st_buf) < 0)  {
993                                 EM_DEBUG_EXCEPTION("input_mail_data->file_path_plain, stat(\"%s\") failed...", input_mail_data->file_path_plain);
994                                 err = EMF_ERROR_INVALID_MAIL;
995                                 goto FINISH_OFF;
996                         }
997                 }
998                 
999                 if (input_mail_data->file_path_html)  {
1000                         if (stat(input_mail_data->file_path_html, &st_buf) < 0)  {
1001                                 EM_DEBUG_EXCEPTION("input_mail_data->file_path_html, stat(\"%s\") failed...", input_mail_data->file_path_html);
1002                                 err = EMF_ERROR_INVALID_MAIL;
1003                                 goto FINISH_OFF;
1004                         }
1005                 }
1006                 
1007                 if (input_attachment_count && input_attachment_data_list)  {
1008                         for (i = 0; i < input_attachment_count; i++)  {
1009                                 if (input_attachment_data_list[i].save_status) {
1010                                         if (!input_attachment_data_list[i].attachment_path || stat(input_attachment_data_list[i].attachment_path, &st_buf) < 0)  {
1011                                                 EM_DEBUG_EXCEPTION("stat(\"%s\") failed...", input_attachment_data_list[i].attachment_path);
1012                                                 err = EMF_ERROR_INVALID_ATTACHMENT;             
1013                                                 goto FINISH_OFF;
1014                                         }
1015                                 }
1016                         }
1017                 }
1018         }
1019
1020         if (input_sync_server) {
1021                 if (!input_mail_data->full_address_from) 
1022                         input_mail_data->full_address_from = EM_SAFE_STRDUP(account_tbl_item->email_addr);
1023
1024                 /* check for email_address validation */
1025                 if (!em_core_verify_email_address_of_mail_data(input_mail_data, false, &err)) {
1026                         EM_DEBUG_EXCEPTION("em_core_verify_email_address_of_mail_data failed [%d]", err);
1027                         goto FINISH_OFF;
1028                 }
1029                 
1030                 if (input_mail_data->report_status == EMF_MAIL_REPORT_MDN)  {   
1031                         /* check read-report mail */
1032                         if(!input_mail_data->full_address_to) { /* A report mail should have 'to' address */
1033                                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
1034                                 err = EMF_ERROR_INVALID_PARAM;
1035                                 goto FINISH_OFF;
1036                         }
1037                         /* Create report mail body */
1038                         /*
1039                         if (!em_core_mail_get_rfc822(mail_src, NULL, NULL, NULL, &err))  {
1040                                 EM_DEBUG_EXCEPTION("em_core_mail_get_rfc822 failed [%d]", err);
1041                                 goto FINISH_OFF;
1042                         }
1043                         */
1044                 }
1045
1046                 mailbox_name_target = EM_SAFE_STRDUP(input_mail_data->mailbox_name);
1047         }
1048         else {  /*  For Spam handling */
1049                 emf_option_t *opt = &account_tbl_item->options;
1050                 EM_DEBUG_LOG("block_address [%d], block_subject [%d]", opt->block_address, opt->block_subject);
1051                 
1052                 if (opt->block_address || opt->block_subject)  {
1053                         int is_completed = false;
1054                         int type = 0;
1055                         
1056                         if (!opt->block_address)
1057                                 type = EMF_FILTER_SUBJECT;
1058                         else if (!opt->block_subject)
1059                                 type = EMF_FILTER_FROM;
1060                         
1061                         if (!em_storage_get_rule(ALL_ACCOUNT, type, 0, &rule_len, &is_completed, &rule, true, &err) || !rule) 
1062                                 EM_DEBUG_LOG("No proper rules. em_storage_get_rule returns [%d]", err);
1063                 }
1064
1065                 if (rule) {
1066                         if (!em_storage_get_mailboxname_by_mailbox_type(input_mail_data->account_id, EMF_MAILBOX_TYPE_SPAMBOX, &mailbox_name_spam, false, &err))  {
1067                                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1068                                 err = em_storage_get_emf_error_from_em_storage_error(err);
1069                                 mailbox_name_spam = NULL;
1070                         }
1071
1072                         /*
1073                         if (mailbox_name_spam && !em_core_mail_check_rule(mail_src->head, rule, rule_len, &rule_matched, &err))  {
1074                                 EM_DEBUG_EXCEPTION("em_core_mail_check_rule failed [%d]", err);
1075                                 goto FINISH_OFF;
1076                         }
1077                         */
1078                 }
1079
1080                 if (rule_matched >= 0 && mailbox_name_spam) 
1081                         mailbox_name_target = EM_SAFE_STRDUP(mailbox_name_spam);
1082                 else
1083                         mailbox_name_target = EM_SAFE_STRDUP(input_mail_data->mailbox_name);
1084         }
1085         
1086         if (!em_storage_get_mailbox_by_name(input_mail_data->account_id, -1, mailbox_name_target, (emf_mailbox_tbl_t **)&mailbox_tbl, false, &err)) {
1087                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);              
1088                 err = em_storage_get_emf_error_from_em_storage_error(err);
1089                 goto FINISH_OFF;
1090         }
1091
1092         if (!em_storage_increase_mail_id(&input_mail_data->mail_id, true, &err)) {
1093                 EM_DEBUG_EXCEPTION("em_storage_increase_mail_id failed [%d]", err);
1094                 goto FINISH_OFF;
1095         }
1096
1097         EM_DEBUG_LOG("input_mail_data->mail_size [%d]", input_mail_data->mail_size);
1098
1099         if(input_mail_data->mail_size == 0)
1100                 em_core_calc_mail_size(input_mail_data, input_attachment_data_list, input_attachment_count, &(input_mail_data->mail_size)); /*  Getting file size before file moved.  */
1101
1102         if (input_sync_server || input_mail_data->body_download_status) {
1103                 if (!em_storage_create_dir(input_mail_data->account_id, input_mail_data->mail_id, 0, &err))  {
1104                         EM_DEBUG_EXCEPTION("em_storage_create_dir failed [%d]", err);
1105                         goto FINISH_OFF;
1106                 }
1107
1108                 if (input_mail_data->file_path_plain) {
1109                         EM_DEBUG_LOG("input_mail_data->file_path_plain [%s]", input_mail_data->file_path_plain);
1110                         /* if (!em_storage_get_save_name(account_id, mail_id, 0, input_mail_data->body->plain_charset ? input_mail_data->body->plain_charset  :  "UTF-8", name_buf, &err))  {*/
1111                         if (!em_storage_get_save_name(input_mail_data->account_id, input_mail_data->mail_id, 0, "UTF-8", name_buf, &err))  {
1112                                 EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
1113                                 goto FINISH_OFF;
1114                         }
1115                 
1116                         if (!em_storage_move_file(input_mail_data->file_path_plain, name_buf, input_sync_server, &err)) {
1117                                 EM_DEBUG_EXCEPTION("em_storage_move_file failed [%d]", err);
1118                                 goto FINISH_OFF;
1119                         }
1120                         if (input_mail_data->body_download_status == EMF_BODY_DOWNLOAD_STATUS_NONE)
1121                                 input_mail_data->body_download_status = EMF_BODY_DOWNLOAD_STATUS_FULLY_DOWNLOADED;
1122
1123                         EM_SAFE_FREE(input_mail_data->file_path_plain);
1124                         input_mail_data->file_path_plain = EM_SAFE_STRDUP(name_buf);
1125                 }
1126
1127                 if (input_mail_data->file_path_html) {
1128                         EM_DEBUG_LOG("input_mail_data->file_path_html [%s]", input_mail_data->file_path_html);
1129                         memcpy(html_body, "UTF-8.htm", strlen("UTF-8.htm"));
1130                                 
1131                         if (!em_storage_get_save_name(input_mail_data->account_id, input_mail_data->mail_id, 0, html_body, name_buf, &err))  {
1132                                 EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
1133                                 goto FINISH_OFF;
1134                         }
1135
1136                         if (!em_storage_move_file(input_mail_data->file_path_html, name_buf, input_sync_server, &err))  {
1137                                 EM_DEBUG_EXCEPTION("em_storage_move_file failed [%d]", err);
1138                                 goto FINISH_OFF;
1139                         }
1140
1141                         if (input_mail_data->body_download_status == EMF_BODY_DOWNLOAD_STATUS_NONE)
1142                                 input_mail_data->body_download_status = EMF_BODY_DOWNLOAD_STATUS_FULLY_DOWNLOADED;
1143
1144                         EM_SAFE_FREE(input_mail_data->file_path_html);
1145                         input_mail_data->file_path_html = EM_SAFE_STRDUP(name_buf);
1146                 }
1147         }
1148
1149         
1150         if (!input_mail_data->datetime)  {
1151                 /* time isn't set */
1152                 input_mail_data->datetime = em_core_get_current_time_string(&err);
1153                 if(!input_mail_data->datetime) {
1154                         EM_DEBUG_EXCEPTION("em_core_get_current_time_string failed [%d]", err);
1155                         goto FINISH_OFF;
1156                 }
1157         }
1158
1159         EM_SAFE_FREE(input_mail_data->mailbox_name);
1160
1161         input_mail_data->mailbox_name         = EM_SAFE_STRDUP(mailbox_name_target);
1162         input_mail_data->mailbox_type         = mailbox_tbl->mailbox_type;
1163         input_mail_data->server_mail_status   = !input_sync_server;
1164         input_mail_data->save_status          = EMF_MAIL_STATUS_SAVED;
1165
1166         /*  Getting attachment count */
1167         for (i = 0; i < input_attachment_count; i++) {
1168                 if (input_attachment_data_list[i].inline_content_status== 1)
1169                         local_inline_content_count++;
1170                 local_attachment_count++;
1171         }
1172
1173         input_mail_data->inline_content_count = local_inline_content_count;
1174         input_mail_data->attachment_count     = local_attachment_count;
1175
1176         EM_DEBUG_LOG("inline_content_count   [%d]", local_inline_content_count);
1177         EM_DEBUG_LOG("input_attachment_count [%d]", local_attachment_count);
1178
1179         EM_DEBUG_LOG("preview_text[%p]", input_mail_data->preview_text);
1180         if (input_mail_data->preview_text == NULL) {
1181                 if ( (err = em_core_get_preview_text_from_file(input_mail_data->file_path_plain, input_mail_data->file_path_html, MAX_PREVIEW_TEXT_LENGTH, &(input_mail_data->preview_text))) != EMF_ERROR_NONE) {
1182                         EM_DEBUG_EXCEPTION("em_core_get_preview_text_from_file failed[%d]", err);
1183                         goto FINISH_OFF;
1184                 }
1185         }
1186
1187         if (!em_convert_mail_data_to_mail_tbl(input_mail_data, 1, &converted_mail_tbl, &err)) {
1188                 EM_DEBUG_EXCEPTION("em_convert_mail_data_to_mail_tbl failed [%d]", err);
1189                 goto FINISH_OFF;
1190         }
1191         
1192         /* Fill address information */
1193         em_core_fill_address_information_of_mail_tbl(converted_mail_tbl);
1194
1195         /* Fill thread id */
1196         if(input_mail_data->thread_id == 0) {
1197                 if (em_storage_get_thread_id_of_thread_mails(converted_mail_tbl, &thread_id, &latest_mail_id_in_thread, &thread_item_count) != EMF_ERROR_NONE)
1198                         EM_DEBUG_LOG(" em_storage_get_thread_id_of_thread_mails is failed");
1199                 
1200                 if (thread_id == -1) {
1201                         converted_mail_tbl->thread_id         = input_mail_data->mail_id;
1202                         converted_mail_tbl->thread_item_count = thread_item_count = 1;
1203                 }
1204                 else  {
1205                         converted_mail_tbl->thread_id         = thread_id;
1206                         thread_item_count++;
1207                 }
1208         }
1209         else {
1210                 thread_item_count                    = 2;
1211         }
1212
1213         em_storage_begin_transaction(NULL, NULL, NULL);
1214
1215         /*  insert mail to mail table */
1216         if (!em_storage_add_mail(converted_mail_tbl, 0, false, &err))  {
1217                 EM_DEBUG_EXCEPTION("em_storage_add_mail failed [%d]", err);
1218                 /*  ROLLBACK TRANSACTION; */
1219                 em_storage_rollback_transaction(NULL, NULL, NULL);
1220                 err = em_storage_get_emf_error_from_em_storage_error(err);
1221                 goto FINISH_OFF;
1222         }
1223
1224         /* Update thread information */
1225         EM_DEBUG_LOG("thread_item_count [%d]", thread_item_count);
1226
1227         if (thread_item_count > 1) {
1228                 if (!em_storage_update_latest_thread_mail(input_mail_data->account_id, converted_mail_tbl->thread_id, 0, 0, false, &err)) {
1229                         EM_DEBUG_EXCEPTION("em_storage_update_latest_thread_mail failed [%d]", err);
1230                         em_storage_rollback_transaction(NULL, NULL, NULL);
1231                         err = em_storage_get_emf_error_from_em_storage_error(err);
1232                         goto FINISH_OFF;
1233                 }
1234         }
1235
1236         /*  Insert attachment information to DB */
1237
1238         for (i = 0; i < input_attachment_count; i++) {
1239                 if (input_attachment_data_list[i].attachment_size == 0) { 
1240                         /* set attachment size */
1241                         if(input_attachment_data_list[i].attachment_path && stat(input_attachment_data_list[i].attachment_path, &st_buf) < 0) 
1242                                 input_attachment_data_list[i].attachment_size = st_buf.st_size;
1243                 }
1244                 
1245                 if (!input_attachment_data_list[i].inline_content_status) {
1246                         if (!em_storage_get_new_attachment_no(&attachment_id, &err)) {
1247                                 EM_DEBUG_EXCEPTION("em_storage_get_new_attachment_no failed [%d]", err);
1248                                 em_storage_rollback_transaction(NULL, NULL, NULL);
1249                                 goto FINISH_OFF;
1250                         }
1251                 }
1252
1253                 if (!em_storage_create_dir(input_mail_data->account_id, input_mail_data->mail_id, input_attachment_data_list[i].inline_content_status ? 0  :  attachment_id, &err))  {
1254                         EM_DEBUG_EXCEPTION("em_storage_create_dir failed [%d]", err);
1255                         em_storage_rollback_transaction(NULL, NULL, NULL);
1256                         goto FINISH_OFF;
1257                 }
1258                 
1259                 if (!em_storage_get_save_name(input_mail_data->account_id, input_mail_data->mail_id, input_attachment_data_list[i].inline_content_status ? 0  :  attachment_id, input_attachment_data_list[i].attachment_name, name_buf, &err))  {
1260                         EM_DEBUG_EXCEPTION("em_storage_get_save_name failed [%d]", err);
1261                         em_storage_rollback_transaction(NULL, NULL, NULL);
1262                         goto FINISH_OFF;
1263                 }
1264                 
1265                 if (input_sync_server || input_attachment_data_list[i].save_status) {   
1266                         if (!em_storage_copy_file(input_attachment_data_list[i].attachment_path, name_buf, input_sync_server, &err))  {
1267                                 EM_DEBUG_EXCEPTION("em_storage_copy_file failed [%d]", err);
1268                                 em_storage_rollback_transaction(NULL, NULL, NULL);
1269                                 goto FINISH_OFF;
1270                         }
1271                         
1272                         if ((ext = strrchr(input_attachment_data_list[i].attachment_name, '.'))) {      
1273                                 if (!strncmp(ext, ".vcs", strlen(".vcs")))
1274                                         remove(input_attachment_data_list[i].attachment_path);
1275                                 else if (!strncmp(ext, ".vcf", strlen(".vcf")))
1276                                         remove(input_attachment_data_list[i].attachment_path);
1277                                 else if (!strncmp(ext, ".vnt", strlen(".vnt")))
1278                                         remove(input_attachment_data_list[i].attachment_path);
1279                         }
1280                 }
1281
1282                 memset(&attachment_tbl, 0, sizeof(emf_mail_attachment_tbl_t));
1283                 attachment_tbl.attachment_name = input_attachment_data_list[i].attachment_name;
1284                 attachment_tbl.attachment_path = name_buf;
1285                 attachment_tbl.attachment_size = input_attachment_data_list[i].attachment_size;
1286                 attachment_tbl.mail_id         = input_mail_data->mail_id;
1287                 attachment_tbl.account_id      = input_mail_data->account_id;
1288                 attachment_tbl.mailbox_name    = input_mail_data->mailbox_name;
1289                 attachment_tbl.file_yn         = input_attachment_data_list[i].save_status;
1290                 attachment_tbl.flag2           = input_attachment_data_list[i].drm_status;
1291                 attachment_tbl.flag3           = input_attachment_data_list[i].inline_content_status;
1292
1293                 if (!em_storage_add_attachment(&attachment_tbl, 0, false, &err))  {
1294                         EM_DEBUG_EXCEPTION("em_storage_add_attachment failed [%d]", err);
1295                         em_storage_rollback_transaction(NULL, NULL, NULL);
1296                         err = em_storage_get_emf_error_from_em_storage_error(err);
1297                         goto FINISH_OFF;
1298                 }
1299                 input_attachment_data_list[i].attachment_id = attachment_tbl.attachment_id;
1300         }
1301
1302         /*  Insert Meeting request to DB */
1303         if (input_mail_data->meeting_request_status == EMF_MAIL_TYPE_MEETING_REQUEST
1304                 || input_mail_data->meeting_request_status == EMF_MAIL_TYPE_MEETING_RESPONSE
1305                 || input_mail_data->meeting_request_status == EMF_MAIL_TYPE_MEETING_ORIGINATINGREQUEST) {
1306                 EM_DEBUG_LOG("This mail has the meeting request");
1307                 input_meeting_request->mail_id = input_mail_data->mail_id;
1308                 if (!em_storage_add_meeting_request(input_mail_data->account_id, mailbox_name_target, input_meeting_request, false, &err))  {
1309                         EM_DEBUG_EXCEPTION("em_storage_add_meeting_request failed [%d]", err);
1310                         err = em_storage_get_emf_error_from_em_storage_error(err);
1311                         goto FINISH_OFF;
1312                 }                       
1313         }
1314
1315         em_storage_commit_transaction(NULL, NULL, NULL);
1316
1317         if (!em_storage_notify_storage_event(NOTI_MAIL_ADD, converted_mail_tbl->account_id, converted_mail_tbl->mail_id, mailbox_name_target, converted_mail_tbl->thread_id))
1318                         EM_DEBUG_LOG("em_storage_notify_storage_event [NOTI_MAIL_ADD] failed.");
1319
1320         if (account_tbl_item->receiving_server_type != EMF_SERVER_TYPE_ACTIVE_SYNC) {
1321                 if (!em_core_mailbox_remove_overflowed_mails(mailbox_tbl, &err)) {
1322                         if (err == EM_STORAGE_ERROR_MAIL_NOT_FOUND || err == EMF_ERROR_NOT_SUPPORTED)
1323                                 err = EMF_ERROR_NONE;
1324                         else
1325                                 EM_DEBUG_LOG("em_core_mailbox_remove_overflowed_mails failed [%d]", err);
1326                 }       
1327         }
1328
1329         if ( !input_sync_server && (input_mail_data->flags_seen_field == 0) 
1330                                 && input_mail_data->mailbox_type != EMF_MAILBOX_TYPE_TRASH 
1331                                 && input_mail_data->mailbox_type != EMF_MAILBOX_TYPE_SPAMBOX) { 
1332                 if (!em_storage_update_sync_status_of_account(input_mail_data->account_id, SET_TYPE_SET, SYNC_STATUS_SYNCING | SYNC_STATUS_HAVE_NEW_MAILS, true, &err)) 
1333                                 EM_DEBUG_LOG("em_storage_update_sync_status_of_account failed [%d]", err);
1334                 em_core_add_notification_for_unread_mail(input_mail_data);
1335                 em_core_check_unread_mail();
1336         }
1337         
1338 FINISH_OFF: 
1339         if (account_tbl_item)
1340                 em_storage_free_account(&account_tbl_item, 1, NULL);
1341
1342         if (mailbox_tbl)
1343                 em_storage_free_mailbox(&mailbox_tbl, 1, NULL);
1344
1345         if (converted_mail_tbl)
1346                 em_storage_free_mail(&converted_mail_tbl, 1, NULL);
1347         
1348         EM_SAFE_FREE(mailbox_name_spam);
1349         EM_SAFE_FREE(mailbox_name_target);
1350         
1351         EM_DEBUG_FUNC_END();
1352         return err;
1353 }
1354
1355 EXPORT_API int  
1356 em_core_mail_add_meeting_request(int account_id, char *mailbox_name, emf_meeting_request_t *meeting_req, int *err_code)
1357 {
1358         EM_DEBUG_FUNC_BEGIN("account_id[%d], mailbox_name[%s], meeting_req[%p], err_code[%p]", account_id, mailbox_name, meeting_req, err_code);
1359         int ret = false;
1360         int err = EMF_ERROR_NONE;
1361
1362         if (!meeting_req || meeting_req->mail_id <= 0) {
1363                 if (meeting_req)
1364                         EM_DEBUG_EXCEPTION("mail_id[%d]", meeting_req->mail_id);
1365                 
1366                 err = EMF_ERROR_INVALID_PARAM;
1367                 goto FINISH_OFF;
1368         }
1369
1370         if (!em_storage_add_meeting_request(account_id, mailbox_name, meeting_req, 1, &err))  {
1371                 EM_DEBUG_EXCEPTION(" em_storage_add_meeting_request failed [%d]", err);
1372                 err = em_storage_get_emf_error_from_em_storage_error(err);
1373                 goto FINISH_OFF;
1374         }       
1375
1376         ret = true;
1377         
1378 FINISH_OFF: 
1379         
1380         if (err_code)
1381                 *err_code = err;
1382
1383         EM_DEBUG_FUNC_END();
1384         return ret;     
1385 }
1386
1387 /*  send a message (not saved) */
1388 EXPORT_API int em_core_mail_send(int account_id, char *input_mailbox_name, int mail_id, emf_option_t *sending_option, int *err_code)
1389 {
1390         EM_DEBUG_FUNC_BEGIN("account_id[%d], input_mailbox_name[%s], mail_id[%d], sending_option[%p], err_code[%p]", account_id, input_mailbox_name, mail_id, sending_option, err_code);
1391         EM_PROFILE_BEGIN(profile_em_core_mail_send);
1392         int ret = false;
1393         int err = EMF_ERROR_NONE, err2 = EMF_ERROR_NONE;
1394         int status = EMF_SEND_FAIL;
1395         
1396         SENDSTREAM *stream = NULL;
1397         ENVELOPE *envelope = NULL;
1398         sslstart_t stls = NULL;
1399         emf_mail_t *mail = NULL;
1400         emf_account_t *ref_account = NULL;
1401         emf_option_t *opt = NULL;
1402         emf_mailbox_t dest_mbox = {0};
1403         void *tmp_stream = NULL;
1404         char *fpath = NULL;
1405         int sent_box = 0;
1406         char *mailbox_name = NULL;
1407         
1408         if (!account_id || !mail_id)  {
1409                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
1410                 err = EMF_ERROR_INVALID_PARAM;
1411                 goto FINISH_OFF;
1412         }
1413         
1414         if (!(ref_account = em_core_get_account_reference(account_id)))  {
1415                 EM_DEBUG_EXCEPTION("em_core_get_account_reference failed [%d]", account_id);
1416                 err = EMF_ERROR_INVALID_ACCOUNT;
1417                 goto FINISH_OFF;
1418         }
1419
1420         /*  get mail to send */
1421         if (!em_core_mail_get_mail(mail_id, &mail, &err))  {
1422                 EM_DEBUG_EXCEPTION("em_core_mail_get_mail failed [%d]", err);
1423                 goto FINISH_OFF;
1424         }
1425
1426         if (!em_core_check_send_mail_thread_status()) {
1427                 EM_DEBUG_EXCEPTION("em_core_check_send_mail_thread_status failed...");
1428                 err = EMF_ERROR_CANCELLED;
1429                 goto FINISH_OFF;
1430         }
1431
1432         if ((!mail->head->to) && (!mail->head->cc) && (!mail->head->bcc)) {
1433                 err = EMF_ERROR_NO_RECIPIENT;
1434                 EM_DEBUG_EXCEPTION("No Recipient information [%d]", err);
1435                 goto FINISH_OFF;
1436         }
1437         else {
1438                 if (!em_core_verify_email_address_of_mail_header(mail->head, false, &err)) {
1439                         err = EMF_ERROR_INVALID_ADDRESS;
1440                         EM_DEBUG_EXCEPTION("em_core_verify_email_address_of_mail_header failed [%d]", err);
1441                         goto FINISH_OFF;
1442                 }
1443         }
1444         
1445         if (mail->info)
1446                 mail->info->account_id = account_id;            
1447         
1448         if (!em_core_check_send_mail_thread_status()) {
1449                 EM_DEBUG_EXCEPTION("em_core_check_send_mail_thread_status failed...");
1450                 err = EMF_ERROR_CANCELLED;
1451                 goto FINISH_OFF;
1452         }
1453         
1454         if (sending_option != NULL)
1455                 opt = sending_option;
1456         else
1457                 opt = em_core_get_option(&err);
1458         
1459         
1460         /*Update status flag to DB*/
1461         
1462         /*  get rfc822 data */
1463         if (!em_core_mail_get_rfc822(mail, &envelope, &fpath, opt, &err))  {
1464                 EM_DEBUG_EXCEPTION("em_core_mail_get_rfc822 failed [%d]", err);
1465                 goto FINISH_OFF;
1466         }
1467         
1468         if (!envelope || (!envelope->to && !envelope->cc && !envelope->bcc))  {
1469                 EM_DEBUG_EXCEPTION(" no recipients found...");
1470                 
1471                 err = EMF_ERROR_NO_RECIPIENT;
1472                 goto FINISH_OFF;
1473         }
1474         
1475         /*  if there is no security option, unset security. */
1476         if (!ref_account->sending_security)  {
1477                 stls = (sslstart_t)mail_parameters(NULL, GET_SSLSTART, NULL);
1478                 mail_parameters(NULL, SET_SSLSTART, NULL);
1479         }
1480
1481         if (!em_core_check_send_mail_thread_status()) {
1482                 EM_DEBUG_EXCEPTION("em_core_check_send_mail_thread_status failed...");
1483                 err = EMF_ERROR_CANCELLED;
1484                 goto FINISH_OFF;
1485         }
1486         
1487         if (ref_account->pop_before_smtp != FALSE)  {
1488                 if (!em_core_mailbox_open(account_id, NULL, (void **)&tmp_stream, &err))  {
1489                         EM_DEBUG_EXCEPTION(" POP before SMTP Authentication failed [%d]", err);
1490                         status = EMF_LIST_CONNECTION_FAIL;
1491                         if (err == EMF_ERROR_CONNECTION_BROKEN)
1492                                 err = EMF_ERROR_CANCELLED;              
1493                         goto FINISH_OFF;
1494                 }
1495         }
1496
1497
1498         if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_DRAFT, &mailbox_name, false, &err))  {
1499                 EM_DEBUG_EXCEPTION(" em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1500                 err = em_storage_get_emf_error_from_em_storage_error(err);
1501                 goto FINISH_OFF;
1502         }
1503
1504         if (!em_core_mailbox_open(account_id, (char *)ENCODED_PATH_SMTP, (void **)&tmp_stream, &err))  {
1505                 EM_DEBUG_EXCEPTION(" em_core_mailbox_open failed [%d]", err);
1506                 
1507                 if (err == EMF_ERROR_CONNECTION_BROKEN)
1508                         err = EMF_ERROR_CANCELLED;
1509                 
1510                 status = EMF_SEND_CONNECTION_FAIL;
1511                 goto FINISH_OFF;
1512         }
1513         
1514         stream = (SENDSTREAM *)tmp_stream;
1515
1516         if (!em_core_check_send_mail_thread_status()) {
1517                 EM_DEBUG_EXCEPTION(" em_core_check_send_mail_thread_status failed...");
1518                 err = EMF_ERROR_CANCELLED;
1519                 goto FINISH_OFF;
1520         }
1521         
1522         /*  set request of delivery status. */
1523         if (opt->req_delivery_receipt == EMF_OPTION_REQ_DELIVERY_RECEIPT_ON)  { 
1524                 stream->protocol.esmtp.dsn.want = 1;
1525                 stream->protocol.esmtp.dsn.full = 0;
1526                 stream->protocol.esmtp.dsn.notify.failure = 1;
1527                 stream->protocol.esmtp.dsn.notify.success = 1;
1528                 EM_DEBUG_LOG("opt->req_delivery_receipt == EMF_OPTION_REQ_DELIVERY_RECEIPT_ON");
1529         }
1530         
1531         mail->info->extra_flags.status = EMF_MAIL_STATUS_SENDING;
1532
1533         /*Update status flag to DB*/
1534         if (!em_core_mail_modify_extra_flag(mail_id, mail->info->extra_flags, &err))
1535                 EM_DEBUG_EXCEPTION("Failed to modify extra flag [%d]", err);
1536
1537         /*  send mail to server. */
1538         if (!em_core_mail_send_smtp(stream, envelope, fpath, account_id, mail_id, &err)) {
1539                 EM_DEBUG_EXCEPTION(" em_core_mail_send_smtp failed [%d]", err);
1540
1541                 
1542 #ifndef __FEATURE_MOVE_TO_OUTBOX_FIRST__
1543         EM_SAFE_FREE(mailbox_name);
1544         if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_OUTBOX, &mailbox_name, false, &err))  {
1545                 EM_DEBUG_EXCEPTION(" em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1546                 err = em_storage_get_emf_error_from_em_storage_error(err);
1547                 goto FINISH_OFF;
1548         }
1549         dest_mbox.name = mailbox_name;
1550         dest_mbox.account_id = account_id;
1551                 
1552         /*  unsent mail is moved to 'OUTBOX'. */
1553         if (!em_core_mail_move(&mail_id, 1, dest_mbox.name, EMF_MOVED_BY_COMMAND, 0, NULL)) 
1554                 EM_DEBUG_EXCEPTION(" em_core_mail_move falied...");
1555 #endif
1556         
1557
1558                 goto FINISH_OFF;
1559         }
1560         
1561         /*  sent mail is moved to 'SENT' box or deleted. */
1562         if (opt->keep_local_copy)  {
1563                 EM_SAFE_FREE(mailbox_name);
1564                 
1565                 if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_SENTBOX, &mailbox_name, false, &err))  {
1566                         EM_DEBUG_EXCEPTION(" em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1567                         err = em_storage_get_emf_error_from_em_storage_error(err);
1568                         goto FINISH_OFF;
1569                 }
1570                 dest_mbox.name = mailbox_name;
1571                 dest_mbox.account_id = account_id;
1572                 
1573                 if (!em_core_mail_move(&mail_id, 1, dest_mbox.name, EMF_MOVED_AFTER_SENDING, 0, &err)) 
1574                         EM_DEBUG_EXCEPTION(" em_core_mail_move falied [%d]", err);
1575 #ifdef __FEATURE_SYNC_CLIENT_TO_SERVER__                
1576 #ifdef __LOCAL_ACTIVITY__               
1577                 else if (ref_account->receiving_server_type == EMF_SERVER_TYPE_IMAP4) /* To be synced to Sent box only IMAP not for POP */ {
1578
1579                         emf_activity_tbl_t new_activity;
1580                         int activityid = 0;
1581                         
1582                         if (false == em_core_get_next_activity_id(&activityid, &err)) {
1583                                 EM_DEBUG_EXCEPTION(" em_core_get_next_activity_id Failed [%d] ", err);
1584                         }
1585
1586                         memset(&new_activity, 0x00, sizeof(emf_activity_tbl_t));
1587                         new_activity.activity_id  =  activityid;
1588                         new_activity.server_mailid = NULL;
1589                         new_activity.account_id = account_id;
1590                         new_activity.mail_id    = mail_id;
1591                         new_activity.activity_type = ACTIVITY_SAVEMAIL;
1592                         new_activity.dest_mbox  = NULL;
1593                         new_activity.src_mbox   = NULL;
1594                 
1595                         if (!em_core_activity_add(&new_activity, &err)) {
1596                                 EM_DEBUG_EXCEPTION(" em_core_activity_add Failed [%d] ", err);
1597                         }
1598                         
1599                         if (!em_core_mail_move_from_server(dest_mbox.account_id, mailbox_name, &mail_id, 1, dest_mbox.name, &err)) {
1600                                 EM_DEBUG_EXCEPTION(" em_core_mail_move_from_server falied [%d]", err);
1601                         }
1602                         else {
1603                                 /* Remove ACTIVITY_SAVEMAIL activity */
1604                                 new_activity.activity_id  =  activityid;                                
1605                                 new_activity.activity_type = ACTIVITY_SAVEMAIL;
1606                                 new_activity.account_id = account_id;
1607                                 new_activity.mail_id    = mail_id;
1608                                 new_activity.dest_mbox  = NULL;
1609                                 new_activity.server_mailid = NULL;
1610                                 new_activity.src_mbox   = NULL;
1611                                 
1612                                 if (!em_core_activity_delete(&new_activity, &err)) {
1613                                         EM_DEBUG_EXCEPTION(">>>>>>Local Activity [ACTIVITY_SAVEMAIL] [%d] ", err);
1614                                 }
1615                         }
1616                         sent_box = 1;                   
1617                 }
1618 #endif
1619 #endif          
1620
1621                 /* On Successful Mail sent remove the Draft flag */
1622                 emf_mail_flag_t update_flag;
1623                 if (mail->info)
1624                         memcpy(&update_flag, &(mail->info->flags), sizeof(emf_mail_flag_t));
1625                 else
1626                         memset(&update_flag, 0x00, sizeof(emf_mail_flag_t));
1627                 update_flag.draft = 0;
1628                 int sticky_flag = 1;
1629                 if (!em_core_mail_modify_flag(mail_id, update_flag, sticky_flag, &err))
1630                         EM_DEBUG_EXCEPTION(" Flag Modification Failed [ %d] ", err);
1631                 sent_box = 1; 
1632         }
1633         else  {
1634                 if (!em_core_mail_delete(account_id, &mail_id, 1, 0, EMF_DELETED_AFTER_SENDING, false, &err)) 
1635                         EM_DEBUG_EXCEPTION(" em_core_mail_delete failed [%d]", err);
1636         }
1637         
1638         /*Update status flag to DB*/
1639                 mail->info->extra_flags.status = EMF_MAIL_STATUS_SENT;
1640         if (!em_core_mail_modify_extra_flag(mail_id, mail->info->extra_flags, &err))
1641                 EM_DEBUG_EXCEPTION("Failed to modify extra flag [%d]", err);
1642         /*Update status flag to DB*/
1643                 if (!em_core_delete_transaction_info_by_mailId(mail_id))
1644                         EM_DEBUG_EXCEPTION(" em_core_delete_transaction_info_by_mailId failed for mail_id[%d]", mail_id);
1645
1646         ret = true;
1647         
1648 FINISH_OFF: 
1649         if (ret == false && err != EMF_ERROR_INVALID_PARAM && mail)  {
1650                 if (err != EMF_ERROR_CANCELLED) {
1651                         mail->info->extra_flags.status = EMF_MAIL_STATUS_SEND_FAILURE;
1652                         if (!em_core_mail_modify_extra_flag(mail_id, mail->info->extra_flags, &err2))
1653                                 EM_DEBUG_EXCEPTION("Failed to modify extra flag [%d]", err2);
1654                 }
1655                 else {
1656                         if (EMF_MAIL_STATUS_SEND_CANCELED == mail->info->extra_flags.status)
1657                                 EM_DEBUG_LOG("EMF_MAIL_STATUS_SEND_CANCELED Already set for ");
1658                         else {  
1659                                 mail->info->extra_flags.status = EMF_MAIL_STATUS_SEND_CANCELED;
1660                                 if (!em_core_mail_modify_extra_flag(mail_id, mail->info->extra_flags, &err2))
1661                                         EM_DEBUG_EXCEPTION("Failed to modify extra flag [%d]", err2);
1662                         }
1663                 }
1664         }
1665
1666 #ifndef __FEATURE_KEEP_CONNECTION__
1667         if (stream) 
1668                 smtp_close(stream);
1669 #endif /* __FEATURE_KEEP_CONNECTION__ */
1670         if (stls) 
1671                 mail_parameters(NULL, SET_SSLSTART, (void  *)stls);
1672         if (mail) 
1673                 em_core_mail_free(&mail, 1, NULL);
1674         if (envelope) 
1675                 mail_free_envelope(&envelope);
1676         
1677         if (fpath) {
1678                 EM_DEBUG_LOG("REMOVE TEMP FILE  :  %s", fpath);
1679                 remove(fpath);
1680                 free(fpath);
1681         }
1682         
1683         if (ret == true) {
1684                 if (!em_storage_notify_network_event(NOTI_SEND_FINISH, account_id, NULL, mail_id, 0))
1685                         EM_DEBUG_EXCEPTION("em_storage_notify_network_event [NOTI_SEND_FINISH] Failed");
1686         }
1687         else {
1688                 if (!em_storage_notify_network_event(NOTI_SEND_FAIL, account_id, NULL, mail_id, err))
1689                         EM_DEBUG_EXCEPTION("em_storage_notify_network_event [NOTI_SEND_FAIL] Failed");
1690                 em_core_show_popup(mail_id, EMF_ACTION_SEND_MAIL, err);
1691         }
1692         
1693         EM_SAFE_FREE(mailbox_name);
1694         
1695         if (err_code != NULL)
1696                 *err_code = err;
1697         EM_PROFILE_END(profile_em_core_mail_send);
1698         EM_DEBUG_FUNC_END("ret [%d], err [%d]", ret, err);
1699         return ret;
1700 }
1701
1702 /*  send a saved message */
1703 EXPORT_API int em_core_mail_send_saved(int account_id, char *input_mailbox_name, emf_option_t *sending_option,  int *err_code)
1704 {
1705         EM_DEBUG_FUNC_BEGIN("account_id[%d], input_mailbox_name[%p], sending_option[%p], err_code[%p]", account_id, input_mailbox_name, sending_option, err_code);
1706         
1707         int ret = false;
1708         int err = EMF_ERROR_NONE;
1709         int status = EMF_SEND_FAIL;
1710         
1711         SENDSTREAM *stream = NULL;
1712         ENVELOPE *envelope = NULL;
1713         emf_mailbox_t   dest_mbox = {0};
1714         emf_mail_t *mail = NULL;
1715         emf_account_t *ref_account = NULL;
1716         emf_mail_tbl_t  mail_table_data = {0};
1717         emf_option_t *opt = NULL;
1718         sslstart_t      stls = NULL;
1719         void *tmp_stream = NULL;
1720         void *p = NULL;
1721         char *fpath = NULL;
1722         int mail_id = 0; 
1723         int handle = 0;
1724         int i = 0;
1725         int total = 0;
1726         char *mailbox_name = NULL;      
1727         
1728         if (!account_id || !input_mailbox_name)  {
1729                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
1730                 err = EMF_ERROR_INVALID_PARAM;
1731                 goto FINISH_OFF;
1732         }
1733         
1734         mail_send_notify(EMF_SEND_PREPARE, 0, 0, account_id, mail_id, err);
1735         
1736         if (!(ref_account = em_core_get_account_reference(account_id)))  {
1737                 EM_DEBUG_EXCEPTION("em_core_get_account_reference failed [%d]", account_id);
1738                 err = EMF_ERROR_INVALID_ACCOUNT;
1739                 goto FINISH_OFF;
1740         }
1741         
1742         FINISH_OFF_IF_CANCELED;
1743         
1744         if (sending_option)
1745                 opt = sending_option;
1746         else
1747                 opt = em_core_get_option(&err);
1748         
1749         /*  search mail. */
1750         if (!em_storage_mail_search_start(NULL, account_id, input_mailbox_name, 0, &handle, &total, true, &err))  {
1751                 EM_DEBUG_EXCEPTION("em_storage_mail_search_start failed [%d]", err);
1752                 err = em_storage_get_emf_error_from_em_storage_error(err);
1753                 goto FINISH_OFF;
1754         }
1755         
1756         while (i++ < total)  {
1757                 FINISH_OFF_IF_CANCELED;
1758                 
1759                 p = NULL;
1760                 if (!em_storage_mail_search_result(handle, RETRIEVE_ID, (void **)&p, true, &err))  {
1761                         EM_DEBUG_EXCEPTION("em_storage_mail_search_result failed [%d]", err);
1762                         err = em_storage_get_emf_error_from_em_storage_error(err);
1763                         goto FINISH_OFF;
1764                 }
1765                 
1766                 mail_id = (int)p;
1767                 
1768                 if (!em_core_mail_get_mail(mail_id, &mail, &err))  {
1769                         EM_DEBUG_EXCEPTION("em_core_mail_get_mail failed [%d]", err);
1770                         goto FINISH_OFF;
1771                 }
1772
1773                 /* check for email_address validation */
1774                 if (!em_core_verify_email_address_of_mail_header(mail->head, false, &err)) {
1775                         EM_DEBUG_EXCEPTION("em_core_verify_email_address_of_mail_header failed [%d]", err);
1776                         goto FINISH_OFF;
1777                 }
1778
1779                 /*  check that this mail was saved in offline-mode. */
1780                 if (mail->info->extra_flags.status != EMF_MAIL_STATUS_SAVED_OFFLINE)  {
1781                         EM_DEBUG_EXCEPTION(" mail was not saved in offline mode...");
1782                         em_core_mail_free(&mail, 1, &err); mail = NULL;
1783                         continue;
1784                 }
1785                 
1786                 if(!em_convert_mail_flag_to_mail_tbl(&(mail->info->flags), &mail_table_data, &err)) {
1787                         EM_DEBUG_EXCEPTION("em_convert_mail_flag_to_mail_tbl failed [%d]", err);
1788                         goto FINISH_OFF;
1789                 }
1790                 
1791                 mail_table_data.save_status = mail->info->extra_flags.status;
1792                 mail_table_data.lock_status = mail->info->extra_flags.lock;
1793                 mail_table_data.priority = mail->info->extra_flags.priority;
1794                 mail_table_data.report_status = mail->info->extra_flags.report;
1795                 
1796                 mail->info->extra_flags.status = EMF_MAIL_STATUS_SENDING;
1797                 
1798                 if (!em_core_mail_get_rfc822(mail, &envelope, &fpath, opt, &err))  {
1799                         EM_DEBUG_EXCEPTION("em_core_mail_get_rfc822 falied [%d]", err);
1800                         goto FINISH_OFF;
1801                 }
1802                 
1803                 FINISH_OFF_IF_CANCELED;
1804                 
1805                 /*  connect mail server. */
1806                 if (!stream) {
1807                         /*  if there no security option, unset security. */
1808                         if (!ref_account->sending_security) {
1809                                 stls = (sslstart_t)mail_parameters(NULL, GET_SSLSTART, NULL);
1810                                 mail_parameters(NULL, SET_SSLSTART, NULL);
1811                         }
1812                         
1813                         stream = NULL;
1814                         if (!em_core_mailbox_open(account_id, (char *)ENCODED_PATH_SMTP, &tmp_stream, &err) || !tmp_stream)  {
1815                                 EM_DEBUG_EXCEPTION("em_core_mailbox_open failed [%d]", err);
1816
1817                                 if (err == EMF_ERROR_CONNECTION_BROKEN)
1818                                         err = EMF_ERROR_CANCELLED;
1819                                 
1820                                 status = EMF_SEND_CONNECTION_FAIL;
1821                                 goto FINISH_OFF;
1822                         }
1823                         
1824                         stream = (SENDSTREAM *)tmp_stream;
1825                         
1826                         FINISH_OFF_IF_CANCELED;
1827                         
1828                         mail_send_notify(EMF_SEND_CONNECTION_SUCCEED, 0, 0, account_id, mail_id, err);
1829                         
1830                         /*  reqest of delivery status. */
1831                         if (opt && opt->req_delivery_receipt == EMF_OPTION_REQ_DELIVERY_RECEIPT_ON)  { 
1832                                 stream->protocol.esmtp.dsn.want = 1;
1833                                 stream->protocol.esmtp.dsn.full = 0;
1834                                 stream->protocol.esmtp.dsn.notify.failure = 1;
1835                                 stream->protocol.esmtp.dsn.notify.success = 1;
1836                         }
1837                         
1838                         mail_send_notify(EMF_SEND_START, 0, 0, account_id, mail_id, err);
1839                 }
1840                 
1841                 mail_table_data.save_status = EMF_MAIL_STATUS_SENDING;
1842                 
1843                 /*  update mail status to sending. */
1844                 if (!em_storage_change_mail_field(mail_id, UPDATE_EXTRA_FLAG, &mail_table_data, true, &err))  {
1845                         EM_DEBUG_EXCEPTION("em_storage_change_mail_field failed [%d]", err);
1846                         err = em_storage_get_emf_error_from_em_storage_error(err);
1847                         goto FINISH_OFF;
1848                 }
1849                 
1850                 if (!em_core_mail_send_smtp(stream, envelope, fpath, account_id, mail_id, &err))  {
1851                         EM_DEBUG_EXCEPTION("em_core_mail_send_smtp failed [%d]", err);
1852                         
1853                         mail_table_data.save_status = EMF_MAIL_STATUS_SEND_FAILURE;
1854                         
1855                         /*  update mail status to failure. */
1856                         if (!em_storage_change_mail_field(mail_id, UPDATE_EXTRA_FLAG, &mail_table_data, true, &err)) 
1857                                 EM_DEBUG_EXCEPTION("em_storage_change_mail_field failed [%d]", err);
1858                                                 
1859                         if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_OUTBOX, &mailbox_name, false, &err))  {
1860                                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1861                                 err = em_storage_get_emf_error_from_em_storage_error(err);
1862                                 goto FINISH_OFF;
1863                         }       
1864                         dest_mbox.name = mailbox_name;
1865                         dest_mbox.account_id = account_id;
1866                         
1867                         em_core_mail_move(&mail_id, 1, dest_mbox.name, EMF_MOVED_AFTER_SENDING, 0, NULL);
1868                         
1869                         goto FINISH_OFF;
1870                 }
1871                 
1872                 mail_table_data.save_status = EMF_MAIL_STATUS_SENT;
1873                 
1874                 /*  update mail status to sent mail. */
1875                 if (!em_storage_change_mail_field(mail_id, UPDATE_EXTRA_FLAG, &mail_table_data, true, &err))  {
1876                         EM_DEBUG_EXCEPTION("em_storage_change_mail_field failed [%d]", err);
1877                         err = em_storage_get_emf_error_from_em_storage_error(err);
1878                         goto FINISH_OFF;
1879                 }
1880                 
1881                 /*  sent mail is moved to 'SENT' box or deleted. */
1882                 if (opt->keep_local_copy)  {
1883                         EM_SAFE_FREE(mailbox_name);
1884                         if (!em_storage_get_mailboxname_by_mailbox_type(account_id, EMF_MAILBOX_TYPE_SENTBOX, &mailbox_name, false, &err))  {
1885                                 EM_DEBUG_EXCEPTION("em_storage_get_mailboxname_by_mailbox_type failed [%d]", err);
1886                                 err = em_storage_get_emf_error_from_em_storage_error(err);
1887                                 goto FINISH_OFF;
1888                         }       
1889                         dest_mbox.name = mailbox_name;
1890                         dest_mbox.account_id = account_id;
1891                         
1892                         if (!em_core_mail_move(&mail_id, 1, dest_mbox.name, EMF_MOVED_AFTER_SENDING, 0, &err)) 
1893                                 EM_DEBUG_EXCEPTION("em_core_mail_move falied [%d]", err);
1894                 }
1895                 else  {
1896                         if (!em_core_mail_delete(account_id, &mail_id, 1, 0, EMF_DELETED_AFTER_SENDING, false, &err)) 
1897                                 EM_DEBUG_EXCEPTION("em_core_mail_delete falied [%d]", err);
1898                 }
1899                 
1900                 em_core_mail_free(&mail, 1, NULL); mail = NULL;
1901                 mail_free_envelope(&envelope); envelope = NULL;
1902                 
1903                 if (fpath)  {
1904                         remove(fpath);
1905                         EM_SAFE_FREE(fpath);
1906                 }
1907         }
1908         
1909         
1910         ret = true;
1911
1912 FINISH_OFF: 
1913         if (stream) 
1914                 smtp_close(stream);
1915
1916         if (stls) 
1917                 mail_parameters(NIL, SET_SSLSTART, (void  *)stls);
1918
1919         if (envelope) 
1920                 mail_free_envelope(&envelope);
1921
1922         if (handle)  {
1923                 if (!em_storage_mail_search_end(handle, true, &err))
1924                         EM_DEBUG_EXCEPTION("em_storage_mail_search_end failed [%d]", err);
1925         }
1926
1927         if (mail) 
1928                 em_core_mail_free(&mail, 1, NULL);
1929
1930         if (fpath)  {
1931                 remove(fpath);
1932                 EM_SAFE_FREE(fpath);
1933         }
1934
1935         EM_SAFE_FREE(mailbox_name);
1936
1937         if (ret == true) 
1938                 mail_send_notify(EMF_SEND_FINISH, 0, 0, account_id, mail_id, err);
1939         else {
1940                 mail_send_notify(status, 0, 0, account_id, mail_id, err);
1941                 em_core_show_popup(account_id, EMF_ACTION_SEND_MAIL, err);
1942         }
1943         
1944         if (err_code != NULL)
1945                 *err_code = err;
1946         
1947         return ret;
1948 }       
1949
1950 static int em_core_mail_send_smtp(SENDSTREAM *stream, ENVELOPE *env, char *data_file, int account_id, int mail_id, int *err_code)
1951 {
1952         EM_DEBUG_FUNC_BEGIN("stream[%p], env[%p], data_file[%s], account_id[%d], mail_id[%d], err_code[%p]", stream, env, data_file, account_id, mail_id, err_code);
1953         EM_PROFILE_BEGIN(profile_em_core_mail_send_smtp);
1954         
1955         int ret = false;
1956         int err = EMF_ERROR_NONE;
1957         int recipients = 0;
1958         long total = 0, sent = 0, send_ret = 0, send_err = 0, sent_percent = 0, last_sent_percent = 0;
1959         char buf[2048] = { 0, };
1960         emf_account_t *ref_account = NULL;
1961         FILE *fp = NULL;
1962         
1963         if (!env || !env->from || (!env->to && !env->cc && !env->bcc)) {
1964                 if (env != NULL)
1965                         EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
1966                 err = EMF_ERROR_INVALID_PARAM;
1967                 goto FINISH_OFF;
1968         }
1969         
1970         if (!env->from->mailbox || !env->from->host) {
1971                 EM_DEBUG_EXCEPTION("env->from->mailbox[%p], env->from->host[%p]", env->from->mailbox, env->from->host);
1972                 err = EMF_ERROR_INVALID_PARAM;
1973                 goto FINISH_OFF;
1974         }
1975         
1976         if (!(ref_account = em_core_get_account_reference(account_id))) {
1977                 EM_DEBUG_EXCEPTION("em_core_get_account_reference failed [%d]", account_id);
1978                 err = EMF_ERROR_INVALID_ACCOUNT;
1979                 goto FINISH_OFF;
1980         }
1981
1982         EM_DEBUG_LOG("Modifying - MAIL FROM ");
1983         if (ref_account->email_addr == NULL) {
1984                 EM_DEBUG_LOG("ref_account->email_addr is null!!");
1985                 SNPRINTF(buf, sizeof(buf), "FROM:<%s@%s>", env->from->mailbox, env->from->host);
1986         }
1987         else
1988                 SNPRINTF(buf, sizeof(buf), "FROM:<%s>", ref_account->email_addr);
1989         
1990         /*  set DSN for ESMTP */
1991         if (stream->protocol.esmtp.ok) {
1992                 if (stream->protocol.esmtp.eightbit.ok && stream->protocol.esmtp.eightbit.want)
1993                         strncat (buf, " BODY=8BITMIME", sizeof(buf)-(strlen(buf)+1));
1994                 
1995                 if (stream->protocol.esmtp.dsn.ok && stream->protocol.esmtp.dsn.want) {
1996                         EM_DEBUG_LOG("stream->protocol.esmtp.dsn.want is required");
1997                         strncat (buf, stream->protocol.esmtp.dsn.full ? " RET=FULL" : " RET=HDRS", sizeof(buf)-strlen(buf)-1);
1998                         if (stream->protocol.esmtp.dsn.envid) 
1999                                 SNPRINTF (buf + strlen (buf), sizeof(buf)-(strlen(buf)), " ENVID=%.100s", stream->protocol.esmtp.dsn.envid);
2000                 }
2001                 else
2002                         EM_DEBUG_LOG("stream->protocol.esmtp.dsn.want is not required");
2003         }
2004         
2005         EM_PROFILE_BEGIN(profile_prepare_and_head);
2006         send_ret = smtp_send(stream, "RSET", 0);
2007         EM_DEBUG_LOG("[SMTP] RSET --------> %s", stream->reply);
2008         
2009         if (send_ret != SMTP_RESPONSE_OK) {
2010                 err = send_ret;
2011                 goto FINISH_OFF;
2012         }
2013         
2014         send_ret = smtp_send(stream, "MAIL", buf);
2015         EM_DEBUG_LOG("[SMTP] MAIL %s --------> %s", buf, stream->reply);
2016         
2017         switch (send_ret) {
2018                 case SMTP_RESPONSE_OK:
2019                         break;
2020                 
2021                 case SMTP_RESPONSE_WANT_AUTH  :
2022                 case SMTP_RESPONSE_WANT_AUTH2:
2023                         EM_DEBUG_EXCEPTION("SMTP error :  authentication required...");
2024                         err = EMF_ERROR_AUTHENTICATE;
2025                         goto FINISH_OFF;
2026                 
2027                 case SMTP_RESPONSE_UNAVAIL:
2028                         EM_DEBUG_EXCEPTION("SMTP error :  mailbox unavailable...");
2029                         err = EMF_ERROR_MAILBOX_FAILURE;
2030                         goto FINISH_OFF;
2031                 
2032                 default: 
2033                         err = send_ret;
2034                         goto FINISH_OFF;
2035         }
2036         
2037         if (env->to) {
2038                 send_ret = smtp_rcpt(stream, env->to, &send_err);
2039                 EM_DEBUG_LOG("[SMTP] RCPT TO : <%s@%s> ... --------> %s", env->to->mailbox, env->to->host, env->to->error ? env->to->error  :  stream->reply);
2040                 if (send_ret) {
2041                         err = stream->replycode;
2042                         goto FINISH_OFF;
2043                 }
2044                 
2045                 if (!send_err)
2046                         recipients++;
2047         }
2048         
2049         if (env->cc) {
2050                 send_ret = smtp_rcpt(stream, env->cc, &send_err);
2051                 EM_DEBUG_LOG("[SMTP] RCPT TO : <%s@%s> ... --------> %s", env->cc->mailbox, env->cc->host, env->cc->error ? env->cc->error  :  stream->reply);
2052                 if (send_ret) {
2053                         err = stream->replycode;
2054                         goto FINISH_OFF;
2055                 }
2056                 
2057                 if (!send_err)
2058                         recipients++;
2059         }
2060         
2061         if (env->bcc) {
2062                 send_ret = smtp_rcpt(stream, env->bcc, &send_err);
2063                 EM_DEBUG_LOG("[SMTP] RCPT TO : <%s@%s> ... --------> %s", env->bcc->mailbox, env->bcc->host, env->bcc->error ? env->bcc->error  :  stream->reply);
2064                 if (send_ret) {
2065                         err = stream->replycode;
2066                         goto FINISH_OFF;
2067                 }
2068                 
2069                 if (!send_err)
2070                         recipients++;
2071         }
2072         
2073         
2074         if (send_err) {
2075                 EM_DEBUG_EXCEPTION("One or more recipients failed...");
2076                 err = EMF_ERROR_INVALID_ADDRESS;
2077         }
2078         
2079         if (!recipients) {
2080                 EM_DEBUG_EXCEPTION("No valid recipients...");
2081                 
2082                 switch (stream->replycode) {
2083                         case SMTP_RESPONSE_UNAVAIL: 
2084                         case SMTP_RESPONSE_WANT_AUTH  : 
2085                         case SMTP_RESPONSE_WANT_AUTH2: 
2086                                 err = EMF_ERROR_AUTH_REQUIRED;
2087                                 break;
2088                         
2089                         default: 
2090                                 err = EMF_ERROR_INVALID_ADDRESS;
2091                                 break;
2092                 }
2093                 goto FINISH_OFF;
2094         }
2095         
2096         send_ret = smtp_send(stream, "DATA", 0);
2097         EM_DEBUG_LOG("[SMTP] DATA --------> %s", stream->reply);
2098         EM_PROFILE_END(profile_prepare_and_head);       
2099
2100         if (send_ret != SMTP_RESPONSE_READY) {
2101                 err = send_ret;
2102                 goto FINISH_OFF;
2103         }
2104         
2105         if (data_file) {
2106                 EM_PROFILE_BEGIN(profile_open_file);
2107                 if (!(fp = fopen(data_file, "r+"))) {
2108                         EM_DEBUG_EXCEPTION("fopen(\"%s\") failed...", data_file);
2109                         err = EMF_ERROR_SYSTEM_FAILURE;
2110                         goto FINISH_OFF;
2111                 }
2112                 EM_PROFILE_END(profile_open_file);
2113                 
2114
2115 #ifdef __FEATURE_SEND_OPTMIZATION__  
2116         {
2117                 char *data = NULL;
2118                 int read_size, allocSize, dataSize, gMaxAllocSize = 40960; /*  40KB */
2119                 
2120                 fseek(fp, 0, SEEK_END);
2121                 total = ftell(fp);
2122                 fseek(fp, 0, SEEK_SET);
2123                 EM_DEBUG_LOG("total size [%d]", total);
2124
2125                 if (total < gMaxAllocSize)
2126                         allocSize = total + 1;
2127                 else
2128                         allocSize = gMaxAllocSize;
2129
2130                 EM_PROFILE_BEGIN(profile_allocation);
2131                 /* Allocate a buffer of max 2MB to read from file */
2132                 data = (char *)em_core_malloc(allocSize);               
2133                 allocSize--;
2134                 EM_PROFILE_END(profile_allocation);
2135
2136                 if (NULL == data) {
2137                         err = EMF_ERROR_SMTP_SEND_FAILURE;
2138                         goto FINISH_OFF;
2139                 }
2140
2141                 while (total) {
2142                         if (total  < allocSize)
2143                                 dataSize = total;
2144                         else
2145                                 dataSize = allocSize;
2146                         
2147                         memset(data, 0x0, dataSize+1);
2148                         read_size = fread(data, sizeof (char), dataSize, fp);
2149                                         
2150                         if (read_size != dataSize) {   
2151                                 /* read fail. */
2152                                 EM_SAFE_FREE(data);
2153                                 EM_DEBUG_EXCEPTION("Read from file failed");
2154                                 err = EMF_ERROR_SMTP_SEND_FAILURE;
2155                                 goto FINISH_OFF;
2156                         }
2157                         sent += read_size;
2158
2159                         EM_DEBUG_LOG("before smtp_soutr_test");
2160                         if (!(send_ret = smtp_soutr_test(stream->netstream, data))) {
2161                                 EM_SAFE_FREE(data);
2162                                 EM_DEBUG_EXCEPTION("Failed to send the data ");
2163                                 err = EMF_ERROR_SMTP_SEND_FAILURE;
2164                                 goto FINISH_OFF;
2165                         }               
2166                         else {
2167                                 sent_percent = (int) ((double)sent / (double)total * 100.0);
2168                                 if (last_sent_percent + 5 <= sent_percent) {
2169                                         if (!em_storage_notify_network_event(NOTI_SEND_START, account_id, NULL, mail_id, sent_percent))
2170                                                 EM_DEBUG_EXCEPTION("em_storage_notify_network_event [NOTI_SEND_START] Failed >>>>");
2171                                         last_sent_percent = sent_percent;
2172                                 }
2173                                 EM_DEBUG_LOG("Sent data Successfully. sent[%d] total[%d]", sent, total);
2174                         }
2175                         total -= dataSize;
2176                 }
2177
2178                 EM_SAFE_FREE(data);
2179         }
2180 #else
2181                 fseek(fp, 0, SEEK_END);
2182                 total = ftell(fp);
2183                 fseek(fp, 0, SEEK_SET);
2184                 
2185                 while (fgets(buf, 1024, fp)) {
2186 #ifdef FEATURE_SEND_DATA_DEBUG
2187                         EM_DEBUG_LOG("%s", buf);
2188 #endif
2189                         sent += strlen(buf);
2190                         
2191                         if (!(send_ret = smtp_soutr(stream->netstream, buf))) 
2192                                 break;
2193                         /*  Sending Progress Notification */
2194                         sent_percent = (int) ((double)sent / (double)total * 100.0);
2195                         if (last_sent_percent + 5 <= sent_percent) {
2196                                 /* Disabled Temporary
2197                                 if (!em_storage_notify_network_event(NOTI_SEND_START, account_id, NULL, mail_id, sent_percent))
2198                                         EM_DEBUG_EXCEPTION(" em_storage_notify_network_event [NOTI_SEND_START] Failed >>>>");
2199                                 */
2200                                 last_sent_percent = sent_percent;
2201                         }
2202                 }
2203                 
2204 #endif
2205                 if (!send_ret) {
2206                         EM_DEBUG_EXCEPTION("smtp_soutr failed - %ld", send_ret);
2207                         err = EMF_ERROR_SMTP_SEND_FAILURE;
2208                         goto FINISH_OFF;
2209                 }
2210         }
2211         
2212         send_ret = smtp_send(stream, ".", 0);
2213         EM_DEBUG_LOG("[SMTP] . --------> %s", stream->reply);
2214         
2215         if (send_ret != SMTP_RESPONSE_OK) {
2216                 err = send_ret;
2217                 goto FINISH_OFF;
2218         }
2219         
2220         ret = true;
2221         
2222 FINISH_OFF: 
2223         if (ret == false)
2224                 smtp_send(stream, "RSET", 0);
2225         
2226         if (err_code)
2227                 *err_code = err;
2228         
2229         if (fp)
2230                 fclose(fp); 
2231         EM_PROFILE_END(profile_em_core_mail_send_smtp);
2232         EM_DEBUG_FUNC_END("ret [%d]", ret);
2233         return ret;
2234 }
2235
2236 /* ------ rfc822 handle --------------------------------------------------- */
2237 #define RANDOM_NUMBER_LENGTH 35
2238
2239 char *em_core_generate_content_id_string(const char *hostname, int *err)
2240 {
2241         EM_DEBUG_FUNC_BEGIN("hostname[%p]", hostname);
2242
2243         if (!hostname) {
2244                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
2245                 if (err)
2246                         *err = EMF_ERROR_INVALID_PARAM;
2247                 return NULL;
2248         }
2249         
2250         int cid_length = RANDOM_NUMBER_LENGTH + strlen(hostname) + 2, random_number_1, random_number_2, random_number_3, random_number_4;
2251         char *cid_string = NULL;
2252
2253         cid_string = malloc(cid_length);
2254
2255         if (!cid_string) {
2256                 if (err)
2257                         *err = EMF_ERROR_OUT_OF_MEMORY;
2258                 return NULL;
2259         }
2260
2261         memset(cid_string, 0, cid_length);
2262
2263         srand(time(NULL) + rand());
2264         random_number_1 = rand() * rand();
2265         random_number_2 = rand() * rand();
2266         random_number_3 = rand() * rand();
2267         random_number_4 = rand() * rand();
2268
2269         SNPRINTF(cid_string, cid_length, "<%08x%08x%08x%08x@%s>", random_number_1, random_number_2, random_number_3, random_number_4, hostname);
2270         
2271         if (err)
2272                 *err = EMF_ERROR_NONE;
2273
2274         EM_DEBUG_FUNC_END("cid_string [%s]", cid_string);
2275         return cid_string;
2276 }
2277
2278
2279 /* ------ attach_part ----------------------------------------------------- */
2280 /*  data  :  if filename NULL, content data. */
2281 /*              else absolute path of file to be attached. */
2282 /*  data_len  :  length of data. if filename not NULL, ignored. */
2283 /*  file_name :  attahcment name. */
2284 static int attach_part(BODY *body, const unsigned char *data, int data_len, char *filename, char *content_sub_type, int is_inline, int *err_code)
2285 {
2286         EM_DEBUG_FUNC_BEGIN("body[%p], data[%s], data_len[%d], filename[%s], content_sub_type[%s], err_code[%p]", body, data, data_len, filename, content_sub_type, err_code);
2287         
2288         int        ret = false;
2289         int        error = EMF_ERROR_NONE;
2290         int        has_special_character = 0;
2291         int        base64_file_name_length = 0;
2292         int        i= 0;
2293         gsize      bytes_read;
2294         gsize      bytes_written;
2295         char      *encoded_file_name = NULL;
2296         char      *extension = NULL;
2297         char      *base64_file_name = NULL;
2298         char      *result_file_name = NULL;
2299         char       content_disposition[100] = { 0, };
2300         PARAMETER *last_param = NULL;
2301         PARAMETER *param = NULL;
2302         PART      *last_part = NULL;
2303         PART      *part = NULL;
2304         SIZEDTEXT  source_text;
2305         GError    *glib_error = NULL;
2306         CHARSET   *result_charset = NULL;
2307         
2308         if (!body)  {
2309                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
2310                 error = EMF_ERROR_INVALID_PARAM;
2311                 goto FINISH_OFF;
2312         }
2313         
2314         if (body->nested.part)  {
2315                 last_part = body->nested.part;
2316                 
2317                 if (last_part != NULL)  {
2318                         while (last_part->next)
2319                                 last_part = last_part->next;
2320                 }
2321         }
2322         
2323         /*  PART */
2324         part = mail_newbody_part();
2325         if (part == NULL)  {
2326                 EM_DEBUG_EXCEPTION("mail_newbody_part failed...");
2327                 error = EMF_ERROR_OUT_OF_MEMORY;
2328                 goto FINISH_OFF;
2329         }
2330         
2331         part->next = NULL;
2332         
2333         if (last_part)  
2334                 last_part->next = part;
2335         else 
2336                 body->nested.part = part;
2337         
2338         last_part = part;
2339         
2340         /* set data..  */
2341         /* content_data = (unsigned char  *)fs_get(data_len + 1); */
2342         /* memcpy(content_data, data, data_len); */
2343         /* content_data[data_len] = 0; */
2344         
2345         /* part->body.contents.text.data = content_data; */
2346         /* part->body.contents.text.size = data_len; */
2347         
2348         if (filename)  {   /*  attachment */
2349                 source_text.data = (unsigned char*)filename; 
2350                 source_text.size = strlen(filename);
2351
2352                 result_charset   = (CHARSET*)utf8_infercharset(&source_text);
2353
2354                 if(result_charset) {
2355                         EM_DEBUG_LOG("return_charset->name [%s]", result_charset->name);
2356                         encoded_file_name = (char*)g_convert (filename, -1, "UTF-8", result_charset->name, &bytes_read, &bytes_written, &glib_error);
2357                 }
2358                 else {
2359                         i = 0;
2360                         while(filename[i]) {
2361                                 if(filename[i++] & 0x80) {
2362                                         has_special_character = 1;
2363                                         break;
2364                                 }
2365                         }
2366                         EM_DEBUG_LOG("has_special_character [%d]", has_special_character);
2367                         if(has_special_character)
2368                                 encoded_file_name = (char*)g_convert (filename, -1, "UTF-8", "EUC-KR", &bytes_read, &bytes_written, &glib_error);
2369                 }
2370                 
2371                 EM_DEBUG_LOG("encoded_file_name [%s]", encoded_file_name);
2372
2373                 if(encoded_file_name == NULL)
2374                         encoded_file_name = strdup(filename);
2375
2376                 if(!em_core_encode_base64(encoded_file_name, strlen(encoded_file_name), &base64_file_name, (unsigned long*)&base64_file_name_length, &error)) {
2377                         EM_DEBUG_EXCEPTION("em_core_encode_base64 failed. error [%d]", error);
2378                         goto FINISH_OFF;
2379                 }
2380                 
2381                 result_file_name = em_core_replace_string(base64_file_name, "\015\012", "");
2382                 
2383                 EM_DEBUG_LOG("base64_file_name_length [%d]", base64_file_name_length);
2384                 
2385                 if(result_file_name) {
2386                         EM_SAFE_FREE(encoded_file_name);
2387                         encoded_file_name = em_core_malloc(strlen(result_file_name) + 15);
2388                         if(!encoded_file_name) {
2389                                 EM_DEBUG_EXCEPTION("em_core_malloc failed.");
2390                                 goto FINISH_OFF;
2391                         }
2392                         snprintf(encoded_file_name, strlen(result_file_name) + 15, "=?UTF-8?B?%s?=", result_file_name);
2393                         EM_DEBUG_LOG("encoded_file_name [%s]", encoded_file_name);
2394                 }
2395
2396                 extension = em_core_get_extension_from_file_path(filename, NULL);
2397
2398                 part->body.type = em_core_get_content_type(extension, NULL);
2399                 if(part->body.type == TYPEIMAGE)
2400                         part->body.subtype = strdup(extension);
2401                 else
2402                         part->body.subtype = cpystr("octet-stream");
2403
2404                 part->body.encoding = ENCBINARY;
2405                 part->body.size.bytes = data_len;
2406
2407                 if (data)
2408                         part->body.sparep = EM_SAFE_STRDUP((char *)data); /*  file path */
2409                 else
2410                         part->body.sparep = NULL;       
2411                 
2412                 SNPRINTF(content_disposition, sizeof(content_disposition), "%s", "attachment");
2413                 
2414                 part->body.disposition.type = cpystr(content_disposition);
2415                 
2416                 /*  BODY PARAMETER */
2417                 /*  another parameter or get parameter-list from this   function-parameter */
2418                 param = mail_newbody_parameter();
2419                 if (param == NULL)  {
2420                         EM_DEBUG_EXCEPTION("mail_newbody_parameter failed...");
2421                         error = EMF_ERROR_OUT_OF_MEMORY;
2422                         goto FINISH_OFF;
2423                 }
2424                 
2425                 param->attribute          = cpystr("name");
2426                 param->value              = cpystr(encoded_file_name);
2427                 param->next               = NULL;
2428                 last_param                = param;
2429                 last_part->body.parameter = last_param;
2430
2431                 if (is_inline) {        
2432                         /*  CONTENT-ID */
2433                         part->body.id = em_core_generate_content_id_string("com.samsung.slp.email", &error);
2434                         part->body.type = TYPEIMAGE;
2435                         /*  EM_SAFE_FREE(part->body.subtype); */
2436                         /*  part->body.subtype = EM_SAFE_STRDUP(content_sub_type); */
2437                 }
2438
2439                 /*  DISPOSITION PARAMETER */
2440                 param = mail_newbody_parameter();
2441                 if (param == NULL)  {
2442                         EM_DEBUG_EXCEPTION("mail_newbody_parameter failed...");
2443                         error = EMF_ERROR_OUT_OF_MEMORY;
2444                         goto FINISH_OFF;
2445                 }
2446                 
2447                 param->attribute                      = cpystr("filename");
2448                 param->value                          = cpystr(encoded_file_name);
2449                 param->next                           = NULL;
2450                 last_param                            = param;
2451                 last_part->body.disposition.parameter = last_param;
2452                 
2453                 if (is_inline)
2454                         last_part->body.disposition.type = EM_SAFE_STRDUP("inline");
2455         }
2456         else  {   
2457                 /*  text body (plain/html) */
2458                 part->body.type = TYPETEXT;
2459                 
2460                 part->body.size.bytes = data_len;
2461                 if (data)
2462                         part->body.sparep = EM_SAFE_STRDUP((char *)data); /*  file path */
2463                 else
2464                         part->body.sparep = NULL;
2465
2466                 
2467                 if (!content_sub_type)  {
2468                         /* Plain text body */
2469                         part->body.encoding = ENC8BIT; 
2470                         part->body.subtype = cpystr("plain");
2471                         last_param = part->body.parameter;
2472                         
2473                         if (last_param != NULL)  {
2474                                 while (last_param->next)
2475                                         last_param = last_param->next;
2476                         }
2477                         
2478                         param = mail_newbody_parameter();
2479                         
2480                         if (param == NULL)  {
2481                                 EM_DEBUG_EXCEPTION("mail_newbody_parameter failed...");
2482                                 error = EMF_ERROR_OUT_OF_MEMORY;
2483                                 goto FINISH_OFF;
2484                         }
2485                         
2486                         param->attribute = cpystr("CHARSET");
2487
2488                         if (data != NULL) {
2489                                 gchar *extract_charset_plain = g_path_get_basename((const gchar *)data);
2490                                 if (extract_charset_plain != NULL && extract_charset_plain[0] != '\0')
2491                                         param->value = cpystr(extract_charset_plain);
2492                                 g_free(extract_charset_plain);
2493                         }
2494                         else    
2495                                 param->value = cpystr("UTF-8");
2496
2497                         if(!param->value)
2498                                 param->value = cpystr("UTF-8");
2499
2500                         param->next = NULL;
2501                         
2502                         if (last_param != NULL)
2503                                 last_param->next = param;
2504                         else
2505                                 part->body.parameter = param;
2506                 }
2507                 else {
2508                         /* HTML text body */
2509                         part->body.encoding = ENC8BIT;  
2510                         part->body.subtype  = cpystr(content_sub_type);
2511
2512                         last_param = part->body.parameter;
2513                         
2514                         if (last_param != NULL)  {
2515                                 while (last_param->next)
2516                                         last_param = last_param->next;
2517                         }
2518                         
2519                         param = mail_newbody_parameter();
2520                         
2521                         if (param == NULL)  {
2522                                 EM_DEBUG_EXCEPTION("mail_newbody_parameter failed...");
2523                                 error = EMF_ERROR_OUT_OF_MEMORY;
2524                                 goto FINISH_OFF;
2525                         }
2526                         
2527                         param->attribute = cpystr("CHARSET");
2528                         
2529                         char *pHtml = NULL;
2530                         if (data != NULL) {
2531                                 gchar *extract_charset = g_path_get_basename((const gchar *)data);
2532                                 if (extract_charset != NULL) {
2533                                         if ((pHtml = strstr(extract_charset, ".htm")) != NULL) {
2534                                                 extract_charset[pHtml-extract_charset] = '\0';
2535                                                 param->value = cpystr(extract_charset);
2536                                         }
2537                                 }
2538                                 
2539                                 if(!param->value)
2540                                         param->value = cpystr("UTF-8");
2541
2542                                 EM_SAFE_FREE(extract_charset);
2543                         }
2544                         else
2545                                 param->value = cpystr("UTF-8");
2546                         param->next = NULL;
2547                         
2548                         if (last_param != NULL)
2549                                 last_param->next = param;
2550                         else
2551                                 part->body.parameter = param;
2552                 }
2553                 
2554                 /* NOTE : need to require this code. */
2555                 /* sprintf(content_disposition, "%s\0", "inline"); */
2556                 if (is_inline) {
2557                         SNPRINTF(content_disposition, sizeof(content_disposition), "%s", "inline");
2558                         part->body.disposition.type = cpystr(content_disposition);
2559                 }
2560         }
2561         
2562         ret = true;
2563         
2564 FINISH_OFF: 
2565         EM_SAFE_FREE(encoded_file_name);
2566         EM_SAFE_FREE(base64_file_name); 
2567         if (err_code != NULL)
2568                 *err_code = error;
2569         EM_DEBUG_FUNC_END();
2570         return ret;
2571 }
2572
2573 static PART *attach_mutipart_with_sub_type(BODY *parent_body, char *sub_type, int *err_code)
2574 {
2575         EM_DEBUG_FUNC_BEGIN("parent_body[%p], sub_type [%s], err_code[%p]", parent_body, sub_type, err_code);
2576         
2577         int error = EMF_ERROR_NONE;
2578         
2579         PART *tail_part_cur = NULL;
2580         PART *new_part = NULL;
2581         
2582         if (!parent_body || !sub_type)  {
2583                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
2584                 error = EMF_ERROR_INVALID_PARAM;
2585                 goto FINISH_OFF;
2586         }
2587         
2588         if (parent_body->nested.part)  {
2589                 tail_part_cur = parent_body->nested.part;
2590                 
2591                 if (tail_part_cur != NULL)  {
2592                         while (tail_part_cur->next)
2593                                 tail_part_cur = tail_part_cur->next;
2594                 }
2595         }
2596         
2597         new_part = mail_newbody_part();
2598         
2599         if (new_part == NULL)  {
2600                 EM_DEBUG_EXCEPTION("EMF_ERROR_OUT_OF_MEMORY");
2601                 error = EMF_ERROR_OUT_OF_MEMORY;
2602                 goto FINISH_OFF;
2603
2604         }
2605         
2606         new_part->next = NULL;
2607         new_part->body.type = TYPEMULTIPART;
2608         new_part->body.subtype = EM_SAFE_STRDUP(sub_type);
2609         
2610         if (tail_part_cur)      
2611                 tail_part_cur->next = new_part;
2612         else 
2613                 parent_body->nested.part = new_part;
2614
2615 FINISH_OFF: 
2616
2617         if (err_code)
2618                 *err_code = error;
2619
2620         EM_DEBUG_FUNC_END();
2621         
2622         return new_part;
2623 }
2624
2625 static int attach_attachment_to_body(BODY **multipart_body, BODY *text_body, emf_attachment_info_t *atch, int *err_code)
2626 {
2627         EM_DEBUG_FUNC_BEGIN("multipart_body[%p], text_body[%p], atch[%p], err_code[%p]", multipart_body, text_body, atch, err_code);
2628         
2629         int ret = false;
2630         int error = EMF_ERROR_NONE;
2631         BODY *frame_body = NULL;
2632         /*  make multipart body(multipart frame_body..) .. that has not content..  */
2633         
2634         if (!multipart_body || !text_body || !atch) {
2635                 EM_DEBUG_EXCEPTION(" multipart_body[%p], text_body[%p], atch[%p]", multipart_body, text_body, atch);
2636                 error = EMF_ERROR_INVALID_PARAM;
2637                 goto FINISH_OFF;
2638         }
2639         
2640         frame_body = mail_newbody();
2641         if (frame_body == NULL) {
2642                 EM_DEBUG_EXCEPTION("mail_newbody failed...");
2643                 error = EMF_ERROR_OUT_OF_MEMORY;
2644                 goto FINISH_OFF;
2645         }
2646         
2647         frame_body->type = TYPEMULTIPART;
2648         frame_body->contents.text.data = NULL;
2649         frame_body->contents.text.size = 0;
2650         frame_body->size.bytes = 0;
2651         
2652         /*  insert original text_body to frame_body.. */
2653         if (!attach_part(frame_body, text_body->sparep, 0, NULL, NULL, false, &error))  {
2654                 EM_DEBUG_EXCEPTION(" attach_part failed [%d]", error);
2655                 goto FINISH_OFF;
2656         }
2657         
2658         /*  insert files..  */
2659         emf_attachment_info_t *p = atch;
2660         char *name = NULL;
2661         struct stat st_buf;
2662         
2663         while (p)  {
2664                 EM_DEBUG_LOG("insert files - attachment id[%d]", p->attachment_id);
2665                 if (stat(p->savename, &st_buf) == 0)  {
2666                         if (!p->name)  {
2667                                 if (!em_core_get_file_name(p->savename, &name, &error))  {
2668                                         EM_DEBUG_EXCEPTION("em_core_get_file_name failed [%d]", error);
2669                                         goto FINISH_OFF;
2670                                 }
2671                         }
2672                         else 
2673                                 name = p->name;
2674                         
2675                         if (!attach_part(frame_body, (unsigned char *)p->savename, 0, name, NULL, false, &error))  {
2676                                 EM_DEBUG_EXCEPTION("attach_part failed [%d]", error);
2677                                 goto FINISH_OFF;
2678                         }
2679                 }
2680                 
2681                 p = p->next;
2682         }
2683         
2684         ret = true;
2685         
2686 FINISH_OFF: 
2687         if (ret == true)
2688                 *multipart_body = frame_body;
2689         else if (frame_body != NULL)
2690                 mail_free_body(&frame_body);
2691         
2692         if (err_code != NULL)
2693                 *err_code = error;
2694         EM_DEBUG_FUNC_END();
2695         return ret;
2696 }
2697
2698 static char *em_core_encode_rfc2047_text(char *utf8_text, int *err_code)
2699 {
2700         EM_DEBUG_FUNC_BEGIN("utf8_text[%s], err_code[%p]", utf8_text, err_code);
2701         
2702         if (utf8_text == NULL)  {
2703                 if (err_code != NULL)
2704                         *err_code = EMF_ERROR_INVALID_PARAM;
2705                 return NULL;
2706         }
2707         
2708         gsize len = strlen(utf8_text);
2709         
2710         EM_DEBUG_FUNC_END();
2711
2712         if (len > 0)
2713                 return g_strdup_printf("=?UTF-8?B?%s?=", g_base64_encode((const guchar  *)utf8_text, len));
2714         else
2715                 return EM_SAFE_STRDUP("");
2716 }
2717
2718 static void em_core_encode_rfc2047_address(ADDRESS *address, int *err_code)
2719 {
2720         EM_DEBUG_FUNC_BEGIN("address[%p], err_code[%p]", address, err_code);
2721         
2722         while (address)  {
2723                 if (address->personal)  {
2724                         char *rfc2047_personal = em_core_encode_rfc2047_text(address->personal, err_code);
2725                         EM_SAFE_FREE(address->personal);
2726                         address->personal = rfc2047_personal;
2727                 }
2728                 address = address->next;
2729         }
2730         EM_DEBUG_FUNC_END();
2731 }
2732
2733 #define DATE_STR_LENGTH 100
2734 /*  Description :  send mail to network(and save to sent-mailbox) or draft-mailbox, */
2735 /*  Parameters :  */
2736 /*                      mail :   */
2737 /*                      is_draft  :  this mail is draft mail. */
2738 /*                      file_path :  path of file that rfc822 data will be written to. */
2739 EXPORT_API int em_core_mail_get_rfc822(emf_mail_t *mail, ENVELOPE **env, char **file_path, emf_option_t *sending_option, int *err_code)
2740 {
2741         EM_DEBUG_FUNC_BEGIN("mail[%p], env[%p], file_path[%p], sending_option[%p], err_code[%p]", mail, env, file_path, sending_option, err_code);
2742         
2743         int ret = false;
2744         int error = EMF_ERROR_NONE;
2745         
2746         ENVELOPE *envelope = NULL;
2747         BODY *text_body = NULL, *html_body = NULL;
2748         BODY *root_body = NULL;
2749         PART *part_for_html = NULL, *part_for_text = NULL;
2750         emf_extra_flag_t extra_flag;
2751         char *fname = NULL;
2752         int is_incomplete = 0;
2753         emf_account_t *ref_account = NULL;
2754         char *pAdd = NULL;
2755         
2756         if (!mail || !mail->info || !mail->head)  {
2757                 if (mail != NULL)
2758                         EM_DEBUG_EXCEPTION("mail->info[%p], mail->head[%p]", mail->info, mail->head);
2759                 
2760                 error = EMF_ERROR_INVALID_PARAM;
2761                 goto FINISH_OFF;
2762         }
2763         
2764         if (mail->info->extra_flags.report != EMF_MAIL_REPORT_MDN && !mail->body) {
2765                 EM_DEBUG_EXCEPTION("mail->body[%p]", mail->body);
2766                 error = EMF_ERROR_INVALID_PARAM;
2767                 goto FINISH_OFF;
2768         }
2769
2770         
2771         ref_account = em_core_get_account_reference(mail->info->account_id);
2772         if (!ref_account)  {    
2773                 EM_DEBUG_EXCEPTION("em_core_get_account_reference failed [%d]", mail->info->account_id);
2774                 error = EMF_ERROR_INVALID_ACCOUNT;
2775                 goto FINISH_OFF;
2776         }
2777         
2778         if (!(envelope = mail_newenvelope()))  {
2779                 EM_DEBUG_EXCEPTION("mail_newenvelope failed...");
2780                 error = EMF_ERROR_OUT_OF_MEMORY;
2781                 goto FINISH_OFF;
2782         }
2783         
2784         is_incomplete = mail->info->flags.draft || (mail->info->extra_flags.status == EMF_MAIL_STATUS_SENDING);/* 4 */
2785         
2786         if (is_incomplete)  {
2787                 if (ref_account->email_addr && ref_account->email_addr[0] != '\0')  {
2788                         char *p = cpystr(ref_account->email_addr);
2789                         
2790                         if (p == NULL)  {
2791                                 EM_DEBUG_EXCEPTION("cpystr failed...");
2792                                 error = EMF_ERROR_OUT_OF_MEMORY;
2793                                 goto FINISH_OFF;
2794                         }
2795                         
2796                         EM_DEBUG_LOG("Assign envelop->from");
2797                         if (mail->head && mail->head->from) {
2798                                 char *pAdd = NULL ;
2799                                 em_core_skip_whitespace(mail->head->from , &pAdd);
2800                                 EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
2801
2802                                 rfc822_parse_adrlist(&envelope->from, pAdd, ref_account->sending_server_addr);
2803                                 EM_SAFE_FREE(pAdd);
2804                                 pAdd = NULL ;
2805                         }
2806                         else
2807                                 envelope->from = rfc822_parse_mailbox(&p, NULL);
2808
2809
2810                         EM_SAFE_FREE(p);                
2811                         if (!envelope->from)  {
2812                                 EM_DEBUG_EXCEPTION("rfc822_parse_mailbox failed...");
2813                                 
2814                                 error = EMF_ERROR_INVALID_ADDRESS;
2815                                 goto FINISH_OFF;                
2816                         }
2817                         else  {
2818
2819                                 if (envelope->from->personal == NULL) {
2820                                         if (sending_option && sending_option->display_name_from && sending_option->display_name_from[0] != '\0') 
2821                                         envelope->from->personal = cpystr(sending_option->display_name_from);
2822                                 else
2823                                         envelope->from->personal = (ref_account->display_name && ref_account->display_name[0] != '\0') ? cpystr(ref_account->display_name)  :  NULL;
2824                         }
2825                 }
2826         }
2827                 
2828         if (ref_account->return_addr && ref_account->return_addr[0] != '\0')  {
2829                 char *p = cpystr(ref_account->return_addr); 
2830                 
2831                 if (p == NULL)  {
2832                         EM_DEBUG_EXCEPTION("cpystr failed...");
2833                         
2834                         error = EMF_ERROR_OUT_OF_MEMORY;
2835                         goto FINISH_OFF;
2836                 }
2837                 envelope->return_path = rfc822_parse_mailbox(&p, NULL);
2838                 EM_SAFE_FREE(p);
2839         }
2840         }
2841         else  {
2842                 if (!mail->head->from || !mail->head->to)  {
2843                         EM_DEBUG_EXCEPTION("mail->head->from[%p], mail->head->to[%p]", mail->head->from, mail->head->to);
2844                         error = EMF_ERROR_INVALID_MAIL;
2845                         goto FINISH_OFF;
2846                 }
2847                 
2848                 int i, j;
2849                 
2850                 if (mail->head->from)  {
2851                         for (i = 0, j = strlen(mail->head->from); i < j; i++)  {
2852                                 if (mail->head->from[i] == ';')
2853                                         mail->head->from[i] = ',';
2854                         }
2855                 }
2856                 
2857                 if (mail->head->return_path)  {
2858                         for (i = 0, j = strlen(mail->head->return_path); i < j; i++)  {
2859                                 if (mail->head->return_path[i] == ';')
2860                                         mail->head->return_path[i] = ',';
2861                         }
2862                 }
2863                         em_core_skip_whitespace(mail->head->from , &pAdd);
2864                 EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
2865         
2866                 rfc822_parse_adrlist(&envelope->from, pAdd, ref_account->sending_server_addr);
2867                 EM_SAFE_FREE(pAdd);
2868                         pAdd = NULL ;
2869
2870                 em_core_skip_whitespace(mail->head->return_path , &pAdd);
2871                 EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
2872         
2873                 rfc822_parse_adrlist(&envelope->return_path, pAdd, ref_account->sending_server_addr);
2874                 EM_SAFE_FREE(pAdd);
2875                         pAdd = NULL ;
2876         }
2877
2878         {
2879                 int i, j;
2880                 
2881                 if (mail->head->to)  {
2882                         for (i = 0, j = strlen(mail->head->to); i < j; i++)  {
2883                                 if (mail->head->to[i] == ';')
2884                                         mail->head->to[i] = ',';
2885                         }
2886                 }
2887                 
2888                 if (mail->head->cc)  {
2889                         for (i = 0, j = strlen(mail->head->cc); i < j; i++)  {
2890                                 if (mail->head->cc[i] == ';')
2891                                         mail->head->cc[i] = ',';
2892                         }
2893                 }
2894                 
2895                 if (mail->head->bcc)  {
2896                         for (i = 0, j = strlen(mail->head->bcc); i < j; i++)  {
2897                                 if (mail->head->bcc[i] == ';')
2898                                         mail->head->bcc[i] = ',';
2899                         }
2900                 }
2901         }
2902
2903         em_core_skip_whitespace(mail->head->to , &pAdd);
2904         EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
2905         
2906         rfc822_parse_adrlist(&envelope->to, pAdd, ref_account->sending_server_addr);
2907         EM_SAFE_FREE(pAdd);
2908         pAdd = NULL ;
2909         
2910         EM_DEBUG_LOG("address[mail->head->cc][%s]", mail->head->cc);
2911         em_core_skip_whitespace(mail->head->cc , &pAdd);
2912         EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
2913         
2914         rfc822_parse_adrlist(&envelope->cc, pAdd, ref_account->sending_server_addr);
2915         EM_SAFE_FREE(pAdd);
2916                 pAdd = NULL ;
2917
2918         em_core_skip_whitespace(mail->head->bcc , &pAdd);
2919         rfc822_parse_adrlist(&envelope->bcc, pAdd, ref_account->sending_server_addr);
2920         EM_SAFE_FREE(pAdd);
2921                 pAdd = NULL ;
2922
2923         em_core_encode_rfc2047_address(envelope->return_path, &error);
2924         em_core_encode_rfc2047_address(envelope->from, &error);
2925         em_core_encode_rfc2047_address(envelope->sender, &error);
2926         em_core_encode_rfc2047_address(envelope->reply_to, &error);
2927         em_core_encode_rfc2047_address(envelope->to, &error);
2928         em_core_encode_rfc2047_address(envelope->cc, &error);
2929         em_core_encode_rfc2047_address(envelope->bcc, &error);
2930
2931         if (mail->head->subject)
2932                 envelope->subject = em_core_encode_rfc2047_text(mail->head->subject, &error);
2933
2934         char date_str[DATE_STR_LENGTH + 1] = { 0, };
2935         
2936         rfc822_date(date_str);
2937
2938         if (!is_incomplete)  {
2939                 struct tm tm1;
2940                 
2941                 /*  modified by stonyroot - prevent issue */
2942                 memset(&tm1,  0x00, sizeof(tm1));
2943                 
2944                 tm1.tm_year = mail->head->datetime.year - 1900;
2945                 tm1.tm_mon  = mail->head->datetime.month - 1;
2946                 tm1.tm_mday = mail->head->datetime.day;
2947                 tm1.tm_hour = mail->head->datetime.hour;
2948                 tm1.tm_min  = mail->head->datetime.minute;
2949                 tm1.tm_sec  = mail->head->datetime.second;
2950                 
2951                 /* tzset(); */
2952                 time_t t = mktime(&tm1);
2953                 
2954                 char buf[256] = {0, };
2955                 
2956                 if (localtime(&t))
2957                         strftime(buf, 128, "%a, %e %b %Y %H : %M : %S ", localtime(&t));
2958                 else
2959                         strftime(buf, 128, "%a, %e %b %Y %H : %M : %S ", (const struct tm *)&tm1);      
2960                 /*  append last 5byes("+0900") */
2961                 strncat(buf, date_str + (strlen(date_str) -  5), DATE_STR_LENGTH);
2962                 strncpy(date_str, buf, DATE_STR_LENGTH);
2963         }
2964         
2965         envelope->date = (unsigned char *)cpystr((const char *)date_str);
2966         
2967         memcpy(&extra_flag, &mail->info->extra_flags, sizeof(emf_extra_flag_t));
2968         
2969         /*  check report mail */
2970         if (mail->info->extra_flags.report != EMF_MAIL_REPORT_MDN)  {           
2971                 /* Non-report mail */
2972                 EM_DEBUG_LOG("mail->body->plain[%s]", mail->body->plain);
2973                 EM_DEBUG_LOG("mail->body->html[%s]", mail->body->html);
2974                 EM_DEBUG_LOG("mail->body->attachment_num[%d]", mail->body->attachment_num);
2975                 
2976                 
2977                 if ((mail->body->attachment_num > 0) || (mail->body->plain && mail->body->html))  {
2978                         EM_DEBUG_LOG("attachment_num  :  %d", mail->body->attachment_num);
2979                         root_body = mail_newbody();
2980
2981                         if (root_body == NULL)  {
2982                                 EM_DEBUG_EXCEPTION("mail_newbody failed...");
2983                                 error = EMF_ERROR_OUT_OF_MEMORY;
2984                                 goto FINISH_OFF;
2985                         }
2986                         
2987                         root_body->type = TYPEMULTIPART;
2988                         root_body->subtype = EM_SAFE_STRDUP("MIXED");
2989                         root_body->contents.text.data = NULL;
2990                         root_body->contents.text.size = 0;
2991                         root_body->size.bytes = 0;
2992
2993                         part_for_text = attach_mutipart_with_sub_type(root_body, "ALTERNATIVE", &error);
2994
2995                         if (!part_for_text) {
2996                                 EM_DEBUG_EXCEPTION("attach_mutipart_with_sub_type [part_for_text] failed [%d]", error);
2997                                 goto FINISH_OFF;
2998                         }
2999
3000                         text_body = &part_for_text->body;
3001                         
3002                         if (mail->body->plain && strlen(mail->body->plain) > 0)  {
3003                                 EM_DEBUG_LOG("body->plain[%s]", mail->body->plain);
3004                                 if (!attach_part(text_body, (unsigned char *)mail->body->plain, 0, NULL, NULL, false, &error))  {
3005                                         EM_DEBUG_EXCEPTION("attach_part failed [%d]", error);
3006                                         goto FINISH_OFF;
3007                                 }
3008                         }
3009                         
3010                         if (mail->body->html && strlen(mail->body->html) > 0)  {
3011                                 EM_DEBUG_LOG("body->html[%s]", mail->body->html);
3012
3013                                 part_for_html = attach_mutipart_with_sub_type(text_body, "RELATED", &error);
3014                                 if (!part_for_html) {
3015                                         EM_DEBUG_EXCEPTION("attach_mutipart_with_sub_type [part_for_html] failed [%d]", error);
3016                                         goto FINISH_OFF;
3017                                 }
3018
3019                                 if (!attach_part(&(part_for_html->body) , (unsigned char *)mail->body->html, 0, NULL, "html", false, &error))  {
3020                                         EM_DEBUG_EXCEPTION("attach_part failed [%d]", error);
3021                                         goto FINISH_OFF;
3022                                 }
3023                                 /*
3024                                 if (mail->body->plain)  {
3025                                         EM_SAFE_FREE(part_for_text->subtype);
3026                                         part_for_text->subtype = EM_SAFE_STRDUP("ALTERNATIVE");
3027                                 }
3028                                 */
3029                         }
3030                         
3031                         if (mail->body->attachment)  {
3032                                 emf_attachment_info_t *atch = mail->body->attachment;
3033                                 char *name = NULL;
3034                                 BODY *body_to_attach = NULL; 
3035                                 struct stat st_buf;
3036                                 
3037                                 do  {
3038                                         EM_DEBUG_LOG("atch->savename[%s], atch->name[%s]", atch->savename, atch->name);
3039                                         if (stat(atch->savename, &st_buf) == 0)  {
3040                                                 EM_DEBUG_LOG("atch->name[%s]", atch->name);
3041                                                 if (!atch->name)  {
3042                                                         if (!em_core_get_file_name(atch->savename, &name, &error))  {
3043                                                                 EM_DEBUG_EXCEPTION("em_core_get_file_name failed [%d]", error);
3044                                                                 goto TRY_NEXT;
3045                                                         }
3046                                                 }
3047                                                 else 
3048                                                         name = atch->name;
3049                                                 EM_DEBUG_LOG("name[%s]", name);
3050
3051                                                 if (atch->inline_content && part_for_html)
3052                                                         body_to_attach = &(part_for_html->body);
3053                                                 else
3054                                                         body_to_attach = root_body;
3055                                                 
3056                                                 if (!attach_part(body_to_attach, (unsigned char *)atch->savename, 0, name, NULL, atch->inline_content, &error))  {
3057                                                         EM_DEBUG_EXCEPTION("attach_part failed [%d]", error);
3058                                                         goto TRY_NEXT;
3059                                                 }
3060                                         }
3061                                         
3062 TRY_NEXT:
3063                                         atch = atch->next;
3064                                 }
3065                                 while (atch);
3066                         }
3067                         text_body = NULL; 
3068                 }
3069                 else  {
3070                         text_body = mail_newbody();
3071                         
3072                         if (text_body == NULL)  {
3073                                 EM_DEBUG_EXCEPTION("mail_newbody failed...");
3074                                 
3075                                 error = EMF_ERROR_OUT_OF_MEMORY;
3076                                 goto FINISH_OFF;
3077                         }
3078                         
3079                         text_body->type = TYPETEXT;
3080                         text_body->encoding = ENC8BIT;
3081                         if (mail->body->plain || mail->body->html)
3082                                 text_body->sparep = EM_SAFE_STRDUP(mail->body->plain ? mail->body->plain  :  mail->body->html);
3083                         else
3084                                 text_body->sparep = NULL;
3085                         
3086                         if (mail->body->html != NULL && mail->body->html[0] != '\0')
3087                                 text_body->subtype = EM_SAFE_STRDUP("html");
3088                         if (text_body->sparep)
3089                                 text_body->size.bytes = strlen(text_body->sparep);
3090                         else
3091                                 text_body->size.bytes = 0;
3092                 }
3093         }
3094         else  { /*  Report mail */
3095                 EM_DEBUG_LOG("REPORT MAIL");
3096                 envelope->references = cpystr(mail->head->mid);
3097                 
3098                 if (em_core_mail_get_report_body(envelope, &root_body, &error))  {
3099                         if (!mail->body)  {
3100                                 mail->body = em_core_malloc(sizeof(emf_mail_body_t));
3101                                 if (!mail->body)  {
3102                                         EM_DEBUG_EXCEPTION("malloc failed...");
3103                                         error = EMF_ERROR_OUT_OF_MEMORY;
3104                                         goto FINISH_OFF;
3105                                 }
3106                                 
3107                                 mail->body->plain = EM_SAFE_STRDUP(root_body->nested.part->body.sparep);
3108                                 mail->body->attachment_num = 1;
3109                                 
3110                                 mail->body->attachment = em_core_malloc(sizeof(emf_attachment_info_t));
3111                                 if (!mail->body->attachment)  {
3112                                         EM_DEBUG_EXCEPTION("malloc failed...");
3113                                         EM_SAFE_FREE(mail->body->plain);
3114                                         error = EMF_ERROR_OUT_OF_MEMORY;
3115                                         goto FINISH_OFF;
3116                                 }
3117                                 
3118                                 mail->body->attachment->downloaded = 1;
3119                                 mail->body->attachment->savename = EM_SAFE_STRDUP(root_body->nested.part->next->body.sparep);
3120                                 
3121                                 char *p = NULL;
3122                                 
3123                                 if (!em_core_get_file_name(mail->body->attachment->savename, &p, &error))  {
3124                                         EM_DEBUG_EXCEPTION("em_core_get_file_name failed [%d]", error);
3125                                         goto FINISH_OFF;
3126                                 }
3127                                 
3128                                 mail->body->attachment->name = cpystr(p);
3129                         }
3130                 }
3131                         
3132         }
3133         
3134         if (file_path)  {
3135                 EM_DEBUG_LOG("write rfc822  :  file_path[%s]", file_path);
3136
3137                 if (part_for_html)
3138                         html_body = &(part_for_html->body);
3139
3140                 if (!em_core_write_rfc822(envelope, root_body ? root_body  :  text_body, html_body, extra_flag, &fname, &error))  {
3141                         EM_DEBUG_EXCEPTION("em_core_write_rfc822 failed [%d]", error);
3142                         goto FINISH_OFF;
3143                 }
3144                 
3145                 *file_path = fname;
3146         }
3147         
3148         ret = true;
3149         
3150 FINISH_OFF: 
3151         if ((ret == true) && (env != NULL))
3152                 *env = envelope;
3153         else if (envelope != NULL)
3154                 mail_free_envelope(&envelope);
3155         
3156         if (text_body != NULL)
3157                 mail_free_body(&text_body);
3158         
3159         if (root_body != NULL)
3160                 mail_free_body(&root_body);
3161         
3162         if (err_code != NULL)
3163                 *err_code = error;
3164         EM_DEBUG_FUNC_END("ret [%d]", ret);
3165         return ret;
3166 }
3167
3168 static int em_core_mail_get_report_body(ENVELOPE *envelope, BODY **multipart_body, int *err_code)
3169 {
3170         EM_DEBUG_FUNC_BEGIN("envelope[%p], mulitpart_body[%p], err_code[%p]", envelope, multipart_body, err_code);
3171         
3172         int ret = false;
3173         int err = EMF_ERROR_NONE;
3174         
3175         BODY *m_body = NULL;
3176         BODY *p_body = NULL;
3177         BODY *text_body = NULL;
3178         PARAMETER *param = NULL;
3179         emf_attachment_info_t atch;
3180         FILE *fp = NULL;
3181         char *fname = NULL;
3182         char buf[512] = {0x00, };
3183         int sz = 0;
3184         
3185         if (!envelope || !multipart_body)  {
3186                 EM_DEBUG_EXCEPTION(" envelope[%p], mulitpart_body[%p]", envelope, multipart_body);
3187                 err = EMF_ERROR_INVALID_PARAM;
3188                 goto FINISH_OFF;
3189         }
3190         
3191         if (!(text_body = mail_newbody()))  {
3192                 EM_DEBUG_EXCEPTION(" mail_newbody failed...");
3193                 err = EMF_ERROR_OUT_OF_MEMORY;
3194                 goto FINISH_OFF;
3195         }
3196         
3197         if (!em_core_get_temp_file_name(&fname, &err))  {
3198                 EM_DEBUG_EXCEPTION(" em_core_get_temp_file_name failed [%d]", err);
3199                 goto FINISH_OFF;
3200         }
3201         
3202         if (!(fp = fopen(fname, "wb+")))  {
3203                 EM_DEBUG_EXCEPTION(" fopen failed - %s", fname);
3204                 err = EMF_ERROR_SYSTEM_FAILURE;         /* EMF_ERROR_UNKNOWN; */
3205                 goto FINISH_OFF;
3206         }
3207         
3208         if (!envelope->from || !envelope->from->mailbox || !envelope->from->host)  {
3209                 if (!envelope->from)
3210                         EM_DEBUG_EXCEPTION(" envelope->from[%p]", envelope->from);
3211                 else
3212                         EM_DEBUG_LOG(" envelope->from->mailbox[%p], envelope->from->host[%p]", envelope->from->mailbox, envelope->from->host);
3213                 
3214                 err = EMF_ERROR_INVALID_PARAM;
3215                 goto FINISH_OFF;
3216         }
3217         
3218         if (envelope->from->personal) 
3219                 SNPRINTF(buf, sizeof(buf), "%s <%s@%s>", envelope->from->personal, envelope->from->mailbox, envelope->from->host);
3220         else 
3221                 SNPRINTF(buf, sizeof(buf), "%s@%s", envelope->from->mailbox, envelope->from->host);
3222         
3223         fprintf(fp, "Your message has been read by %s"CRLF_STRING, buf);
3224         fprintf(fp, "Date :  %s", envelope->date);
3225         
3226         fclose(fp); fp = NULL;
3227         
3228         if (!em_core_get_file_size(fname, &sz, &err))  {
3229                 EM_DEBUG_EXCEPTION(" em_core_get_file_size failed [%d]", err);
3230                 goto FINISH_OFF;
3231         }
3232         
3233         text_body->type = TYPETEXT;
3234         text_body->encoding = ENC8BIT;
3235         text_body->sparep = fname;
3236         text_body->size.bytes = (unsigned long)sz;
3237         
3238         if (!em_core_get_temp_file_name(&fname, &err))  {
3239                 EM_DEBUG_EXCEPTION(" em_core_get_temp_file_name failed [%d]", err);
3240                 goto FINISH_OFF;
3241         }
3242         
3243         if (!(fp = fopen(fname, "wb+")))  {
3244                 EM_DEBUG_EXCEPTION(" fopen failed - %s", fname);
3245                 err = EMF_ERROR_SYSTEM_FAILURE;         /* EMF_ERROR_UNKNOWN; */
3246                 goto FINISH_OFF;
3247         }
3248         
3249         if (!envelope->references)  {
3250                 EM_DEBUG_EXCEPTION(" envelope->references[%p]", envelope->references);
3251                 err = EMF_ERROR_INVALID_PARAM;
3252                 goto FINISH_OFF;
3253         }
3254
3255         fprintf(fp, "Final-Recipient :  rfc822;%s@%s\r", envelope->from->mailbox, envelope->from->host);
3256         fprintf(fp, "Original-Message-ID:  %s\r", envelope->references);
3257         fprintf(fp, "Disposition :  manual-action/MDN-sent-manually; displayed");
3258         
3259         fclose(fp); fp = NULL;
3260         
3261         memset(&atch, 0x00, sizeof(atch));
3262         
3263         atch.savename = fname;
3264         
3265         if (!em_core_get_file_size(fname, &atch.size, &err))  {
3266                 EM_DEBUG_EXCEPTION(" em_core_get_file_size failed [%d]", err);
3267                 goto FINISH_OFF;
3268         }
3269         
3270         if (!attach_attachment_to_body(&m_body, text_body, &atch, &err))  {
3271                 EM_DEBUG_EXCEPTION(" attach_attachment_to_body failed [%d]", err);
3272                 goto FINISH_OFF;
3273         }
3274         
3275         text_body->contents.text.data = NULL;
3276         
3277         /*  change mail header */
3278         
3279         /*  set content-type to multipart/report */
3280         m_body->subtype = EM_SAFE_STRDUP("report");
3281         
3282         /*  set report-type parameter in content-type */
3283         param = em_core_malloc(sizeof(PARAMETER));
3284         if (!param)  {          
3285                 EM_DEBUG_EXCEPTION(" malloc failed...");
3286                 err = EMF_ERROR_OUT_OF_MEMORY;
3287                 goto FINISH_OFF;
3288         }
3289         
3290         param->attribute = EM_SAFE_STRDUP("report-type");
3291         param->value = EM_SAFE_STRDUP("disposition-notification");
3292         param->next = m_body->parameter;
3293         
3294         m_body->parameter = param;
3295         
3296         /*  change body-header */
3297         
3298         p_body = &m_body->nested.part->next->body;
3299         
3300         /*  set content-type to message/disposition-notification */
3301         p_body->type = TYPEMESSAGE;
3302         p_body->encoding = ENC7BIT;
3303         
3304         EM_SAFE_FREE(p_body->subtype);
3305         
3306         p_body->subtype = EM_SAFE_STRDUP("disposition-notification");
3307         
3308         /*  set parameter */
3309         mail_free_body_parameter(&p_body->parameter);
3310         mail_free_body_parameter(&p_body->disposition.parameter);
3311         
3312         EM_SAFE_FREE(p_body->disposition.type);
3313         
3314         p_body->disposition.type = EM_SAFE_STRDUP("inline");
3315         
3316         ret = true;
3317         
3318 FINISH_OFF: 
3319         if ((ret == true) && (multipart_body != NULL))
3320                 *multipart_body = m_body;
3321         else if (m_body != NULL)
3322                 mail_free_body(&m_body);
3323         
3324         if (text_body != NULL)
3325                 mail_free_body(&text_body);
3326         
3327         if (fp != NULL)
3328                 fclose(fp);
3329         
3330         EM_SAFE_FREE(fname);
3331         
3332         if (err_code != NULL)
3333                 *err_code = err;
3334         
3335         return ret;
3336 }
3337
3338 EXPORT_API   int em_core_get_body_buff(char *file_path, char **buff)
3339 {
3340         EM_DEBUG_FUNC_BEGIN();
3341
3342         FILE *r_fp = NULL;
3343         int read_size = 0;
3344         int ret = false;
3345         char *read_buff = NULL;
3346
3347         
3348         if (file_path)
3349                 r_fp = fopen(file_path, "r");
3350
3351         if (!r_fp) {
3352                 EM_DEBUG_EXCEPTION(" Filename %s failed to open", file_path);   
3353                 goto FINISH_OFF;
3354         }
3355  
3356
3357         struct stat stbuf; 
3358         stat(file_path, &stbuf); 
3359         EM_DEBUG_LOG(" File Size [ %d ] ", stbuf.st_size);
3360         read_buff = calloc(1, (stbuf.st_size+ 1));
3361         read_size = fread(read_buff, 1, stbuf.st_size, r_fp);
3362         read_buff[stbuf.st_size] = '\0';
3363
3364         if (ferror(r_fp)) {
3365                 EM_DEBUG_EXCEPTION("file read failed - %s", file_path);
3366                 EM_SAFE_FREE(read_buff);
3367                 goto FINISH_OFF;
3368         }               
3369
3370
3371         ret = true;
3372         *buff = read_buff;
3373         
3374         FINISH_OFF: 
3375         if (r_fp)       /* Prevent Defect - 17424 */
3376                 fclose(r_fp);
3377
3378         return ret;
3379 }
3380
3381 EXPORT_API int em_core_mail_get_envelope_body_struct(emf_mail_t *mail, 
3382                                                                                         ENVELOPE **env, 
3383                                                                                         BODY **text_body, 
3384                                                                                         BODY **multipart_body, 
3385                                                                                         int *err_code)
3386 {
3387         EM_DEBUG_FUNC_BEGIN("mail[%p], env[%p], text_body[%p], multipart_body[%p], err_code[%p]", mail, env, text_body, multipart_body, err_code);
3388         
3389         int ret = false;
3390         int error = EMF_ERROR_NONE;
3391         ENVELOPE *envelope = NULL;
3392         BODY *txt_body = NULL;
3393         BODY *multi_part_body = NULL;
3394         emf_extra_flag_t extra_flag;
3395         int is_incomplete = 0;
3396         emf_account_t *ref_account = NULL;
3397         char *pAdd = NULL ;
3398         
3399         if (!mail || !mail->info || !mail->head || !mail->body) {
3400                 EM_DEBUG_EXCEPTION("EMF_ERROR_INVALID_PARAM");
3401                 error = EMF_ERROR_INVALID_PARAM;
3402                 goto FINISH_OFF;
3403         }
3404         
3405         ref_account = em_core_get_account_reference(mail->info->account_id);
3406         
3407         if (!ref_account) {
3408                 EM_DEBUG_EXCEPTION(" em_core_get_account_reference failed [%d]", mail->info->account_id);
3409                 error = EMF_ERROR_INVALID_ACCOUNT;
3410                 goto FINISH_OFF;
3411         }
3412
3413         if (!(envelope = mail_newenvelope())) {
3414                 EM_DEBUG_EXCEPTION(" mail_newenvelope failed...");
3415                 error = EMF_ERROR_OUT_OF_MEMORY;
3416                 goto FINISH_OFF;
3417         }
3418
3419         EM_DEBUG_LOG(" mail_newenvelope created...");
3420         is_incomplete = mail->info->flags.draft || mail->info->extra_flags.status == EMF_MAIL_STATUS_SENDING;/* 4; */
3421         if (is_incomplete) {
3422                 if (ref_account->email_addr) {
3423                         char *p = EM_SAFE_STRDUP(ref_account->email_addr);
3424                         
3425                         envelope->from = rfc822_parse_mailbox(&p, NULL);
3426                         /* mailbox = user id; host = mail-server-addr; */
3427                         if (!envelope->from)  {
3428                                 EM_DEBUG_EXCEPTION("rfc822_parse_mailbox failed...");
3429                                 error = EMF_ERROR_INVALID_ADDRESS;
3430                                 goto FINISH_OFF;
3431                         }
3432                         else  {
3433                                 envelope->from->personal = ref_account->display_name ? cpystr(ref_account->display_name)  :  NULL;
3434                         }
3435                 }
3436                 
3437                 if (ref_account->return_addr)  {
3438                         char *p = EM_SAFE_STRDUP(ref_account->return_addr); 
3439                         envelope->return_path = rfc822_parse_mailbox(&p, NULL);
3440                 }
3441         }
3442         else  {
3443                 if (!mail->head->from || !mail->head->to)  {
3444                         EM_DEBUG_EXCEPTION(" mail->head->from[%p], mail->head->to[%p]", mail->head->from, mail->head->to);
3445                         error = EMF_ERROR_INVALID_MAIL;
3446                         goto FINISH_OFF;
3447                 }
3448
3449                 em_core_skip_whitespace(mail->head->from , &pAdd);
3450                 EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
3451                 
3452                 rfc822_parse_adrlist(&envelope->from, pAdd, ref_account->sending_server_addr);
3453                 EM_SAFE_FREE(pAdd);
3454                         pAdd = NULL ;
3455
3456                 em_core_skip_whitespace(mail->head->return_path , &pAdd);
3457                 EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
3458                 rfc822_parse_adrlist(&envelope->return_path, pAdd, ref_account->sending_server_addr);
3459                 EM_SAFE_FREE(pAdd);
3460                         pAdd = NULL ;
3461         }
3462         
3463         {
3464                 int i, j;
3465                 
3466                 if (mail->head->to) {
3467                         for (i = 0, j = strlen(mail->head->to); i < j; i++) {
3468                                 if (mail->head->to[i] == ';')
3469                                         mail->head->to[i] = ',';
3470                         }
3471                 }
3472                 
3473                 if (mail->head->cc) {
3474                         for (i = 0, j = strlen(mail->head->cc); i < j; i++) {
3475                                 if (mail->head->cc[i] == ';')
3476                                         mail->head->cc[i] = ',';
3477                         }
3478                 }
3479                 
3480                 if (mail->head->bcc) {
3481                         for (i = 0, j = strlen(mail->head->bcc); i < j; i++) {
3482                                 if (mail->head->bcc[i] == ';')
3483                                         mail->head->bcc[i] = ',';
3484                         }
3485                 }
3486         }
3487
3488         em_core_skip_whitespace(mail->head->to , &pAdd);
3489         EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
3490                 
3491         rfc822_parse_adrlist(&envelope->to, pAdd, ref_account->sending_server_addr);
3492         EM_SAFE_FREE(pAdd);
3493         pAdd = NULL ;
3494         
3495         em_core_skip_whitespace(mail->head->cc , &pAdd);
3496
3497         rfc822_parse_adrlist(&envelope->cc, pAdd, ref_account->sending_server_addr);
3498         EM_SAFE_FREE(pAdd);
3499         pAdd = NULL ;
3500         
3501         em_core_skip_whitespace(mail->head->bcc , &pAdd);
3502         EM_DEBUG_LOG("address[pAdd][%s]", pAdd);
3503         rfc822_parse_adrlist(&envelope->bcc, pAdd, ref_account->sending_server_addr);
3504         EM_SAFE_FREE(pAdd);
3505                 pAdd = NULL ;
3506         em_core_encode_rfc2047_address(envelope->return_path, &error);
3507         em_core_encode_rfc2047_address(envelope->from, &error);
3508         em_core_encode_rfc2047_address(envelope->sender, &error);
3509         em_core_encode_rfc2047_address(envelope->reply_to, &error);
3510         em_core_encode_rfc2047_address(envelope->to, &error);
3511         em_core_encode_rfc2047_address(envelope->cc, &error);
3512         em_core_encode_rfc2047_address(envelope->bcc, &error);
3513
3514
3515         if (mail->head->subject)
3516                 envelope->subject = em_core_encode_rfc2047_text(mail->head->subject, &error);
3517
3518         char date_str[DATE_STR_LENGTH] = { 0, };
3519         
3520         rfc822_date(date_str);
3521
3522         if (!is_incomplete) {
3523                 struct tm tm1;
3524                 
3525                 /*  modified by stonyroot - prevent issue */
3526                 memset(&tm1,  0x00, sizeof(tm1));
3527                 
3528                 tm1.tm_year = mail->head->datetime.year - 1900;
3529                 tm1.tm_mon = mail->head->datetime.month - 1;
3530                 tm1.tm_mday = mail->head->datetime.day;
3531                 tm1.tm_hour = mail->head->datetime.hour;
3532                 tm1.tm_min = mail->head->datetime.minute;
3533                 tm1.tm_sec = mail->head->datetime.second;
3534                 
3535                 /* tzset(); */
3536                 time_t t = mktime(&tm1);
3537                 
3538                 char buf[256] = {0x00, };
3539                 
3540                 if (localtime(&t))
3541                         strftime(buf, 128, "%a, %e %b %Y %H : %M : %S ", localtime(&t));
3542                 else
3543                         strftime(buf, 128, "%a, %e %b %Y %H : %M : %S ", (const struct tm *)&tm1);      
3544
3545                 /*  append last 5byes("+0900") */
3546                 strncat(buf, date_str + (strlen(date_str) -  5), sizeof(buf) - 1);
3547                 strncpy(date_str, buf, DATE_STR_LENGTH - 1);
3548         }
3549         
3550         envelope->date = (unsigned char *)cpystr((const char *)date_str);
3551         
3552         memcpy(&extra_flag, &mail->info->extra_flags, sizeof(emf_extra_flag_t));
3553         
3554         /*  check report mail */
3555         if (mail->info->extra_flags.report != EMF_MAIL_REPORT_MDN)  {           
3556                 txt_body = mail_newbody();
3557                 if (txt_body == NULL) {
3558                         EM_DEBUG_EXCEPTION(" mail_newbody failed...");
3559                         
3560                         error = EMF_ERROR_OUT_OF_MEMORY;
3561                         goto FINISH_OFF;
3562                 }
3563                 
3564                 txt_body->type = TYPETEXT;
3565                 txt_body->encoding = ENC8BIT;
3566                 if (mail->body && mail->body->plain) {
3567                         if (mail->body->plain)
3568                         txt_body->sparep = EM_SAFE_STRDUP(mail->body->plain);
3569                         else
3570                         txt_body->sparep = NULL;                                
3571                         
3572                         txt_body->size.bytes = (int)strlen(mail->body->plain);
3573                 }
3574                 
3575                 if (mail->body) {
3576                         if (mail->body->attachment) {
3577                                 if (!attach_attachment_to_body(&multi_part_body, txt_body, mail->body->attachment, &error)) {
3578                                         EM_DEBUG_EXCEPTION("attach_attachment_to_body failed [%d]", error);
3579                                         goto FINISH_OFF;
3580                                 }
3581                         }
3582                 }
3583         }
3584         else  {         /*  Report mail */
3585                 if (mail->head || mail->head->mid)
3586                         envelope->references = cpystr(mail->head->mid);
3587                 if (em_core_mail_get_report_body(envelope, &multi_part_body, &error)) {
3588                         if (!mail->body) {
3589                                 mail->body = em_core_malloc(sizeof(emf_mail_body_t));
3590                                 if (!mail->body) {              
3591                                         EM_DEBUG_EXCEPTION("malloc failed...");
3592                                         
3593                                         error = EMF_ERROR_OUT_OF_MEMORY;
3594                                         goto FINISH_OFF;
3595                                 }
3596                                 
3597                                 mail->body->plain = EM_SAFE_STRDUP(multi_part_body->nested.part->body.sparep);
3598                                 mail->body->attachment_num = 1;
3599                                 
3600                                 mail->body->attachment = em_core_malloc(sizeof(emf_attachment_info_t));
3601                                 if (!mail->body->attachment)  { 
3602                                         EM_DEBUG_EXCEPTION("malloc failed...");
3603                                         
3604                                         EM_SAFE_FREE(mail->body->plain);
3605                                         error = EMF_ERROR_OUT_OF_MEMORY;
3606                                         goto FINISH_OFF;
3607                                 }
3608                                 
3609                                 mail->body->attachment->downloaded = 1;
3610                                 mail->body->attachment->savename = EM_SAFE_STRDUP(multi_part_body->nested.part->next->body.sparep);
3611                                 
3612                                 char *p = NULL;
3613                                 if (!em_core_get_file_name(mail->body->attachment->savename, &p, &error))  {
3614                                         EM_DEBUG_EXCEPTION("em_core_get_file_name failed [%d]", error);
3615                                         
3616                                         goto FINISH_OFF;
3617                                 }
3618                                 
3619                                 mail->body->attachment->name = cpystr(p);
3620                         }
3621                 }
3622         }
3623         ret = true;
3624         
3625 FINISH_OFF: 
3626         if (ret == true) {
3627                 if (env != NULL)
3628                         *env = envelope;
3629                 if (txt_body != NULL)
3630                         *text_body = txt_body;
3631                 if (multi_part_body != NULL)
3632                         *multipart_body = multi_part_body;
3633         }
3634         else  {
3635                 if (envelope != NULL)
3636                         mail_free_envelope(&envelope);
3637                 if (txt_body != NULL)
3638                         mail_free_body(&txt_body);
3639                 if (multi_part_body != NULL)
3640                         mail_free_body(&multi_part_body);
3641         }
3642
3643         if (err_code != NULL)
3644                 *err_code = error;
3645         return ret;
3646 }