Git Init
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / Messaging / MailSender.cpp
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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. 
15 */
16
17 /**
18  * @author          Zbigniew Kostrzewa (z.kostrzewa@samsung.com)
19  */
20 #include <utility>
21 #include <emf-types.h>
22 #include <Emf_Mapi.h>
23 #include <Emf_Mapi_Network.h>
24 #include <Emf_Mapi_Init.h>
25 #include <Emf_Mapi_Account.h>
26
27 #include <dpl/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/EventSendMessage.h>
33 #include <API/Messaging/EventOnSendingFailed.h>
34 #include "MailSender.h"
35 #include "NetworkStatus.h"
36 #include "Messaging.h"
37
38 namespace {
39 const char* DBUS_FILTER_NETWORK_STATUS =
40     "type='signal',interface='User.Email.NetworkStatus'";
41 }
42
43 namespace TizenApis {
44 namespace Platform {
45 namespace Messaging {
46
47 using namespace WrtDeviceApis::Commons;
48 using namespace WrtDeviceApis::CommonsJavaScript;
49
50 MailSender& MailSender::getInstance()
51 {
52     static MailSender instance;
53     return instance;
54 }
55
56 int MailSender::send(const Api::Messaging::IEmailPtr& mail)
57 {
58     Assert(mail && "Mail must not be NULL.");
59
60     int mailId = mail->convertId(mail->getIdRef());
61     LogDebug("send mailId = " << mailId);
62     SendRequestsIterator it = m_requests.find(mailId);
63     if (m_requests.end() != it) {
64         ThrowMsg(WrtDeviceApis::Commons::PlatformException,
65                  "Email: " << mailId << " already requested to be send.");
66     }
67
68     return sendInternal(mail);
69 }
70
71 void MailSender::cancel(int handle)
72 {
73     SendRequestsIterator it = m_requests.find(handle);
74     if (m_requests.end() == it) {
75         //ThrowMsg(WrtDeviceApis::Commons::PlatformException,
76         //         "Email handle : " << handle << " not found.");
77         LogDebug("Email handle" << handle  << " not found!");
78           return;
79     }
80     else
81     {
82           cancelInternal(it->second);
83     }
84 }
85
86 // TODO Copied from former solution, refactor it.
87 void MailSender::OnEventReceived(const DBus::MessageEvent& event)
88 {
89     LogDebug("HERE");
90     NetworkStatusPtr msg(new NetworkStatus(event.GetArg0()));
91     int mailId = msg->getMailId();
92     LogDebug("status : " << msg->getStatus() << " mailId : " << mailId);
93     int handle = 0;
94
95     if ( msg->getStatus() == NOTI_SEND_FINISH || msg->getStatus() == NOTI_SEND_FAIL)
96     {
97                 //find handle
98                 SendRequestsIterator it = m_requests.begin();
99                 for (; it != m_requests.end() ; it++)
100                 {
101                         if ( it->second.mail->getUID() == mailId)
102                         {
103                                 handle = it->first;
104                                 LogDebug("handle : " << handle);
105                                 break;
106                         }
107                 }
108
109                 if (msg->getStatus() == NOTI_SEND_FAIL)
110                 {
111                         LogDebug(" Error Code : " << msg->getErrorCode());
112                 }
113     }
114     else 
115     {
116                 if ( msg->getStatus() == NOTI_SEND_START )
117                 {
118                         LogDebug("NOTI_SEND_START");
119                 }
120                 else if ( msg->getStatus() == NOTI_SEND_CANCEL )
121                 {
122                         LogDebug("NOTI_SEND_CANCEL");
123                 }
124
125                 return ;
126     }
127         
128     LogDebug("handle : " << handle);
129         
130     SendRequestsIterator it = m_requests.find(handle);  //find reqeuset
131     if (m_requests.end() != it) {
132         switch (msg->getStatus()) {
133         case NOTI_SEND_START:
134             LogInfo("Start sending e-mail: " << mailId);
135             break;
136
137         case NOTI_SEND_FINISH:
138         {
139             const Api::Messaging::IEmailPtr& mail = it->second.mail;
140             Api::Messaging::EventSendMessageReqReceiver* requestReceiver =
141                 mail->getRequestReceiver();
142             if (requestReceiver) {
143                 Api::Messaging::EventSendMessagePtr event = mail->getSendMessageEvent();
144                      if (event)
145                         {
146                                 for (size_t i = 0; i < mail->getToRecipients().getRecipientSize(); ++i) {
147                                         event->m_successRecipients.push_back(mail->getToRecipients().getRecipient(i));
148                                 }
149                                 for (size_t i = 0; i < mail->getCcRecipients().getRecipientSize(); ++i) {
150                                         event->m_successRecipients.push_back(mail->getCcRecipients().getRecipient(i));
151                                 }
152                                 for (size_t i = 0; i < mail->getBccRecipients().getRecipientSize(); ++i) {
153                                         event->m_successRecipients.push_back(mail->getBccRecipients().getRecipient(i));
154                                 }
155                                 
156                                 requestReceiver->ManualAnswer(event);
157                         }                
158                 
159             }
160                  mail->setMessageStatus(Api::Messaging::MESSAGE_STATUS_SENT);
161             LogInfo("E-mail sent: " << mailId);
162             m_requests.erase(mailId);
163             break;
164         }
165
166         case NOTI_SEND_FAIL:
167         {
168             const Api::Messaging::IEmailPtr& mail = it->second.mail;
169             Api::Messaging::EventOnSendingFailedEmitterPtr emitter = mail->getEmitter();
170             Api::Messaging::EventSendMessageReqReceiver *requestReceiver =
171                 mail->getRequestReceiver();
172             if (emitter) {
173                 Api::Messaging::EventOnSendingFailedPtr event(
174                     new Api::Messaging::EventOnSendingFailed()
175                     );
176                 switch (msg->getErrorCode()) {
177                 case EMF_ERROR_NO_SIM_INSERTED:
178                 case EMF_ERROR_FLIGHT_MODE:
179                     event->setError(
180                         Api::Messaging::EventOnSendingFailed::NO_NETWORKING
181                         );
182                     break;
183
184                 case EMF_ERROR_SMTP_SEND_FAILURE:
185                 case EMF_ERROR_NO_SUCH_HOST:
186                 case EMF_ERROR_CONNECTION_FAILURE:
187                 case EMF_ERROR_CONNECTION_BROKEN:
188                 case EMF_ERROR_INVALID_SERVER:
189                 case EMF_ERROR_NO_RESPONSE:
190                     event->setError(
191                         Api::Messaging::EventOnSendingFailed::NO_CONNECTION
192                         );
193                     break;
194
195                 default:
196                     event->setError(Api::Messaging::EventOnSendingFailed::UNKNOWN);
197                 }
198                 emitter->emit(event);
199             } else if (requestReceiver) {
200                 Api::Messaging::EventSendMessagePtr event = mail->getSendMessageEvent();
201                 event->setExceptionCode(
202                     WrtDeviceApis::Commons::ExceptionCodes::UnknownException
203                     );
204                 requestReceiver->ManualAnswer(event);
205             }
206                  mail->setMessageStatus(Api::Messaging::MESSAGE_STATUS_FAILED);
207                  
208             LogInfo("Sending e-mail: " << mailId <<
209                     " failed with error: " << msg->getErrorCode());
210             m_requests.erase(mailId);
211             break;
212         }
213         }
214     }
215 }
216
217 MailSender::MailSender() :
218     m_dbusThread(new DPL::Thread()),
219     m_dbus(new DBus::Connection())
220 {
221     m_dbusThread->Run();
222
223     m_dbus->setWorkerThread(m_dbusThread.Get());
224     m_dbus->AddListener(this);
225     m_dbus->SwitchAllListenersToThread(
226         ThreadPool::getInstance().getThreadRef(ThreadEnum::MESSAGING_THREAD)
227         );
228     m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
229     m_dbus->open(DBUS_BUS_SYSTEM);
230
231     //start email service
232         if (EMF_ERROR_NONE == email_service_begin()) {
233             LogDebug("Email service Begin\n");
234             if (EMF_ERROR_NONE == email_open_db()) {
235                     LogDebug("Email open DB success\n");
236             }
237             else{
238                     LogDebug("Email open DB failed\n");
239         }
240         }
241         else{
242             LogDebug("Email service not started\n");
243         }
244
245 }
246
247 MailSender::~MailSender()
248 {
249     m_dbus->RemoveListener(this);
250     m_dbus->close();
251
252     m_dbusThread->Quit();
253
254
255     //close email service
256         if (EMF_ERROR_NONE == email_close_db()) {
257                 LogDebug("Email Close DB Success\n");
258                 if (EMF_ERROR_NONE == email_service_end()){
259                 LogDebug("Email service close Success\n");
260                 }
261                 else{
262                 LogDebug("Email service end failed\n");
263         }
264         }
265         else{
266                 LogDebug("Email Close DB failed\n");
267         }
268         
269 }
270
271 int MailSender::sendInternal(const Api::Messaging::IEmailPtr& mail)
272 {
273     int mailId = mail->convertId(mail->getIdRef());
274
275     emf_mailbox_t mailbox = {};
276     mailbox.account_id =
277         Messaging::getInstance().getEmailAccountId(mail->getFromRef());
278     // TODO Causes warning during compilation, refactor it.
279     mailbox.name = (char*)EMF_SENTBOX_NAME;
280
281     emf_option_t options = {};
282     options.keep_local_copy = 1;
283     unsigned int emf_handle=0;
284
285     int error = email_send_mail(&mailbox,
286                                 mailId,
287                                 &options,
288                                 &emf_handle);
289         
290     if (EMF_ERROR_NONE != error) {
291                 LogDebug("Send Fail error = " << error );
292                 m_requests.erase(mailId);
293                 mail->setMessageStatus(Api::Messaging::MESSAGE_STATUS_SENDING); 
294                 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
295                          "Failed to initialize send request. [" << error << "]");
296           return -1;
297     }
298     else
299     {
300                 m_requests.insert(std::make_pair(emf_handle, SendRequestData(emf_handle, mail)));
301     }
302
303     LogDebug("emf Handle : " << emf_handle 
304 << "requests size :" << m_requests.size() );
305   
306     return emf_handle;  
307 }
308
309 void MailSender::cancelInternal(const SendRequestData& data)
310 {
311     int error = email_cancel_job(data.mail->getAccountID(), data.handle);
312     if (EMF_ERROR_NONE != error) {
313         ThrowMsg(WrtDeviceApis::Commons::PlatformException,
314                  "Couldn't cancel sending for email: " <<
315                  data.mail->getIdRef());
316     }
317
318     m_requests.erase(data.handle);
319 }
320 }
321 }
322 }