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 <emf-types.h>
23 #include <Emf_Mapi_Network.h>
24 #include <Emf_Mapi_Init.h>
25 #include <Emf_Mapi_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 (EMF_ERROR_NONE == email_service_begin()) {
78 LogDebug("Email service Begin\n");
79 if (EMF_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 (EMF_ERROR_NONE == email_close_db()) {
109 LogDebug("Email Close DB Success\n");
110 if (EMF_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 int MailSync::downloadAttachment(const Api::Messaging::IEmailPtr& mail, const Api::Messaging::IAttachmentPtr& attachment)
168 if ( mail && attachment )
170 int mailId = mail->convertId(mail->getIdRef()); // get mail id
171 LogDebug("start attachment, mail Id : " << mail->getIdRef());
172 SyncRequestIterator it;
173 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
175 const Api::Messaging::IAttachmentPtr& iattachment = it->second.attachment;
176 LogDebug ( "Requests Attachment ID:" << iattachment->getAttachmentID() << " Input Attachment ID: " << attachment->getAttachmentID());
177 if (iattachment->getAttachmentID() == attachment->getAttachmentID())
179 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
180 "Attachment: " << attachment->getAttachmentID() << " already requested to be download Attachment.");
185 return downloadAttachmentInternal(mail, mail->getAccountID(), attachment);
189 int MailSync::syncAccount(const Api::Messaging::IMessagingServicePtr& messagingService, const int limit)
191 LogDebug("syncAccount : " << limit);
192 if (messagingService)
194 int accountId = messagingService->getAccountID();
195 LogDebug("start sync, account Id : " << accountId);
196 SyncRequestIterator it;
197 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
199 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
200 if (messagingService && messagingService->getAccountID() == accountId)
202 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
203 "Sync: " << accountId << " already requested to be Sync Account.");
206 return syncAccountInternal(messagingService, limit);
210 LogDebug("messagingService is NULL");
213 LogDebug("end sync" );
217 int MailSync::syncAccountInternal( const Api::Messaging::IMessagingServicePtr& messagingService, const int limit)
219 LogDebug("syncAccountInternal limit: " << limit);
221 int account_id = messagingService->getAccountID();
223 emf_mailbox_t mailbox ;
224 unsigned emf_handle = 0;
226 memset(&mailbox, 0, sizeof(emf_mailbox_t));
227 mailbox.name = NULL; /* all folders. */
228 mailbox.account_id = account_id; //set account id.
232 slot_size = m_default_slot_size;
236 email_set_mail_slot_size(0, NULL, slot_size);
238 LogDebug("mailbox.account_id " << mailbox.account_id );
239 err = email_sync_header(&mailbox, &emf_handle);
240 LogDebug("emf_handle " << emf_handle);
242 if (err != EMF_ERROR_NONE) {
243 LogDebug("fail to sync all folders - err : " << err);
247 LogDebug("Insert sync request");
248 SyncRequestData data = SyncRequestData(emf_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC, messagingService);
249 m_SyncRequests.insert(std::make_pair(emf_handle, data));
255 void MailSync::syncAccountCancel(const int handle)
257 LogDebug("sync cancel");
260 SyncRequestIterator it = m_SyncRequests.find(handle);
261 if ( m_SyncRequests.end() != it)
263 if ( it->second.messagingService )
264 cancelEmailJobInternal( it->second.messagingService->getAccountID() , it->second.handle);
268 LogDebug("Don't find cancel Sync handle : " << handle);
269 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
273 int MailSync::syncFolder(const Api::Messaging::IMessagingServicePtr& messagingService, const std::string& folderName, const int limit)
275 LogDebug("sync folder : " << folderName << " limit : " << limit);
277 if (messagingService)
279 int accountId = messagingService->getAccountID();
280 LogDebug("start sync, account Id : " << accountId);
281 SyncRequestIterator it;
282 for( it = m_SyncRequests.begin(); it != m_SyncRequests.end(); ++it)
284 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
285 if (messagingService && messagingService->getAccountID() == accountId
286 && it->second.folderName == folderName)
288 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
289 "Sync: " << accountId << " already requested to be Sync Account.");
293 return syncFolderInternal(messagingService, folderName, limit);
297 LogDebug("messagingService is NULL");
304 void MailSync::syncFolderCancel(const int handle)
306 LogDebug("sync Folder 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 Folder handle : " << handle);
318 //ThrowMsg(WrtDeviceApis::Commons::NotFoundException, "Email: " << mailId << " not found.");
322 int MailSync::syncFolderInternal(const Api::Messaging::IMessagingServicePtr& messagingService, const std::string& folderName, const int limit)
324 LogDebug("Folder Name=" << folderName << " limit : " << limit);
326 int account_id = messagingService->getAccountID();
327 emf_mailbox_t mailbox;
328 gchar *src_box =g_strdup( folderName.c_str() );
329 unsigned emf_handle = 0;
332 memset(&mailbox, 0, sizeof(emf_mailbox_t));
333 mailbox.name = src_box;
334 mailbox.account_id = account_id;
338 slot_size = m_default_slot_size;
342 email_set_mail_slot_size(0, src_box, slot_size);
344 err = email_sync_header(&mailbox, &emf_handle);
345 if (err != EMF_ERROR_NONE) {
346 LogDebug("fail to sync folders - err : " << err);
350 LogDebug("Insert sync request");
352 SyncRequestData data = SyncRequestData(emf_handle, MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER, messagingService, folderName);
353 m_SyncRequests.insert(std::make_pair(emf_handle, data));
364 // TODO Copied from former solution, refactor it.
365 void MailSync::OnEventReceived(const DBus::MessageEvent& event)
367 LogDebug("OnEventReceived");
368 SyncNetworkStatusPtr syncNetworkStatus(new SyncNetworkStatus(event.GetArg0()));
369 int mailId = syncNetworkStatus->getMailId(); //if email body download mode.
370 int status = syncNetworkStatus->getStatus();
371 int handle = syncNetworkStatus->getHandle();
373 // if Attachment Load
374 if ( status == NOTI_DOWNLOAD_ATTACH_FINISH ||
375 status == NOTI_DOWNLOAD_ATTACH_FAIL )
378 LogDebug(" Debus mailID = " << mailId << " , Nth = " << nth );
380 SyncRequestIterator it = m_SyncRequests.begin();
381 for ( it; it != m_SyncRequests.end(); it++ )
383 const Api::Messaging::IEmailPtr& mail = it->second.mail;
385 LogDebug(" request mailID = " << mail->getUID() << " , Nth = " << (it->second.attachment)->getNth() );
386 if ( mail->getUID() == mailId && nth == (it->second.attachment)->getNth())
388 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
389 if ( mail && requestReceiver )
391 Api::Messaging::EventMessagingServicePtr event = mail->getMessagingServiceEvent();
393 if (status == NOTI_DOWNLOAD_ATTACH_FINISH)
395 LogDebug(" Attachment Finish " );
396 int acountId = mail->getAccountID();
397 const Api::Messaging::IAttachmentPtr& attachment = it->second.attachment;
400 emf_mailbox_t mailbox ;
401 emf_attachment_info_t *attach_info = NULL;
402 memset(&mailbox, 0, sizeof(emf_mailbox_t));
403 mailbox.account_id = acountId; //set account id.
404 int attachmentId = attachment->getAttachmentID();
405 std::stringstream stream;
406 stream << attachment->getAttachmentID();
407 LogDebug("Attachment ID = " << stream.str());
409 int err = email_get_attachment_info( &mailbox, mail->getUID(), stream.str().c_str() , &attach_info );
410 if (err == EMF_ERROR_NONE) {
411 LogDebug("attachment Name : " << attach_info->name);
412 LogDebug("attachment ID : " << attach_info->attachment_id);
413 attachment->init(attach_info->savename, false);
417 LogDebug("fail to email_get_attachment_info - err : " << err);
425 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
426 LogDebug(" Attachment Failed " );
429 requestReceiver->ManualAnswer(event);
430 m_SyncRequests.erase( handle );
438 else if ( status == NOTI_DOWNLOAD_ATTACH_START )
440 LogDebug("DownLoading... attachment : size = " << syncNetworkStatus->getErrorCode());
444 SyncRequestIterator it = m_SyncRequests.find(handle);
445 if ( m_SyncRequests.end() != it)
447 int syncType = it->second.syncType;
448 LogDebug(" Sync ... handle : " << handle << " status : " << status << " SyncType: " << syncType);
452 case MESSAGING_SERVICE_SYNC_TYPE_SYNC:
454 LogDebug(" Sync Account");
455 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
456 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
458 if ( messagingService && requestReceiver)
460 Api::Messaging::EventMessagingServicePtr event = messagingService->getMessagingServiceEvent();
461 if ( status == NOTI_DOWNLOAD_FINISH )
463 LogDebug("Sync Success");
464 requestReceiver->ManualAnswer(event);
465 m_SyncRequests.erase( handle );
467 else if ( status == NOTI_DOWNLOAD_FAIL )
469 LogDebug("Sync Fail");
470 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
471 requestReceiver->ManualAnswer(event);
472 m_SyncRequests.erase( handle );
477 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
482 case MESSAGING_SERVICE_SYNC_TYPE_SYNC_FOLDER:
484 LogDebug("Sync Folder");
485 const Api::Messaging::IMessagingServicePtr& messagingService = it->second.messagingService;
486 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = messagingService->getRequestReceiver();
488 if ( messagingService && requestReceiver)
490 Api::Messaging::EventMessagingServicePtr event = messagingService->getMessagingServiceEvent();
491 if ( status == NOTI_DOWNLOAD_FINISH )
493 LogDebug("Sync Success");
494 requestReceiver->ManualAnswer(event);
495 m_SyncRequests.erase( handle );
497 else if ( status == NOTI_DOWNLOAD_FAIL )
499 LogDebug("Sync Fail");
500 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException );
501 requestReceiver->ManualAnswer(event);
502 m_SyncRequests.erase( handle );
507 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
511 case MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY:
513 LogDebug(" DownLoad Body");
514 const Api::Messaging::IEmailPtr& mail = it->second.mail; // IEmailPtr
515 Api::Messaging::EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
516 if (mail && requestReceiver) {
517 Api::Messaging::EventMessagingServicePtr event = mail->getMessagingServiceEvent();
518 if ( status == NOTI_DOWNLOAD_BODY_FINISH )
520 requestReceiver->ManualAnswer(event);
521 m_SyncRequests.erase( handle );
523 else if ( status == NOTI_DOWNLOAD_BODY_FAIL )
525 event->setExceptionCode( WrtDeviceApis::Commons::ExceptionCodes::UnknownException);
526 requestReceiver->ManualAnswer(event);
527 m_SyncRequests.erase( handle );
532 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "request Receiver is NULL. ");
545 int MailSync::downloadBodyInternal( const Api::Messaging::IEmailPtr& mail, int account_id)
548 LogDebug("downloadInternal");
551 int mailId = mail->convertId(mail->getIdRef());
552 unsigned int emf_handle = 0;
555 LogDebug("folder type = " << mail->getCurrentFolder());
557 emf_mailbox_t mailbox;
558 memset(&mailbox, 0, sizeof(emf_mailbox_t));
560 mailbox.name = strdup("INBOX");
562 mailbox.account_id = account_id; //set account id.
563 LogDebug("mailbox.account_id " << mailbox.account_id << " mailId : " << mailId);
564 err = email_download_body(&mailbox, mailId, 0, &emf_handle);
566 if (err != EMF_ERROR_NONE) {
567 LogDebug("fail to downloadBody - err : " << err);
568 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadBody request. [" << err << "]");
572 LogDebug("Insert downloadBody request");
573 LogDebug("handle : " << emf_handle);
574 SyncRequestData data = SyncRequestData(emf_handle, MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_BODY, mail);
575 m_SyncRequests.insert(std::make_pair(emf_handle, data));
582 int MailSync::downloadAttachmentInternal(const Api::Messaging::IEmailPtr& mail, int account_id, const Api::Messaging::IAttachmentPtr& attachment)
584 LogDebug("downloadAttachmentInternal");
589 int mailId = mail->convertId(mail->getIdRef());
590 unsigned emf_handle = 0;
592 emf_mailbox_t mailbox;
593 //gchar *src_box = g_strdup(folder_name);
594 memset(&mailbox, 0, sizeof(emf_mailbox_t));
595 mailbox.account_id = account_id; //set account id.
596 LogDebug("mailbox.account_id " << mailbox.account_id );
597 LogDebug("Attachment ID :" << attachment->getAttachmentID());
599 std::stringstream stream;
600 //stream << attachment->getAttachmentID();
603 ThrowMsg(WrtDeviceApis::Commons::UnknownException,
604 "Couldn't convert e-mail attachment id");
608 std::vector<Api::Messaging::IAttachmentPtr> attachments = mail->getAttachments();
609 for ( int i = 0 ; i < attachments.size() ; i ++)
611 LogDebug( "attachment ID is = " << attachments[i]->getAttachmentID());
612 if (attachments[i]->getAttachmentID() == attachment->getAttachmentID())
620 LogDebug("nth = " << stream.str());
622 LogDebug("attachment Order Index = " << stream.str());
623 err = email_download_attachment(&mailbox, mailId, stream.str().c_str() , &emf_handle);
624 if (err != EMF_ERROR_NONE) {
625 LogDebug("fail to downloadAttachment - err : " << err);
626 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Failed to initialize downloadAttachment request. [" << err << "]");
630 LogDebug("Insert downloadAttachment request");
631 LogDebug("handle : " << emf_handle);
632 SyncRequestData data = SyncRequestData( emf_handle,
633 MESSAGING_SERVICE_SYNC_TYPE_DOWNLOAD_ATTACHMENT, mail, attachment );
634 m_SyncRequests.insert(std::make_pair(emf_handle, data));
641 void MailSync::cancelEmailJobInternal(int accountId, int handle)
643 LogDebug("cancel Email Job, account : " <<accountId << " handle : " << handle);
645 int error = email_cancel_job(accountId, handle);
646 if (EMF_ERROR_NONE != error) {
647 LogDebug("error code : " << error );
648 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
649 "Couldn't cancel email job handle: " << handle);
652 m_SyncRequests.erase(handle);