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.
22 * @author Pawel Misiak (p.misiak@samsung.com)
30 #include <emf-types.h>
32 #include <dpl/log/log.h>
33 #include <dpl/assert.h>
34 #include <dpl/scoped_fclose.h>
35 #include <dpl/scoped_ptr.h>
36 #include <Commons/Exception.h>
37 #include <Commons/StringUtils.h>
38 #include <API/Messaging/MessageFactory.h>
39 #include "Messaging.h"
41 #include "EmailService.h"
42 #include "EmailUtils.h"
43 #include "EmailConverter.h"
44 #include "MailSender.h"
46 #include "MessagingService.h"
47 #include "MessagingServiceManager.h"
48 #include "Attachment.h"
50 #define LOG_ENTER LogDebug("---> ENTER");
51 #define LOG_EXIT LogDebug("---> EXIT");
54 using namespace TizenApis::Api::Messaging;
55 using namespace WrtDeviceApis::Commons;
66 const Api::Messaging::FolderType DEFAULT_FOLDER = Api::Messaging::OUTBOX;
67 const char* DEFAULT_FOLDER_NAME = EMF_OUTBOX_NAME;
69 const Api::Messaging::FolderType DEFAULT_FOLDER = Api::Messaging::DRAFTBOX;
70 const char* DEFAULT_FOLDER_NAME = EMF_DRAFTBOX_NAME;
76 const char* TEMP_FOLDER = "/tmp";
77 const char* COMMAND_NAME = "/bin/cp";
78 const char* COMMAND_SWITCH_RECURSIVE = "-r";
79 const char* COMMAND_SWITCH_FORCE = "-f";
82 Email::Email(const string& id) :
87 if (getIdRef().empty()) {
89 ThrowMsg(WrtDeviceApis::Commons::PlatformException, " message id is invalid");
93 } catch (const WrtDeviceApis::Commons::PlatformException& ex) {
94 LogError("Exception: " << ex.DumpToString());
100 Email::Email(const std::string& id, int accountId) :
106 if (getIdRef().empty()) {
108 ThrowMsg(WrtDeviceApis::Commons::PlatformException, " message id is invalid");
111 LogDebug("Account ID = " << accountId);
112 m_accountId = accountId;
115 } catch (const WrtDeviceApis::Commons::PlatformException& ex) {
116 LogError("Exception: " << ex.DumpToString());
123 Email::Email(Api::Messaging::EmailAccountInfo& account) : IMessage(EMAIL)
128 if (getIdRef().empty()) {
134 catch (const WrtDeviceApis::Commons::PlatformException& ex) {
135 LogError("Exception: " << ex.DumpToString());
141 Email::Email(const Api::Messaging::FolderType folder) : IMessage(EMAIL)
146 if (folder == Api::Messaging::TEMP_FOLDER) {
150 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Folder Type is miss-matched");
153 catch (const WrtDeviceApis::Commons::PlatformException& ex) {
154 LogError("Exception: " << ex.DumpToString());
171 int handle = MailSender::getInstance().send(
172 Api::Messaging::MessageFactory::convertToEmail(SharedFromThis())
179 void Email::sendCancel(int handle)
183 MailSender::getInstance().cancel(handle);
188 int Email::downloadBody()
192 return MailSync::getInstance().downloadBody( Api::Messaging::MessageFactory::convertToEmail(SharedFromThis()) );
197 void Email::downloadBodyCancel( int handle)
203 int Email::downloadAttachment( const Api::Messaging::IAttachmentPtr& attachment)
207 return MailSync::getInstance().downloadAttachment( Api::Messaging::MessageFactory::convertToEmail(SharedFromThis()), attachment );
212 void Email::update(bool draftsOnly)
216 DPL::Mutex::ScopedLock mx(&m_updateMutex);
219 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
222 LogDebug("getCurrentFolder() = " << getCurrentFolder() );
223 if (!draftsOnly || (getCurrentFolder() == Api::Messaging::DRAFTBOX)) {
231 LogWarning("Updating only read status. Folder: " << getCurrentFolder());
235 int error = email_update_message(getIntId(), m_mail.Get());
236 if (EMF_ERROR_NONE != error) {
237 LogWarning("Nothing to update or error. [" << error << "]");
243 int Email::getAccountID()
248 return m_mail->info->account_id;
260 return m_mail->info->uid;
267 int Email::isBodyDownloaded()
271 return m_mail->info->body_downloaded;
276 bool Email::hasAttachment()
278 std::size_t attachmentSize = getAttachmentsCount();
279 if ( attachmentSize > 0)
285 void Email::readAllData()
290 void Email::moveToFolder(const FolderType newFolder)
294 moveToFolder(EmailConverter::toMailboxName(newFolder));
299 void Email::moveToFolder(const string& newFolder)
303 int accountId = Messaging::getInstance().getEmailAccountId(getFromRef());
304 ScopedMailbox mailbox(
305 EmailService::createMailbox(accountId, newFolder.c_str())
308 int mailId = getIntId();
310 int error = email_move_mail_to_mailbox(&mailId, 1, mailbox.Get());
311 if (EMF_ERROR_NONE != error) {
313 WrtDeviceApis::Commons::PlatformException,
314 "Couldn't move mail to folder: " << newFolder << ". [" <<
319 void Email::copyToFolder(const FolderType newFolder)
323 copyToFolder(EmailConverter::toMailboxName(newFolder));
328 void Email::copyToFolder(const string& newFolder)
334 int accountId = Messaging::getInstance().getEmailAccountId(getFromRef());
336 ScopedMail mail(EmailService::cloneMail(m_mail.Get()));
337 ScopedMailbox mailbox(
338 EmailService::createMailbox(accountId, newFolder.c_str())
341 int mailId = EmailService::addMailToMailbox(mail.Get(), mailbox.Get());
342 // TODO Is following check necessary?
344 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Cloned mail didn't get new id.");
352 EmailService::deleteMail(m_accountId, getIntId());
360 EmailAccountInfo account = IMessaging::getInstance().getCurrentEmailAccount();
361 m_accountId = account.getIntId();
362 ScopedMail mail(EmailService::createMail(account));
363 ScopedMailbox mailbox(
364 EmailService::getMailboxByType(account.getIntId(),
365 EMF_MAILBOX_TYPE_DRAFT)
367 setId(convertId(EmailService::addMailToMailbox(mail.Get(), mailbox.Get())));
368 setFolderType(Api::Messaging::DRAFTBOX);
369 setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
378 setFolderType(Api::Messaging::TEMP_FOLDER);
379 setMessageStatus(Api::Messaging::MESSAGE_STATUS_CREATED);
383 void Email::create( Api::Messaging::EmailAccountInfo& account )
387 m_accountId = account.getIntId();
388 MailSender::getInstance();
390 LogDebug("account ID : " << m_accountId);
391 ScopedMail mail(EmailService::createMail(account));
392 setEmailAccount(account); //save account
393 ScopedMailbox mailbox(EmailService::getMailboxByType(account.getIntId(), EMF_MAILBOX_TYPE_DRAFT));
394 setId(convertId(EmailService::addMailToMailbox(mail.Get(), mailbox.Get())));
395 setFolderType(Api::Messaging::DRAFTBOX);
396 setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
405 //EmailAccountInfo account = Messaging::getInstance().getCurrentEmailAccount();
406 LogDebug("account ID :" << m_accountId);
407 m_mail.Reset(EmailService::readMail(m_accountId, getIntId()));
409 if (m_mail->head) { readHeader(); }
410 if (m_mail->body) { readBody(); }
411 if (m_mail->info) { readInfo(); }
413 m_mailbox.Reset(EmailService::getMailboxByMailId(m_accountId, getIntId()) );
414 setFolderType(EmailConverter::toFolderType(m_mailbox->mailbox_type));
419 void Email::readHeader()
423 Assert(m_mail && m_mail->head && "Header is NULL.");
425 if (m_mail->head->subject) {
426 setSubject(m_mail->head->subject);
429 if (m_mail->head->to) {
430 appendToRecipients(EmailUtils::stripAddressLine(m_mail->head->to));
433 if (m_mail->head->cc) {
434 appendCcRecipients(EmailUtils::stripAddressLine(m_mail->head->cc));
437 if (m_mail->head->bcc) {
438 appendBccRecipients(EmailUtils::stripAddressLine(m_mail->head->bcc));
443 struct tm tmpTime = *(localtime(&rawtime));
444 tmpTime.tm_year = m_mail->head->datetime.year;
445 tmpTime.tm_mon = m_mail->head->datetime.month;
446 tmpTime.tm_mday = m_mail->head->datetime.day;
447 tmpTime.tm_hour = m_mail->head->datetime.hour;
448 tmpTime.tm_min = m_mail->head->datetime.minute;
449 tmpTime.tm_sec = m_mail->head->datetime.second;
451 setDateTime(tmpTime);
453 if (m_mail->head->from) {
455 from.setRecipients(m_mail->head->from);
456 setSourceAddress(from);
457 setSourceAddressValidity(true); //not needed to update in platform
463 void Email::readBody() {
466 Assert(m_mail && m_mail->body && "Body is NULL.");
468 if (m_mail->body->plain) {
469 DPL::ScopedFClose file(::fopen(m_mail->body->plain, "r"));
471 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
472 "Cannot read body file: " << m_mail->body->plain);
474 fseek(file.Get(), 0, SEEK_END);
475 long int size = ftell(file.Get());
476 fseek(file.Get(), 0, SEEK_SET);
477 DPL::ScopedPtr<char> data(new char[size + 1]);
478 memset(data.Get(), 0, size + 1);
479 fread(data.Get(), 1, size, file.Get());
484 if (m_mail->body->html) {
485 DPL::ScopedFClose file(::fopen(m_mail->body->html, "r")); //auto close, scopedFClose
487 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
488 "Cannot read html body file: " << m_mail->body->html);
491 fseek(file.Get(), 0, SEEK_END);
492 long int size = ftell(file.Get());
493 fseek(file.Get(), 0, SEEK_SET);
494 DPL::ScopedPtr<char> data(new char[size + 1]);
495 memset(data.Get(), 0, size + 1);
496 fread(data.Get(), 1, size, file.Get());
497 setHtmlBody(data.Get()); //setHtmlBody declarate in Email Calss.
500 if (m_mail->body->attachment && m_mail->body->attachment_num > 0) {
501 LogDebug("reading attachments , attahcment count = " << m_mail->body->attachment_num);
502 emf_attachment_info_t* attach = m_mail->body->attachment;
503 for (int i = 0; i < m_mail->body->attachment_num; ++i) {
505 LogDebug("throw platform exception");
506 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
507 "Attachment list shorter than expected.");
512 LogError("id :" << attach->attachment_id << " name :" << attach->name << " download :" << attach->downloaded << " savefile :" << attach->savename );
514 IAttachmentPtr tmpAtt(new Attachment(attach));
515 LogError(" create new attachment ");
518 //tmpAtt->setMessage(SharedFromThis()); //set IMessagePtr
519 tmpAtt->rename(attach->name);
520 tmpAtt->setAttachmentID(attach->attachment_id);
521 tmpAtt->setDownloaded(attach->downloaded);
523 appendAttachment(tmpAtt);
524 LogError(" append complete");
527 attach = attach->next;
529 catch (const WrtDeviceApis::Commons::Exception& ex) {
530 LogError("Error while trying to append attachment " <<
531 attach->savename << ": " << ex.DumpToString());
539 void Email::readInfo()
543 Assert(m_mail && m_mail->info && "Info is NULL.");
545 setReadStatus(m_mail->info->flags.seen == 1);
547 m_accountId = m_mail->info->account_id;
550 EmailConverter::toMessagePriority( m_mail->info->extra_flags.priority )
552 setSize(m_mail->info->rfc822_size);
557 void Email::updateBody()
561 if (isBodyValid()) { return; }
564 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
568 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Body is NULL.");
570 if (!m_mail->body->plain) {
571 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Body file is NULL.");
574 if (!m_mail->body->html) {
575 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Html Body file is NULL.");
579 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Info is NULL.");
583 FILE* f = fopen(m_mail->body->plain, "w");
585 //fprintf(f, getBodyRef().c_str());
586 fwrite(getBodyRef().c_str(), strlen(getBodyRef().c_str()), 1, f);
591 LogDebug("Plain Body file is NULL.");
594 if (m_mail->body->html) {
596 f = fopen(m_mail->body->html, "w");
598 //fprintf(f, getHtmlBody().c_str());
599 fwrite(getHtmlBody().c_str(), strlen(getHtmlBody().c_str()), 1, f);
605 LogDebug("Html Body file is NULL.");
608 m_mail->info->body_downloaded = true;
609 setBodyValidity(true);
614 void Email::updateSubject()
618 if (isSubjectValid()) { return; }
620 LogDebug("update subject, msgId=" << getIdRef());
623 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail not allocated.");
627 m_mail->head = EmailService::alloc<emf_mail_head_t>();
630 m_mail->head->subject = String::strdup(getSubjectRef());
631 setSubjectValidity(true);
636 void Email::updateReadStatus()
640 if (isReadStatusValid()) { return; }
642 LogDebug("update read, msgId=" << getIdRef());
645 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail not allocated.");
649 EmailService::alloc<emf_mail_info_t>();
652 m_mail->info->flags.seen = isRead();
653 setReadStatusValidity(true);
658 void Email::updateIsRead()
661 if (isReadChangeStatusValid()) {
662 // do not update if not changed
666 EmailService::updateSeenFlag(getAccountID(), getIntId(), isReadChangeStatus());
667 setisReadChangeStatusValidity(true);
671 void Email::addMessageToDraft()
676 //check Message Status.
677 DPL::Mutex::ScopedLock mx(&m_updateMutex);
680 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
689 int error = email_update_message(getIntId(), m_mail.Get());
690 LogDebug("add finished, mailId = " << error);
693 if ( getUID() > 0 && m_accountId > 0)
701 Api::Messaging::EmailAccountInfo account = getEmailAccount();
702 m_accountId = account.getIntId(); //set account ID
703 MailSender::getInstance();
705 LogDebug("account ID : " << m_accountId);
706 ScopedMail mail(EmailService::createMail(account));
708 LogDebug("get mail" );
709 emf_mail_t* ma = mail.Get();
711 LogDebug("UID : " << ma->info->uid);
713 setEmailAccount(account); //save account
714 ScopedMailbox mailbox(EmailService::getMailboxByType(account.getIntId(), EMF_MAILBOX_TYPE_DRAFT));
715 setId(convertId(EmailService::addMailToMailbox(mail.Get(), mailbox.Get())));
717 reload(); //reload mail
718 update(); //update message.
720 LogDebug("Folder = " << EmailConverter::toFolderType(m_mailbox->mailbox_type));
721 setFolderType(EmailConverter::toFolderType(m_mailbox->mailbox_type));
722 setMessageStatus(Api::Messaging::MESSAGE_STATUS_DRAFT);
724 LogDebug("Message ID : " << getUID());
730 void Email::updateRecipients()
734 if (getToValidity() && getCcValidity() && getBccValidity()) { return; }
737 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
741 m_mail->head = EmailService::alloc<emf_mail_head_t>();
744 if (!getToValidity()) {
745 std::string addressLine = EmailUtils::formatAddressLine(getToRecipients());
746 if (m_mail->head->to) {
747 free(m_mail->head->to);
749 m_mail->head->to = String::strdup(addressLine);
753 if (!getCcValidity()) {
754 std::string addressLine = EmailUtils::formatAddressLine(getCcRecipients());
755 if (m_mail->head->cc) {
756 free(m_mail->head->cc);
758 m_mail->head->cc = String::strdup(addressLine);
762 if (!getBccValidity()) {
763 std::string addressLine = EmailUtils::formatAddressLine(
765 if (m_mail->head->bcc) {
766 free(m_mail->head->bcc);
768 m_mail->head->bcc = String::strdup(addressLine);
769 setBccValidity(true);
775 void Email::updateFrom()
779 if (getFromValidity()) { return; }
782 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
786 EmailService::alloc<emf_mail_info_t>();
789 m_mail->info->account_id = m_accountId;
790 // TODO Update m_mail->head->from as well
792 setFromValidity(true);
797 void Email::updateAttachments()
801 if (isAttachmentsValid()) { return; }
804 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail is NULL.");
807 emf_attachment_info_t* attachment = NULL;
809 LogDebug("update attachments, msgId=" << getIdRef());
812 m_mail->body = EmailService::alloc<emf_mail_body_t>();
815 int i = m_mail->body->attachment_num;
816 LogDebug("clean attachment, attachment count=" << i);
817 attachment = m_mail->body->attachment;
818 std::stringstream stream;
822 LogDebug("delete file :" << attachment->name << " saved name :" << attachment->savename );
823 int aId = attachment->attachment_id;
824 char* mId = m_mail->head->mid;
830 LogDebug("mID :" << n_mId << " Attachment Id :" << aId );
832 int error = email_delete_attachment(m_mailbox.Get(), n_mId, (const char*)(stream.str()).c_str());
833 if (EMF_ERROR_NONE != error) {
834 LogDebug("Error Num = " << error);
835 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
836 "Error while adding attachment. [" << error << "]");
838 attachment = attachment->next;
841 m_mail->body->attachment_num = 0;
842 if (NULL != m_mail->body->attachment) {
843 EmailService::freeAttachment(m_mail->body->attachment);
844 m_mail->body->attachment = NULL;
848 std::size_t attachmentSize = getAttachmentsCount();
849 LogDebug("update attachments, attachmentSize=" << attachmentSize);
850 if (attachmentSize > 0) {
852 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail info is NULL.");
855 for (std::size_t i = 0; i < attachmentSize; ++i) {
856 IAttachmentPtr att = getAttachment(i);
861 //copy attachment file
862 std::stringstream to_oss;
863 to_oss << TEMP_FOLDER << "/" << att->getShortName();
864 LogDebug("temp file=" << to_oss.str());
866 std::stringstream cp_oss;
867 cp_oss << COMMAND_NAME;
868 cp_oss << " " << COMMAND_SWITCH_RECURSIVE;
869 cp_oss << " \"" << att->getFullPath() << "\"";
870 cp_oss << " \"" << to_oss.str() << "\"";
872 attachment = EmailService::alloc<emf_attachment_info_t>(); //create attachment struct
873 attachment->name = String::strdup(att->getShortName());
874 //attachment->savename = String::strdup( att->getFullPath() );
875 attachment->savename = String::strdup( to_oss.str().c_str() );
877 attachment->next = NULL;
878 attachment->downloaded = true;
880 int result = system(cp_oss.str().c_str());
882 if (0 != WIFEXITED(result)) {
883 if (0 != WEXITSTATUS(result)) {
884 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Command failed.");
887 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
888 "Command terminated abnormally.");
891 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Couldn't launch command.");
894 LogDebug( "mailbox type = " << m_mailbox.Get()->mailbox_type);
896 int error = email_add_attachment(m_mailbox.Get(),
899 if (EMF_ERROR_NONE != error) {
900 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
901 "Error while adding attachment. [" << error << "]");
905 LogDebug(" attachment id : " << attachment->attachment_id);
906 //IMessagePtr msg = DPL::DynamicPointerCast<IMessage>(this);
907 att->setDownloaded(true);
908 att->setAttachmentID(attachment->attachment_id);
909 att->setMessage(SharedFromThis());
913 EmailService::freeAttachment(attachment);
916 setAttachmentsValidity(true);
919 Catch(WrtDeviceApis::Commons::PlatformException) {
920 EmailService::freeAttachment(attachment);
927 void Email::updatePriority()
931 if (isPriorityValid()) { return; }
934 ThrowMsg(WrtDeviceApis::Commons::PlatformException, "Mail not allocated.");
938 m_mail->info = EmailService::alloc<emf_mail_info_t>();
941 m_mail->info->extra_flags.priority = EmailConverter::toMailPriority(
943 setPriorityValid(true);
948 int Email::getIntId() const
950 return convertId(getIdRef());