2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 #include <email-types.h>
20 #include <email-api.h>
21 #include <email-api-network.h>
22 #include <email-api-init.h>
23 #include <email-api-account.h>
25 #include <Commons/Exception.h>
26 #include <Commons/ThreadPool.h>
27 #include "ReqReceiverMessage.h"
28 #include "EventMessagingService.h"
29 #include "IAttachment.h"
32 #include "SyncNetworkStatus.h"
36 #include <vconf-keys.h>
41 const char* DBUS_FILTER_NETWORK_STATUS =
42 "type='signal',interface='User.Email.NetworkStatus'";
43 //const char* DBUS_FILTER_EMAIL_RECEIVED =
44 // "type='signal',interface='User.Email.StorageChange'";
50 using namespace WrtDeviceApis::Commons;
52 MailSync& MailSync::getInstance()
54 static MailSync instance;
58 MailSync::MailSync() :
59 m_dbusThread(new DPL::Thread()),
60 m_dbus(new DBus::Connection())
64 m_dbus->setWorkerThread(m_dbusThread.Get());
65 m_dbus->AddListener(this);
66 m_dbus->SwitchAllListenersToThread(
67 ThreadPool::getInstance().getThreadRef(ThreadEnum::MESSAGING_THREAD)
69 m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
70 m_dbus->open(DBUS_BUS_SYSTEM);
73 int error = email_service_begin();
74 if (error == EMAIL_ERROR_NONE) {
75 LoggerD("Email service Begin\n");
76 if (EMAIL_ERROR_NONE == email_open_db()) {
77 LoggerD("Email open DB success\n");
80 LoggerD("Email open DB failed\n");
84 LoggerD("Email service not started\n");
85 LoggerD("Error : " << error);
90 vconf_get_int("db/private/email-service/slot_size", &(slot_size));
92 m_default_slot_size = slot_size;
94 LoggerD( "Slot Size : " << m_default_slot_size );
100 m_dbus->RemoveListener(this);
103 m_dbusThread->Quit();
105 //close email service
106 if (EMAIL_ERROR_NONE == email_close_db()) {
107 LoggerD("Email Close DB Success\n");
108 if (EMAIL_ERROR_NONE == email_service_end())
110 LoggerD("Email service close Success\n");
114 LoggerD("Email service end failed\n");
118 LoggerD("Email Close DB failed\n");
122 int MailSync::downloadBody( const IEmailPtr& mail )
126 int mailId = mail->convertId(mail->getIdRef()); // get mail id
127 LoggerD("start attachment, mail Id : " << mail->getIdRef());
128 SyncRequestIterator it;
130 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
132 synType = it->second.syncType;
133 LoggerD("synType : " << synType);
135 if( synType != MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY )
140 const IEmailPtr& email = it->second.mail;
141 LoggerD ( "Requests mail ID:" << mail->convertId(email->getIdRef()) );
142 if ( mailId == mail->convertId(email->getIdRef()))
144 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
145 "download Body: " << mailId << " already requested to be download Body.");
150 return downloadBodyInternal(mail, mail->getAccountID());
154 void MailSync::cancelDownloadBody(int handle)
156 SyncRequestIterator it = m_SyncRequests.find(handle);
157 if ( m_SyncRequests.end() != it)
159 if ( it->second.messagingService )
160 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
161 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
165 LoggerD("Don't find cancel DownloadBody handle : " << handle);
166 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
171 void MailSync::cancelDownloadAttachment(int handle)
174 SyncRequestIterator it = m_SyncRequests.find(handle);
175 if ( m_SyncRequests.end() != it)
177 if ( it->second.messagingService )
178 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
179 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
183 LoggerD("Don't find cancel DownloadAttachment handle : " << handle);
188 int MailSync::downloadAttachment(const IEmailPtr& mail, const IAttachmentPtr& attachment)
190 if ( mail && attachment )
192 //int mailId = mail->convertId(mail->getIdRef()); // get mail id
193 LoggerD("start attachment, mail Id : " << mail->getIdRef());
194 SyncRequestIterator it;
196 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
198 synType = it->second.syncType;
199 LoggerD("synType : " << synType);
201 if( synType != MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT )
207 const IAttachmentPtr& iattachment = it->second.attachment;
208 LoggerD ( "Requests Attachment ID:" << iattachment->getAttachmentID() << " Input Attachment ID: " << attachment->getAttachmentID());
209 if (iattachment->getAttachmentID() == attachment->getAttachmentID())
211 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
212 "Attachment: " << attachment->getAttachmentID() << " already requested to be download Attachment.");
217 return downloadAttachmentInternal(mail, mail->getAccountID(), attachment);
221 int MailSync::syncAccount(const IMessagingServicePtr& messagingService, const int limit)
223 LoggerD("syncAccount : " << limit);
224 if (messagingService)
226 int accountId = messagingService->getAccountID();
227 LoggerD("start sync, account Id : " << accountId);
228 SyncRequestIterator it;
230 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
232 synType = it->second.syncType;
233 LoggerD("synType : " << synType);
235 if( synType != MESSAGING_SERVICE_SYNC_TYPE_SYNC )
241 const IMessagingServicePtr& messagingService = it->second.messagingService;
242 if (messagingService && messagingService->getAccountID() == accountId)
244 LoggerD("accountId is sync requested already");
245 // ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Sync: " << accountId << " already requested to be Sync Account.");
248 return syncAccountInternal(messagingService, limit);
252 LoggerD("messagingService is NULL");
255 LoggerD("end sync" );
259 int MailSync::syncAccountInternal( const IMessagingServicePtr& messagingService, const int limit)
261 LoggerD("syncAccountInternal limit: " << limit);
263 int account_id = messagingService->getAccountID();
265 // email_mailbox_t mailbox ;
266 int email_handle = 0;
268 // memset(&mailbox, 0, sizeof(email_mailbox_t));
269 // mailbox.mailbox_name = NULL; /* all folders. */
270 // mailbox.account_id = account_id; //set account id.
274 slot_size = m_default_slot_size;
278 email_set_mail_slot_size(0, 0, slot_size);
280 // LoggerD("mailbox.account_id " << mailbox.account_id );
281 // err = email_sync_header(&mailbox, &email_handle);
282 // LoggerD("emf_handle " << emf_handle);
284 err = email_sync_header(account_id, 0, &email_handle);
285 LoggerD("email_handle " << email_handle);
287 if (err != EMAIL_ERROR_NONE) {
288 LoggerD("fail to sync all folders - err : " << err);
292 LoggerD("Insert sync request");
293 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC, messagingService);
294 m_SyncRequests.insert(std::make_pair(email_handle, data));
300 void MailSync::syncAccountCancel(const int handle)
302 LoggerD("sync cancel");
304 SyncRequestIterator it = m_SyncRequests.find(handle);
305 if ( m_SyncRequests.end() != it)
307 if ( it->second.messagingService )
308 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
312 LoggerD("Don't find cancel Sync handle : " << handle);
313 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
317 int MailSync::syncFolder(const IMessagingServicePtr& messagingService, const int folder_id, const int limit)
319 LoggerD("sync folder : " << folder_id << " limit : " << limit);
321 if (messagingService)
323 int accountId = messagingService->getAccountID();
324 LoggerD("start sync, account Id : " << accountId);
325 SyncRequestIterator it;
327 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
329 synType = it->second.syncType;
330 LoggerD("synType : " << synType);
332 if( synType != MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER )
338 const IMessagingServicePtr& messagingService = it->second.messagingService;
339 if (messagingService && messagingService->getAccountID() == accountId
340 && it->second.folderId == folder_id)
342 LoggerD("accountId is syncFolder requested already");
343 // ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Sync: " << accountId << " already requested to be Sync Account.");
347 return syncFolderInternal(messagingService, folder_id, limit);
351 LoggerD("messagingService is NULL");
358 void MailSync::syncFolderCancel(const int handle)
360 LoggerD("sync Folder Cancel");
362 SyncRequestIterator it = m_SyncRequests.find(handle);
363 if ( m_SyncRequests.end() != it)
365 if ( it->second.messagingService )
366 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
370 LoggerD("Don't find cancel Sync Folder handle : " << handle);
371 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
375 int MailSync::syncFolderInternal(const IMessagingServicePtr& messagingService, const int folder_id, const int limit)
377 LoggerD("Folder Id=" << folder_id << " limit : " << limit);
379 int account_id = messagingService->getAccountID();
381 int email_handle = 0;
384 email_mailbox_t* mailbox = NULL;
386 // char* mailbox_name = strdup(folderName.c_str());
388 err = email_get_mailbox_by_mailbox_id(folder_id, &mailbox);
389 if (EMAIL_ERROR_NONE != err) {
390 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
391 "Couldn't set mail solt size. [" << err << "]");
394 if (mailbox == NULL) {
395 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Couldn't get mailbox");
398 // char* mailbox_name = strdup(mailbox->mailbox_name);
401 slot_size = m_default_slot_size;
405 err = email_set_mail_slot_size(0, mailbox->mailbox_id, slot_size);
406 if (EMAIL_ERROR_NONE != err) {
407 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
408 "Couldn't set mail solt size. [" << err << "]");
411 // err = email_sync_header(mailbox, &email_handle);
412 err = email_sync_header(account_id, mailbox->mailbox_id, &email_handle);
413 if (err != EMAIL_ERROR_NONE) {
414 LoggerD("fail to sync folders - err : " << err);
418 LoggerD("Insert sync request");
420 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER, messagingService, folder_id);
421 m_SyncRequests.insert(std::make_pair(email_handle, data));
425 // free(mailbox_name);
427 if ( mailbox != NULL )
429 if ( EMAIL_ERROR_NONE != email_free_mailbox( &mailbox , 1) )
430 LoggerD("fail to email_free_mailbox - err ");
438 // TODO Copied from former solution, refactor it.
439 void MailSync::OnEventReceived(const DBus::MessageEvent& event)
441 LoggerD("OnEventReceived");
442 SyncNetworkStatusPtr syncNetworkStatus(new SyncNetworkStatus(event.GetArg0()));
443 int mailId = syncNetworkStatus->getMailId(); //if email body download mode.
444 int status = syncNetworkStatus->getStatus();
445 int handle = syncNetworkStatus->getHandle();
447 LoggerD("mailId : " << mailId << " status : " << status << " handle : " << handle);
448 // if Attachment Load
449 if ( status == NOTI_DOWNLOAD_ATTACH_FINISH ||status == NOTI_DOWNLOAD_ATTACH_FAIL )
452 LoggerD(" Debus mailID = " << mailId << " , Nth = " << nth );
454 SyncRequestIterator it = m_SyncRequests.begin();
455 for ( ; it != m_SyncRequests.end(); it++ )
457 const IEmailPtr& mail = it->second.mail;
459 LoggerD(" request mailID = " << mail->getUID() << " , Nth = " << (it->second.attachment)->getNth() );
460 if ( mail->getUID() == mailId && nth == (it->second.attachment)->getNth())
462 EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
463 if ( mail && requestReceiver )
465 EventMessagingServicePtr event = mail->getMessagingServiceEvent();
466 // EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
468 if (status == NOTI_DOWNLOAD_ATTACH_FINISH)
470 LoggerD(" Attachment Finish " );
471 const IAttachmentPtr& attachment = it->second.attachment;
475 email_attachment_data_t* attachment_data = NULL;
476 int attachmentId = attachment->getAttachmentID();
477 LoggerD("Attachment ID = " << attachmentId);
479 int err = email_get_attachment_data(attachmentId, &attachment_data);
480 if (err == EMAIL_ERROR_NONE) {
481 LoggerD("attachment Name : " << attachment_data->attachment_name);
482 LoggerD("attachment ID : " << attachment_data->attachment_id);
484 attachment->init(attachment_data->attachment_path, false);
485 if(attachment_data->attachment_mime_type)
487 LoggerD("attachment attachment_mime_type : " << attachment_data->attachment_mime_type);
488 attachment->setMimeType(attachment_data->attachment_mime_type);
490 LoggerD("attachment getMimeTypes : " << attachment->getMimeType());
494 LoggerD("fail to email_get_attachment_data - err : " << err);
497 if ( attachment_data != NULL )
499 email_free_attachment_data(&attachment_data, 1);
507 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
508 LoggerD(" Attachment Failed " );
511 LoggerD("remove downloadAttachment request");
512 LoggerD("handle : " << it->first );
513 requestReceiver->ManualAnswer(event);
514 m_SyncRequests.erase(it->first);
521 else if ( status == NOTI_DOWNLOAD_ATTACH_START )
523 LoggerD("DownLoading... attachment : size = " << syncNetworkStatus->getErrorCode());
527 SyncRequestIterator it = m_SyncRequests.find(handle);
528 if ( m_SyncRequests.end() != it)
530 int syncType = it->second.syncType;
531 LoggerD(" Sync ... handle : " << handle << " status : " << status << " SyncType: " << syncType);
535 case MESSAGING_SERVICE_SYNC_TYPE_SYNC:
537 LoggerD(" Sync Account");
538 const IMessagingServicePtr& messagingService = it->second.messagingService;
539 EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
541 if ( messagingService && requestReceiver)
543 EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
544 // get event using handle from m_opRequests;
547 if ( status == NOTI_DOWNLOAD_FINISH )
549 LoggerD("Sync Success");
550 requestReceiver->ManualAnswer(event);
551 m_SyncRequests.erase( handle );
553 else if ( status == NOTI_DOWNLOAD_FAIL )
555 LoggerD("Sync Fail");
556 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
557 requestReceiver->ManualAnswer(event);
558 m_SyncRequests.erase( handle );
564 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
568 case MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER:
570 LoggerD("Sync Folder");
571 const IMessagingServicePtr& messagingService = it->second.messagingService;
572 EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
574 if ( messagingService && requestReceiver)
576 EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
579 if ( status == NOTI_DOWNLOAD_FINISH )
581 LoggerD("Sync Success");
582 requestReceiver->ManualAnswer(event);
583 m_SyncRequests.erase( handle );
585 else if ( status == NOTI_DOWNLOAD_FAIL )
587 LoggerD("Sync Fail");
588 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
589 requestReceiver->ManualAnswer(event);
590 m_SyncRequests.erase( handle );
596 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
600 case MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY:
602 LoggerD(" DownLoad Body");
603 const IEmailPtr& mail = it->second.mail; // IEmailPtr
604 EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
605 if (mail && requestReceiver) {
606 EventMessagingServicePtr event = mail->getMessagingServiceEvent();
607 // EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
609 if ( status == NOTI_DOWNLOAD_BODY_FINISH )
611 event->m_message->readAllData();
612 requestReceiver->ManualAnswer(event);
613 m_SyncRequests.erase( handle );
615 else if ( status == NOTI_DOWNLOAD_BODY_FAIL )
617 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
618 requestReceiver->ManualAnswer(event);
619 m_SyncRequests.erase( handle );
624 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
632 int MailSync::downloadBodyInternal( const IEmailPtr& mail, int account_id)
635 LoggerD("downloadInternal");
638 int mailId = mail->convertId(mail->getIdRef());
639 int email_handle = 0;
641 LoggerD("folder type = " << mail->getCurrentFolder());
642 LoggerD("mail ID :" << mailId );
644 err = email_download_body(mailId, 0, &email_handle);
645 if (err != EMAIL_ERROR_NONE) {
646 LoggerD("fail to downloadBody - err : " << err);
647 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadBody request. [" << err << "]");
651 LoggerD("Insert downloadBody request");
652 LoggerD("handle : " << email_handle);
653 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY, mail);
654 m_SyncRequests.insert(std::make_pair(email_handle, data));
661 int MailSync::downloadAttachmentInternal(const IEmailPtr& mail, int account_id, const IAttachmentPtr& attachment)
663 LoggerD("downloadAttachmentInternal");
665 LoggerE("mail is NULL");
666 Throw(WrtDeviceApis::Commons::PlatformException);
671 int mailId = mail->convertId(mail->getIdRef());
672 int email_handle = 0;
674 email_mail_data_t* result = NULL;
677 error = email_get_mail_data(mailId, &result);
678 if (EMAIL_ERROR_NONE != error) {
679 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
680 "Couldn't find message " << mailId << ". [" << error << "]");
683 LoggerD("Attachment ID :" << attachment->getAttachmentID());
686 std::vector<IAttachmentPtr> attachments = mail->getAttachments();
687 std::vector<IAttachmentPtr> inlineAttachments = mail->getInlineAttachments();
688 unsigned int attachmentSize = attachments.size();
689 unsigned int inlineAttachmentSize = inlineAttachments.size();
691 LoggerD( "attachment sizes = " << attachmentSize << ",inline attachment size : " << inlineAttachmentSize);
692 for ( unsigned int i = 0 ; i < attachmentSize ; i ++)
694 LoggerD( "attachment ID is = " << attachments[i]->getAttachmentID());
695 if (attachments[i]->getAttachmentID() == attachment->getAttachmentID())
698 nth = attachments[i]->getNth();
702 for ( unsigned int i = 0 ; i < inlineAttachmentSize ; i ++)
704 LoggerD( "inline attachment ID is = " << inlineAttachments[i]->getAttachmentID());
705 if (inlineAttachments[i]->getAttachmentID() == attachment->getAttachmentID())
708 nth = inlineAttachments[i]->getNth();
713 LoggerD("nth = " << nth);
714 LoggerD("attachment Order Index = " << nth);
715 err = email_download_attachment(mailId, nth , &email_handle);
716 if (err != EMAIL_ERROR_NONE) {
717 LoggerD("fail to downloadAttachment - err : " << err);
718 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadAttachment request. [" << err << "]");
722 LoggerD("Insert downloadAttachment request");
723 LoggerD("handle : " << email_handle);
724 SyncRequestData data = SyncRequestData( email_handle,
725 MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT, mail, attachment );
726 m_SyncRequests.insert(std::make_pair(email_handle, data));
730 if ( EMAIL_ERROR_NONE != email_free_mail_data( &result , 1) )
731 LoggerD("fail to email_free_mail_data - err ");
736 void MailSync::cancelEmailJobInternal(int accountId, int handle)
738 LoggerD("cancel Email Job, account : " <<accountId << " handle : " << handle);
740 int error = email_cancel_job(accountId, handle,EMAIL_CANCELED_BY_USER);
741 if (EMAIL_ERROR_NONE != error) {
742 LoggerD("error code : " << error );
743 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
744 "Couldn't cancel email job handle: " << handle);
747 m_SyncRequests.erase(handle);