2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author Zbigniew Kostrzewa (z.kostrzewa@samsung.com)
21 #include <email-types.h>
22 #include <email-api.h>
23 #include <email-api-network.h>
24 #include <email-api-init.h>
25 #include <email-api-account.h>
27 #include <dpl/log/log.h>
28 #include <dpl/assert.h>
29 #include <Commons/Exception.h>
30 #include <Commons/ThreadPool.h>
31 #include <API/Messaging/ReqReceiverMessage.h>
32 #include <API/Messaging/EventMessagingService.h>
33 #include <API/Messaging/IAttachment.h>
36 #include "SyncNetworkStatus.h"
37 #include <API/Messaging/IMessage.h>
40 #include <vconf-keys.h>
43 const char* DBUS_FILTER_NETWORK_STATUS =
44 "type='signal',interface='User.Email.NetworkStatus'";
45 //const char* DBUS_FILTER_EMAIL_RECEIVED =
46 // "type='signal',interface='User.Email.StorageChange'";
53 using namespace WrtDeviceApis::Commons;
54 using namespace WrtDeviceApis::CommonsJavaScript;
56 MailSync& MailSync::getInstance()
58 static MailSync instance;
62 MailSync::MailSync() :
63 m_dbusThread(new DPL::Thread()),
64 m_dbus(new DBus::Connection())
68 m_dbus->setWorkerThread(m_dbusThread.Get());
69 m_dbus->AddListener(this);
70 m_dbus->SwitchAllListenersToThread(
71 ThreadPool::getInstance().getThreadRef(ThreadEnum::MESSAGING_THREAD)
73 m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
74 m_dbus->open(DBUS_BUS_SYSTEM);
77 if (EMAIL_ERROR_NONE == email_service_begin()) {
78 LogDebug("Email service Begin\n");
79 if (EMAIL_ERROR_NONE == email_open_db()) {
80 LogDebug("Email open DB success\n");
83 LogDebug("Email open DB failed\n");
87 LogDebug("Email service not started\n");
92 vconf_get_int("db/email/slot_size", &(slot_size));
94 m_default_slot_size = slot_size;
96 LogDebug( "Slot Size : " << m_default_slot_size );
100 MailSync::~MailSync()
102 m_dbus->RemoveListener(this);
105 m_dbusThread->Quit();
107 //close email service
108 if (EMAIL_ERROR_NONE == email_close_db()) {
109 LogDebug("Email Close DB Success\n");
110 if (EMAIL_ERROR_NONE == email_service_end())
112 LogDebug("Email service close Success\n");
116 LogDebug("Email service end failed\n");
120 LogDebug("Email Close DB failed\n");
124 int MailSync::downloadBody( const Api::Messaging::IEmailPtr& mail )
128 int mailId = mail->convertId(mail->getIdRef()); // get mail id
129 LogDebug("start attachment, mail Id : " << mail->getIdRef());
130 SyncRequestIterator it;
131 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
133 const Api::Messaging::IEmailPtr& email = it->second.mail;
134 LogDebug ( "Requests mail ID:" << mail->convertId(email->getIdRef()) );
135 if ( mailId == mail->convertId(email->getIdRef()))
137 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
138 "download Body: " << mailId << " already requested to be download Body.");
143 return downloadBodyInternal(mail, mail->getAccountID());
147 void MailSync::cancelDownloadBody(int handle)
151 SyncRequestIterator it = m_SyncRequests.find(handle);
152 if ( m_SyncRequests.end() != it)
154 if ( it->second.messagingService )
155 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
156 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
160 LogDebug("Don't find cancel DownloadBody handle : " << handle);
161 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
166 void MailSync::cancelDownloadAttachment(int handle)
170 SyncRequestIterator it = m_SyncRequests.find(handle);
171 if ( m_SyncRequests.end() != it)
173 if ( it->second.messagingService )
174 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
175 //cancelDownloadBodyInternal(it->second.mail, it->second.handle );
179 LogDebug("Don't find cancel DownloadAttachment handle : " << handle);
184 int MailSync::downloadAttachment(const Api::Messaging::IEmailPtr& mail, const Api::Messaging::IAttachmentPtr& attachment)
186 if ( mail && attachment )
188 //int mailId = mail->convertId(mail->getIdRef()); // get mail id
189 LogDebug("start attachment, mail Id : " << mail->getIdRef());
190 SyncRequestIterator it;
191 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
193 const Api::Messaging::IAttachmentPtr& iattachment = it->second.attachment;
194 LogDebug ( "Requests Attachment ID:" << iattachment->getAttachmentID() << " Input Attachment ID: " << attachment->getAttachmentID());
195 if (iattachment->getAttachmentID() == attachment->getAttachmentID())
197 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
198 "Attachment: " << attachment->getAttachmentID() << " already requested to be download Attachment.");
203 return downloadAttachmentInternal(mail, mail->getAccountID(), attachment);
207 int MailSync::syncAccount(const Api::Messaging::IMessagingServicePtr& messagingService, const int limit)
209 LogDebug("syncAccount : " << limit);
210 if (messagingService)
212 int accountId = messagingService->getAccountID();
213 LogDebug("start sync, account Id : " << accountId);
214 SyncRequestIterator it;
215 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
217 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
218 if (messagingService && messagingService->getAccountID() == accountId)
220 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
221 "Sync: " << accountId << " already requested to be Sync Account.");
224 return syncAccountInternal(messagingService, limit);
228 LogDebug("messagingService is NULL");
231 LogDebug("end sync" );
235 int MailSync::syncAccountInternal( const Api::Messaging::IMessagingServicePtr& messagingService, const int limit)
237 LogDebug("syncAccountInternal limit: " << limit);
239 int account_id = messagingService->getAccountID();
241 // email_mailbox_t mailbox ;
242 unsigned email_handle = 0;
244 // memset(&mailbox, 0, sizeof(email_mailbox_t));
245 // mailbox.mailbox_name = NULL; /* all folders. */
246 // mailbox.account_id = account_id; //set account id.
250 slot_size = m_default_slot_size;
254 email_set_mail_slot_size(0, 0, slot_size);
256 // LogDebug("mailbox.account_id " << mailbox.account_id );
257 // err = email_sync_header(&mailbox, &email_handle);
258 // LogDebug("emf_handle " << emf_handle);
260 err = email_sync_header(account_id, 0, &email_handle);
261 LogDebug("email_handle " << email_handle);
263 if (err != EMAIL_ERROR_NONE) {
264 LogDebug("fail to sync all folders - err : " << err);
268 LogDebug("Insert sync request");
269 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC, messagingService);
270 m_SyncRequests.insert(std::make_pair(email_handle, data));
276 void MailSync::syncAccountCancel(const int handle)
278 LogDebug("sync cancel");
281 SyncRequestIterator it = m_SyncRequests.find(handle);
282 if ( m_SyncRequests.end() != it)
284 if ( it->second.messagingService )
285 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
289 LogDebug("Don't find cancel Sync handle : " << handle);
290 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
294 int MailSync::syncFolder(const Api::Messaging::IMessagingServicePtr& messagingService, const int folder_id, const int limit)
296 LogDebug("sync folder : " << folder_id << " limit : " << limit);
298 if (messagingService)
300 int accountId = messagingService->getAccountID();
301 LogDebug("start sync, account Id : " << accountId);
302 SyncRequestIterator it;
303 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
305 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
306 if (messagingService && messagingService->getAccountID() == accountId
307 && it->second.folderId == folder_id)
309 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
310 "Sync: " << accountId << " already requested to be Sync Account.");
314 return syncFolderInternal(messagingService, folder_id, limit);
318 LogDebug("messagingService is NULL");
325 void MailSync::syncFolderCancel(const int handle)
327 LogDebug("sync Folder Cancel");
330 SyncRequestIterator it = m_SyncRequests.find(handle);
331 if ( m_SyncRequests.end() != it)
333 if ( it->second.messagingService )
334 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
338 LogDebug("Don't find cancel Sync Folder handle : " << handle);
339 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
343 int MailSync::syncFolderInternal(const Api::Messaging::IMessagingServicePtr& messagingService, const int folder_id, const int limit)
345 LogDebug("Folder Id=" << folder_id << " limit : " << limit);
347 int account_id = messagingService->getAccountID();
349 unsigned email_handle = 0;
352 email_mailbox_t* mailbox;
354 // char* mailbox_name = strdup(folderName.c_str());
356 err = email_get_mailbox_by_mailbox_id(folder_id, &mailbox);
357 if (EMAIL_ERROR_NONE != err) {
358 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
359 "Couldn't set mail solt size. [" << err << "]");
362 // char* mailbox_name = strdup(mailbox->mailbox_name);
365 slot_size = m_default_slot_size;
369 err = email_set_mail_slot_size(0, mailbox->mailbox_id, slot_size);
370 if (EMAIL_ERROR_NONE != err) {
371 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
372 "Couldn't set mail solt size. [" << err << "]");
375 // err = email_sync_header(mailbox, &email_handle);
376 err = email_sync_header(account_id, mailbox->mailbox_id, &email_handle);
377 if (err != EMAIL_ERROR_NONE) {
378 LogDebug("fail to sync folders - err : " << err);
382 LogDebug("Insert sync request");
384 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER, messagingService, folder_id);
385 m_SyncRequests.insert(std::make_pair(email_handle, data));
389 // free(mailbox_name);
392 if ( EMAIL_ERROR_NONE != email_free_mailbox( &mailbox , 1) )
393 LogDebug("fail to email_free_mailbox - err ");
399 // TODO Copied from former solution, refactor it.
400 void MailSync::OnEventReceived(const DBus::MessageEvent& event)
402 LogDebug("OnEventReceived");
403 SyncNetworkStatusPtr syncNetworkStatus(new SyncNetworkStatus(event.GetArg0()));
404 int mailId = syncNetworkStatus->getMailId(); //if email body download mode.
405 int status = syncNetworkStatus->getStatus();
406 int handle = syncNetworkStatus->getHandle();
408 // if Attachment Load
409 if ( status == NOTI_DOWNLOAD_ATTACH_FINISH ||status == NOTI_DOWNLOAD_ATTACH_FAIL )
412 LogDebug(" Debus mailID = " << mailId << " , Nth = " << nth );
414 SyncRequestIterator it = m_SyncRequests.begin();
415 for ( ; it != m_SyncRequests.end(); it++ )
417 const Api::Messaging::IEmailPtr& mail = it->second.mail;
419 LogDebug(" request mailID = " << mail->getUID() << " , Nth = " << (it->second.attachment)->getNth() );
420 if ( mail->getUID() == mailId && nth == (it->second.attachment)->getNth())
422 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
423 if ( mail && requestReceiver )
425 Api::Messaging::EventMessagingServicePtr event = mail->getMessagingServiceEvent();
427 if (status == NOTI_DOWNLOAD_ATTACH_FINISH)
429 LogDebug(" Attachment Finish " );
430 int acountId = mail->getAccountID();
431 const Api::Messaging::IAttachmentPtr& attachment = it->second.attachment;
434 // email_mailbox_t mailbox ;
435 // email_attachment_info_t *attach_info = NULL;
436 // memset(&mailbox, 0, sizeof(email_mailbox_t));
437 // mailbox.account_id = acountId; //set account id.
438 //int attachmentId = attachment->getAttachmentID();
439 // std::stringstream stream;
440 // stream << attachment->getAttachmentID();
441 // int err = email_get_attachment_info(mail->getUID(), stream.str().c_str() , &attach_info );
443 email_attachment_data_t* attachment_data = NULL;
444 int attachmentId = attachment->getAttachmentID();
445 LogDebug("Attachment ID = " << attachmentId);
447 int err = email_get_attachment_data(attachmentId, &attachment_data);
448 if (err == EMAIL_ERROR_NONE) {
449 LogDebug("attachment Name : " << attachment_data->attachment_name);
450 LogDebug("attachment ID : " << attachment_data->attachment_id);
451 attachment->init(attachment_data->attachment_path, false);
455 LogDebug("fail to email_get_attachment_data - err : " << err);
463 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
464 LogDebug(" Attachment Failed " );
467 requestReceiver->ManualAnswer(event);
468 m_SyncRequests.erase( handle );
475 else if ( status == NOTI_DOWNLOAD_ATTACH_START )
477 LogDebug("DownLoading... attachment : size = " << syncNetworkStatus->getErrorCode());
481 SyncRequestIterator it = m_SyncRequests.find(handle);
482 if ( m_SyncRequests.end() != it)
484 int syncType = it->second.syncType;
485 LogDebug(" Sync ... handle : " << handle << " status : " << status << " SyncType: " << syncType);
489 case MESSAGING_SERVICE_SYNC_TYPE_SYNC:
491 LogDebug(" Sync Account");
492 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
493 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
495 if ( messagingService && requestReceiver)
497 Api::Messaging::EventMessagingServicePtr event = messagingService->getMessagingServiceEvent();
498 if ( status == NOTI_DOWNLOAD_FINISH )
500 LogDebug("Sync Success");
501 requestReceiver->ManualAnswer(event);
502 m_SyncRequests.erase( handle );
504 else if ( status == NOTI_DOWNLOAD_FAIL )
506 LogDebug("Sync Fail");
507 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
508 requestReceiver->ManualAnswer(event);
509 m_SyncRequests.erase( handle );
514 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
518 case MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER:
520 LogDebug("Sync Folder");
521 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
522 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
524 if ( messagingService && requestReceiver)
526 Api::Messaging::EventMessagingServicePtr event = messagingService->getMessagingServiceEvent();
527 if ( status == NOTI_DOWNLOAD_FINISH )
529 LogDebug("Sync Success");
530 requestReceiver->ManualAnswer(event);
531 m_SyncRequests.erase( handle );
533 else if ( status == NOTI_DOWNLOAD_FAIL )
535 LogDebug("Sync Fail");
536 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
537 requestReceiver->ManualAnswer(event);
538 m_SyncRequests.erase( handle );
543 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
547 case MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY:
549 LogDebug(" DownLoad Body");
550 const Api::Messaging::IEmailPtr& mail = it->second.mail; // IEmailPtr
551 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
552 if (mail && requestReceiver) {
553 Api::Messaging::EventMessagingServicePtr event = mail->getMessagingServiceEvent();
554 if ( status == NOTI_DOWNLOAD_BODY_FINISH )
556 event->m_message->readAllData();
557 requestReceiver->ManualAnswer(event);
558 m_SyncRequests.erase( handle );
560 else if ( status == NOTI_DOWNLOAD_BODY_FAIL )
562 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
563 requestReceiver->ManualAnswer(event);
564 m_SyncRequests.erase( handle );
569 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
577 int MailSync::downloadBodyInternal( const Api::Messaging::IEmailPtr& mail, int account_id)
580 LogDebug("downloadInternal");
583 int mailId = mail->convertId(mail->getIdRef());
584 unsigned int email_handle = 0;
586 LogDebug("folder type = " << mail->getCurrentFolder());
587 LogDebug("mail ID :" << mailId );
589 err = email_download_body(mailId, 0, &email_handle);
590 if (err != EMAIL_ERROR_NONE) {
591 LogDebug("fail to downloadBody - err : " << err);
592 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadBody request. [" << err << "]");
596 LogDebug("Insert downloadBody request");
597 LogDebug("handle : " << email_handle);
598 SyncRequestData data = SyncRequestData(email_handle, MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY, mail);
599 m_SyncRequests.insert(std::make_pair(email_handle, data));
606 int MailSync::downloadAttachmentInternal(const Api::Messaging::IEmailPtr& mail, int account_id, const Api::Messaging::IAttachmentPtr& attachment)
608 LogDebug("downloadAttachmentInternal");
613 int mailId = mail->convertId(mail->getIdRef());
614 unsigned email_handle = 0;
616 email_mail_data_t* result = NULL;
619 error = email_get_mail_data(mailId, &result);
620 if (EMAIL_ERROR_NONE != error) {
621 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
622 "Couldn't find message " << mailId << ". [" << error << "]");
625 LogDebug("Attachment ID :" << attachment->getAttachmentID());
626 std::stringstream stream;
629 ThrowMsg(WrtDeviceApis::Commons::UnknownException,
630 "Couldn't convert e-mail attachment id");
634 std::vector<Api::Messaging::IAttachmentPtr> attachments = mail->getAttachments();
635 for ( unsigned int i = 0 ; i < attachments.size() ; i ++)
637 LogDebug( "attachment ID is = " << attachments[i]->getAttachmentID());
638 if (attachments[i]->getAttachmentID() == attachment->getAttachmentID())
646 LogDebug("nth = " << stream.str());
647 LogDebug("attachment Order Index = " << stream.str());
648 err = email_download_attachment(mailId, nth+1 , &email_handle);
649 if (err != EMAIL_ERROR_NONE) {
650 LogDebug("fail to downloadAttachment - err : " << err);
651 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadAttachment request. [" << err << "]");
655 LogDebug("Insert downloadAttachment request");
656 LogDebug("handle : " << email_handle);
657 SyncRequestData data = SyncRequestData( email_handle,
658 MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT, mail, attachment );
659 m_SyncRequests.insert(std::make_pair(email_handle, data));
663 if ( EMAIL_ERROR_NONE != email_free_mail_data( &result , 1) )
664 LogDebug("fail to email_free_mail_data - err ");
669 void MailSync::cancelEmailJobInternal(int accountId, int handle)
671 LogDebug("cancel Email Job, account : " <<accountId << " handle : " << handle);
673 int error = email_cancel_job(accountId, handle,EMAIL_CANCELED_BY_USER);
674 if (EMAIL_ERROR_NONE != error) {
675 LogDebug("error code : " << error );
676 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
677 "Couldn't cancel email job handle: " << handle);
680 m_SyncRequests.erase(handle);