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 <dpl/log/log.h>
26 #include <dpl/assert.h>
27 #include <Commons/Exception.h>
28 #include <Commons/ThreadPool.h>
29 #include "ReqReceiverMessage.h"
30 #include "EventMessagingService.h"
31 #include "IAttachment.h"
34 #include "SyncNetworkStatus.h"
38 #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;
51 using namespace WrtDeviceApis::CommonsJavaScript;
53 MailSync& MailSync::getInstance()
55 static MailSync instance;
59 MailSync::MailSync() :
60 m_dbusThread(new DPL::Thread()),
61 m_dbus(new DBus::Connection())
65 m_dbus->setWorkerThread(m_dbusThread.Get());
66 m_dbus->AddListener(this);
67 m_dbus->SwitchAllListenersToThread(
68 ThreadPool::getInstance().getThreadRef(ThreadEnum::MESSAGING_THREAD)
70 m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
71 m_dbus->open(DBUS_BUS_SYSTEM);
74 int error = email_service_begin();
75 if (error == EMAIL_ERROR_NONE) {
76 LogDebug("Email service Begin\n");
77 if (EMAIL_ERROR_NONE == email_open_db()) {
78 LogDebug("Email open DB success\n");
81 LogDebug("Email open DB failed\n");
85 LogDebug("Email service not started\n");
86 LogDebug("Error : " << error);
91 vconf_get_int("db/private/email-service/slot_size", &(slot_size));
93 m_default_slot_size = slot_size;
95 LogDebug( "Slot Size : " << m_default_slot_size );
101 m_dbus->RemoveListener(this);
104 m_dbusThread->Quit();
106 //close email service
107 if (EMAIL_ERROR_NONE == email_close_db()) {
108 LogDebug("Email Close DB Success\n");
109 if (EMAIL_ERROR_NONE == email_service_end())
111 LogDebug("Email service close Success\n");
115 LogDebug("Email service end failed\n");
119 LogDebug("Email Close DB failed\n");
123 int MailSync::downloadBody( const IEmailPtr& mail )
127 int mailId = mail->convertId(mail->getIdRef()); // get mail id
128 LogDebug("start attachment, mail Id : " << mail->getIdRef());
129 SyncRequestIterator it;
131 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
133 synType = it->second.syncType;
134 LogDebug("synType : " << synType);
136 if( synType != MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY )
141 const IEmailPtr& email = it->second.mail;
142 LogDebug ( "Requests mail ID:" << mail->convertId(email->getIdRef()) );
143 if ( mailId == mail->convertId(email->getIdRef()))
145 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
146 "download Body: " << mailId << " already requested to be download Body.");
151 return downloadBodyInternal(mail, mail->getAccountID());
155 void MailSync::cancelDownloadBody(int handle)
159 SyncRequestIterator it = m_SyncRequests.find(handle);
160 if ( m_SyncRequests.end() != it)
162 if ( it->second.messagingService )
163 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
164 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
168 LogDebug("Don't find cancel DownloadBody handle : " << handle);
169 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
174 void MailSync::cancelDownloadAttachment(int handle)
178 SyncRequestIterator it = m_SyncRequests.find(handle);
179 if ( m_SyncRequests.end() != it)
181 if ( it->second.messagingService )
182 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
183 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
187 LogDebug("Don't find cancel DownloadAttachment handle : " << handle);
192 int MailSync::downloadAttachment(const IEmailPtr& mail, const IAttachmentPtr& attachment)
194 if ( mail && attachment )
196 //int mailId = mail->convertId(mail->getIdRef()); // get mail id
197 LogDebug("start attachment, mail Id : " << mail->getIdRef());
198 SyncRequestIterator it;
200 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
202 synType = it->second.syncType;
203 LogDebug("synType : " << synType);
205 if( synType != MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT )
211 const IAttachmentPtr& iattachment = it->second.attachment;
212 LogDebug ( "Requests Attachment ID:" << iattachment->getAttachmentID() << " Input Attachment ID: " << attachment->getAttachmentID());
213 if (iattachment->getAttachmentID() == attachment->getAttachmentID())
215 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
216 "Attachment: " << attachment->getAttachmentID() << " already requested to be download Attachment.");
221 return downloadAttachmentInternal(mail, mail->getAccountID(), attachment);
225 int MailSync::syncAccount(const IMessagingServicePtr& messagingService, const int limit)
227 LogDebug("syncAccount : " << limit);
228 if (messagingService)
230 int accountId = messagingService->getAccountID();
231 LogDebug("start sync, account Id : " << accountId);
232 SyncRequestIterator it;
234 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
236 synType = it->second.syncType;
237 LogDebug("synType : " << synType);
239 if( synType != MESSAGING_SERVICE_SYNC_TYPE_SYNC )
245 const IMessagingServicePtr& messagingService = it->second.messagingService;
246 if (messagingService && messagingService->getAccountID() == accountId)
248 LogDebug("accountId is sync requested already");
249 // ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Sync: " << accountId << " already requested to be Sync Account.");
252 return syncAccountInternal(messagingService, limit);
256 LogDebug("messagingService is NULL");
259 LogDebug("end sync" );
263 int MailSync::syncAccountInternal( const IMessagingServicePtr& messagingService, const int limit)
265 LogDebug("syncAccountInternal limit: " << limit);
267 int account_id = messagingService->getAccountID();
269 // email_mailbox_t mailbox ;
270 int email_handle = 0;
272 // memset(&mailbox, 0, sizeof(email_mailbox_t));
273 // mailbox.mailbox_name = NULL; /* all folders. */
274 // mailbox.account_id = account_id; //set account id.
278 slot_size = m_default_slot_size;
282 email_set_mail_slot_size(0, 0, slot_size);
284 // LogDebug("mailbox.account_id " << mailbox.account_id );
285 // err = email_sync_header(&mailbox, &email_handle);
286 // LogDebug("emf_handle " << emf_handle);
288 err = email_sync_header(account_id, 0, &email_handle);
289 LogDebug("email_handle " << email_handle);
291 if (err != EMAIL_ERROR_NONE) {
292 LogDebug("fail to sync all folders - err : " << err);
296 LogDebug("Insert sync request");
297 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC, messagingService);
298 m_SyncRequests.insert(std::make_pair(email_handle, data));
304 void MailSync::syncAccountCancel(const int handle)
306 LogDebug("sync cancel");
309 SyncRequestIterator it = m_SyncRequests.find(handle);
310 if ( m_SyncRequests.end() != it)
312 if ( it->second.messagingService )
313 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
317 LogDebug("Don't find cancel Sync handle : " << handle);
318 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
322 int MailSync::syncFolder(const IMessagingServicePtr& messagingService, const int folder_id, const int limit)
324 LogDebug("sync folder : " << folder_id << " limit : " << limit);
326 if (messagingService)
328 int accountId = messagingService->getAccountID();
329 LogDebug("start sync, account Id : " << accountId);
330 SyncRequestIterator it;
332 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
334 synType = it->second.syncType;
335 LogDebug("synType : " << synType);
337 if( synType != MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER )
343 const IMessagingServicePtr& messagingService = it->second.messagingService;
344 if (messagingService && messagingService->getAccountID() == accountId
345 && it->second.folderId == folder_id)
347 LogDebug("accountId is syncFolder requested already");
348 // ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Sync: " << accountId << " already requested to be Sync Account.");
352 return syncFolderInternal(messagingService, folder_id, limit);
356 LogDebug("messagingService is NULL");
363 void MailSync::syncFolderCancel(const int handle)
365 LogDebug("sync Folder Cancel");
368 SyncRequestIterator it = m_SyncRequests.find(handle);
369 if ( m_SyncRequests.end() != it)
371 if ( it->second.messagingService )
372 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
376 LogDebug("Don't find cancel Sync Folder handle : " << handle);
377 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
381 int MailSync::syncFolderInternal(const IMessagingServicePtr& messagingService, const int folder_id, const int limit)
383 LogDebug("Folder Id=" << folder_id << " limit : " << limit);
385 int account_id = messagingService->getAccountID();
387 int email_handle = 0;
390 email_mailbox_t* mailbox = NULL;
392 // char* mailbox_name = strdup(folderName.c_str());
394 err = email_get_mailbox_by_mailbox_id(folder_id, &mailbox);
395 if (EMAIL_ERROR_NONE != err) {
396 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
397 "Couldn't set mail solt size. [" << err << "]");
400 if (mailbox == NULL) {
401 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Couldn't get mailbox");
404 // char* mailbox_name = strdup(mailbox->mailbox_name);
407 slot_size = m_default_slot_size;
411 err = email_set_mail_slot_size(0, mailbox->mailbox_id, slot_size);
412 if (EMAIL_ERROR_NONE != err) {
413 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
414 "Couldn't set mail solt size. [" << err << "]");
417 // err = email_sync_header(mailbox, &email_handle);
418 err = email_sync_header(account_id, mailbox->mailbox_id, &email_handle);
419 if (err != EMAIL_ERROR_NONE) {
420 LogDebug("fail to sync folders - err : " << err);
424 LogDebug("Insert sync request");
426 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER, messagingService, folder_id);
427 m_SyncRequests.insert(std::make_pair(email_handle, data));
431 // free(mailbox_name);
433 if ( mailbox != NULL )
435 if ( EMAIL_ERROR_NONE != email_free_mailbox( &mailbox , 1) )
436 LogDebug("fail to email_free_mailbox - err ");
444 // TODO Copied from former solution, refactor it.
445 void MailSync::OnEventReceived(const DBus::MessageEvent& event)
447 LogDebug("OnEventReceived");
448 SyncNetworkStatusPtr syncNetworkStatus(new SyncNetworkStatus(event.GetArg0()));
449 int mailId = syncNetworkStatus->getMailId(); //if email body download mode.
450 int status = syncNetworkStatus->getStatus();
451 int handle = syncNetworkStatus->getHandle();
453 LogDebug("mailId : " << mailId << " status : " << status << " handle : " << handle);
454 // if Attachment Load
455 if ( status == NOTI_DOWNLOAD_ATTACH_FINISH ||status == NOTI_DOWNLOAD_ATTACH_FAIL )
458 LogDebug(" Debus mailID = " << mailId << " , Nth = " << nth );
460 SyncRequestIterator it = m_SyncRequests.begin();
461 for ( ; it != m_SyncRequests.end(); it++ )
463 const IEmailPtr& mail = it->second.mail;
465 LogDebug(" request mailID = " << mail->getUID() << " , Nth = " << (it->second.attachment)->getNth() );
466 if ( mail->getUID() == mailId && nth == (it->second.attachment)->getNth())
468 EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
469 if ( mail && requestReceiver )
471 EventMessagingServicePtr event = mail->getMessagingServiceEvent();
472 // EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
474 if (status == NOTI_DOWNLOAD_ATTACH_FINISH)
476 LogDebug(" Attachment Finish " );
477 const IAttachmentPtr& attachment = it->second.attachment;
481 email_attachment_data_t* attachment_data = NULL;
482 int attachmentId = attachment->getAttachmentID();
483 LogDebug("Attachment ID = " << attachmentId);
485 int err = email_get_attachment_data(attachmentId, &attachment_data);
486 if (err == EMAIL_ERROR_NONE) {
487 LogDebug("attachment Name : " << attachment_data->attachment_name);
488 LogDebug("attachment ID : " << attachment_data->attachment_id);
489 attachment->init(attachment_data->attachment_path, false);
493 LogDebug("fail to email_get_attachment_data - err : " << err);
496 if ( attachment_data != NULL )
498 email_free_attachment_data(&attachment_data, 1);
506 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
507 LogDebug(" Attachment Failed " );
510 LogDebug("remove downloadAttachment request");
511 LogDebug("handle : " << it->first );
512 requestReceiver->ManualAnswer(event);
513 m_SyncRequests.erase(it->first);
520 else if ( status == NOTI_DOWNLOAD_ATTACH_START )
522 LogDebug("DownLoading... attachment : size = " << syncNetworkStatus->getErrorCode());
526 SyncRequestIterator it = m_SyncRequests.find(handle);
527 if ( m_SyncRequests.end() != it)
529 int syncType = it->second.syncType;
530 LogDebug(" Sync ... handle : " << handle << " status : " << status << " SyncType: " << syncType);
534 case MESSAGING_SERVICE_SYNC_TYPE_SYNC:
536 LogDebug(" Sync Account");
537 const IMessagingServicePtr& messagingService = it->second.messagingService;
538 EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
540 if ( messagingService && requestReceiver)
542 EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
543 // get event using handle from m_opRequests;
544 if ( status == NOTI_DOWNLOAD_FINISH )
546 LogDebug("Sync Success");
547 requestReceiver->ManualAnswer(event);
548 m_SyncRequests.erase( handle );
550 else if ( status == NOTI_DOWNLOAD_FAIL )
552 LogDebug("Sync Fail");
553 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
554 requestReceiver->ManualAnswer(event);
555 m_SyncRequests.erase( handle );
560 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
564 case MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER:
566 LogDebug("Sync Folder");
567 const IMessagingServicePtr& messagingService = it->second.messagingService;
568 EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
570 if ( messagingService && requestReceiver)
572 EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
573 if ( status == NOTI_DOWNLOAD_FINISH )
575 LogDebug("Sync Success");
576 requestReceiver->ManualAnswer(event);
577 m_SyncRequests.erase( handle );
579 else if ( status == NOTI_DOWNLOAD_FAIL )
581 LogDebug("Sync Fail");
582 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
583 requestReceiver->ManualAnswer(event);
584 m_SyncRequests.erase( handle );
589 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
593 case MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY:
595 LogDebug(" DownLoad Body");
596 const IEmailPtr& mail = it->second.mail; // IEmailPtr
597 EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
598 if (mail && requestReceiver) {
599 EventMessagingServicePtr event = mail->getMessagingServiceEvent();
600 // EventMessagingServicePtr event = messagingService->getEventFromHandle(handle);
602 if ( status == NOTI_DOWNLOAD_BODY_FINISH )
604 event->m_message->readAllData();
605 requestReceiver->ManualAnswer(event);
606 m_SyncRequests.erase( handle );
608 else if ( status == NOTI_DOWNLOAD_BODY_FAIL )
610 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
611 requestReceiver->ManualAnswer(event);
612 m_SyncRequests.erase( handle );
617 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
625 int MailSync::downloadBodyInternal( const IEmailPtr& mail, int account_id)
628 LogDebug("downloadInternal");
631 int mailId = mail->convertId(mail->getIdRef());
632 int email_handle = 0;
634 LogDebug("folder type = " << mail->getCurrentFolder());
635 LogDebug("mail ID :" << mailId );
637 err = email_download_body(mailId, 0, &email_handle);
638 if (err != EMAIL_ERROR_NONE) {
639 LogDebug("fail to downloadBody - err : " << err);
640 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadBody request. [" << err << "]");
644 LogDebug("Insert downloadBody request");
645 LogDebug("handle : " << email_handle);
646 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY, mail);
647 m_SyncRequests.insert(std::make_pair(email_handle, data));
654 int MailSync::downloadAttachmentInternal(const IEmailPtr& mail, int account_id, const IAttachmentPtr& attachment)
656 LogDebug("downloadAttachmentInternal");
661 int mailId = mail->convertId(mail->getIdRef());
662 int email_handle = 0;
664 email_mail_data_t* result = NULL;
667 error = email_get_mail_data(mailId, &result);
668 if (EMAIL_ERROR_NONE != error) {
669 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
670 "Couldn't find message " << mailId << ". [" << error << "]");
673 LogDebug("Attachment ID :" << attachment->getAttachmentID());
676 std::vector<IAttachmentPtr> attachments = mail->getAttachments();
677 std::vector<IAttachmentPtr> inlineAttachments = mail->getInlineAttachments();
678 unsigned int attachmentSize = attachments.size();
679 unsigned int inlineAttachmentSize = inlineAttachments.size();
681 LogDebug( "attachment sizes = " << attachmentSize << ",inline attachment size : " << inlineAttachmentSize);
682 for ( unsigned int i = 0 ; i < attachmentSize ; i ++)
684 LogDebug( "attachment ID is = " << attachments[i]->getAttachmentID());
685 if (attachments[i]->getAttachmentID() == attachment->getAttachmentID())
688 nth = attachments[i]->getNth();
692 for ( unsigned int i = 0 ; i < inlineAttachmentSize ; i ++)
694 LogDebug( "inline attachment ID is = " << inlineAttachments[i]->getAttachmentID());
695 if (inlineAttachments[i]->getAttachmentID() == attachment->getAttachmentID())
698 nth = inlineAttachments[i]->getNth();
703 LogDebug("nth = " << nth);
704 LogDebug("attachment Order Index = " << nth);
705 err = email_download_attachment(mailId, nth , &email_handle);
706 if (err != EMAIL_ERROR_NONE) {
707 LogDebug("fail to downloadAttachment - err : " << err);
708 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadAttachment request. [" << err << "]");
712 LogDebug("Insert downloadAttachment request");
713 LogDebug("handle : " << email_handle);
714 SyncRequestData data = SyncRequestData( email_handle,
715 MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT, mail, attachment );
716 m_SyncRequests.insert(std::make_pair(email_handle, data));
720 if ( EMAIL_ERROR_NONE != email_free_mail_data( &result , 1) )
721 LogDebug("fail to email_free_mail_data - err ");
726 void MailSync::cancelEmailJobInternal(int accountId, int handle)
728 LogDebug("cancel Email Job, account : " <<accountId << " handle : " << handle);
730 int error = email_cancel_job(accountId, handle,EMAIL_CANCELED_BY_USER);
731 if (EMAIL_ERROR_NONE != error) {
732 LogDebug("error code : " << error );
733 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
734 "Couldn't cancel email job handle: " << handle);
737 m_SyncRequests.erase(handle);