Update change log and spec for wrt-plugins-tizen_0.4.13
[framework/web/wrt-plugins-tizen.git] / src / Messaging / MailSender.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 #include <utility>
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>
24
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 "EventSendMessage.h"
31 #include "EventMessagingService.h"
32 #include "EventOnSendingFailed.h"
33 #include "MailSender.h"
34 #include "NetworkStatus.h"
35 #include "Messaging.h"
36
37 namespace {
38 const char* DBUS_FILTER_NETWORK_STATUS =
39     "type='signal',interface='User.Email.NetworkStatus'";
40 }
41
42 namespace DeviceAPI {
43 namespace Messaging {
44
45 using namespace WrtDeviceApis::Commons;
46 using namespace WrtDeviceApis::CommonsJavaScript;
47
48 MailSender& MailSender::getInstance()
49 {
50     static MailSender instance;
51     return instance;
52 }
53
54 int MailSender::send(const IEmailPtr& mail)
55 {
56     Assert(mail && "Mail must not be NULL.");
57
58     int mailId = mail->convertId(mail->getIdRef());
59     LogDebug("send mailId = " << mailId);
60     SendRequestsIterator it = m_requests.find(mailId);
61     if (m_requests.end() != it) {
62         ThrowMsg(WrtDeviceApis::Commons::PlatformException,
63                  "Email: " << mailId << " already requested to be send.");
64     }
65
66     return sendInternal(mail);
67 }
68
69 void MailSender::cancel(int handle)
70 {
71     SendRequestsIterator it = m_requests.find(handle);
72     if (m_requests.end() == it) {
73         //ThrowMsg(WrtDeviceApis::Commons::PlatformException,
74         //         "Email handle : " << handle << " not found.");
75         LogDebug("Email handle" << handle  << " not found!");
76           return;
77     }
78     else
79     {
80           cancelInternal(it->second);
81     }
82 }
83
84 // TODO Copied from former solution, refactor it.
85 void MailSender::OnEventReceived(const DBus::MessageEvent& event)
86 {
87     LogDebug("enter");
88     NetworkStatusPtr msg(new NetworkStatus(event.GetArg0()));
89     int mailId = msg->getMailId();
90     LogDebug("status : " << msg->getStatus() << " mailId : " << mailId);
91     int handle = 0;
92
93     if ( msg->getStatus() == NOTI_SEND_FINISH || msg->getStatus() == NOTI_SEND_FAIL)
94     {
95                 //find handle
96                 SendRequestsIterator it = m_requests.begin();
97                 for (; it != m_requests.end() ; it++)
98                 {
99                         if ( it->second.mail->getUID() == mailId)
100                         {
101                                 handle = it->first;
102                                 LogDebug("handle : " << handle);
103                                 break;
104                         }
105                 }
106
107                 if (msg->getStatus() == NOTI_SEND_FAIL)
108                 {
109                         LogDebug(" Error Code : " << msg->getErrorCode());
110                 }
111     }
112     else 
113     {
114                 if ( msg->getStatus() == NOTI_SEND_START )
115                 {
116                         LogDebug("NOTI_SEND_START");
117                 }
118                 else if ( msg->getStatus() == NOTI_SEND_CANCEL )
119                 {
120                         LogDebug("NOTI_SEND_CANCEL");
121                 }
122
123                 return ;
124     }
125         
126     LogDebug("handle : " << handle);
127         
128     SendRequestsIterator it = m_requests.find(handle);  //find reqeuset
129     if (m_requests.end() != it) {
130         switch (msg->getStatus()) {
131         case NOTI_SEND_START:
132             LogInfo("Start sending e-mail: " << mailId);
133             break;
134
135         case NOTI_SEND_FINISH:
136         {
137             const IEmailPtr& mail = it->second.mail;
138             //EventSendMessageReqReceiver* requestReceiver = mail->getRequestReceiver();
139             EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
140                 
141             if (requestReceiver) {
142                 //EventSendMessagePtr event = mail->getSendMessageEvent();
143                 EventMessagingServicePtr event = mail->getMessagingServiceEvent();
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(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 IEmailPtr& mail = it->second.mail;
169             EventOnSendingFailedEmitterPtr emitter = mail->getEmitter();
170             //EventSendMessageReqReceiver *requestReceiver = mail->getRequestReceiver();
171             EventMessagingServiceReqReceiver* requestReceiver = mail->getRequestReceiver();
172             if (emitter) {
173                 EventOnSendingFailedPtr event(
174                     new EventOnSendingFailed()
175                     );
176                 switch (msg->getErrorCode()) {
177                 case EMAIL_ERROR_NO_SIM_INSERTED:
178                 case EMAIL_ERROR_FLIGHT_MODE:
179                     event->setError(
180                         EventOnSendingFailed::NO_NETWORKING
181                         );
182                     break;
183
184                 case EMAIL_ERROR_SMTP_SEND_FAILURE:
185                 case EMAIL_ERROR_NO_SUCH_HOST:
186                 case EMAIL_ERROR_CONNECTION_FAILURE:
187                 case EMAIL_ERROR_CONNECTION_BROKEN:
188                 case EMAIL_ERROR_INVALID_SERVER:
189                 case EMAIL_ERROR_NO_RESPONSE:
190                     event->setError(
191                         EventOnSendingFailed::NO_CONNECTION
192                         );
193                     break;
194
195                 default:
196                     event->setError(EventOnSendingFailed::UNKNOWN);
197                 }
198                 emitter->emit(event);
199             } else if (requestReceiver) {
200                 //EventSendMessagePtr event = mail->getSendMessageEvent();
201                         EventMessagingServicePtr event = mail->getMessagingServiceEvent();
202                 event->setExceptionCode(
203                     WrtDeviceApis::Commons::ExceptionCodes::UnknownException
204                     );
205                 requestReceiver->ManualAnswer(event);
206             }
207                  mail->setMessageStatus(MESSAGE_STATUS_FAILED);
208                  
209             LogInfo("Sending e-mail: " << mailId <<
210                     " failed with error: " << msg->getErrorCode());
211             m_requests.erase(mailId);
212             break;
213         }
214         }
215     }
216 }
217
218 MailSender::MailSender() :
219     m_dbusThread(new DPL::Thread()),
220     m_dbus(new DBus::Connection())
221 {
222     LogDebug("enter");
223     m_dbusThread->Run();
224
225     m_dbus->setWorkerThread(m_dbusThread.Get());
226     m_dbus->AddListener(this);
227     m_dbus->SwitchAllListenersToThread(
228         ThreadPool::getInstance().getThreadRef(ThreadEnum::MESSAGING_THREAD)
229         );
230     m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
231     m_dbus->open(DBUS_BUS_SYSTEM);
232
233     //start email service
234         if (EMAIL_ERROR_NONE == email_service_begin()) {
235             LogDebug("Email service Begin\n");
236             if (EMAIL_ERROR_NONE == email_open_db()) {
237                     LogDebug("Email open DB success\n");
238             }
239             else{
240                     LogDebug("Email open DB failed\n");
241         }
242         }
243         else{
244             LogDebug("Email service not started\n");
245         }
246
247 }
248
249 MailSender::~MailSender()
250 {
251     m_dbus->RemoveListener(this);
252     m_dbus->close();
253
254     m_dbusThread->Quit();
255
256
257     //close email service
258         if (EMAIL_ERROR_NONE == email_close_db()) {
259                 LogDebug("Email Close DB Success\n");
260                 if (EMAIL_ERROR_NONE == email_service_end()){
261                 LogDebug("Email service close Success\n");
262                 }
263                 else{
264                 LogDebug("Email service end failed\n");
265         }
266         }
267         else{
268                 LogDebug("Email Close DB failed\n");
269         }
270         
271 }
272
273 int MailSender::sendInternal(const IEmailPtr& mail)
274 {
275     int mailId = mail->convertId(mail->getIdRef());
276
277     email_option_t options = {};
278     options.keep_local_copy = 1;
279     int email_handle=0;
280
281     int error = email_send_mail(mailId,
282                                 &email_handle);
283         
284     if (EMAIL_ERROR_NONE != error) {
285                 LogDebug("Send Fail error = " << error );
286                 m_requests.erase(mailId);
287                 mail->setMessageStatus(MESSAGE_STATUS_SENDING); 
288                 ThrowMsg(WrtDeviceApis::Commons::PlatformException,
289                          "Failed to initialize send request. [" << error << "]");
290           return -1;
291     }
292     else
293     {
294                 m_requests.insert(std::make_pair(email_handle, SendRequestData(email_handle, mail)));
295     }
296
297     LogDebug("emf Handle : " << email_handle 
298 << "requests size :" << m_requests.size() );
299   
300     return email_handle;        
301 }
302
303 void MailSender::cancelInternal(const SendRequestData& data)
304 {
305     int error = email_cancel_job(data.mail->getAccountID(), data.handle,EMAIL_CANCELED_BY_USER);
306     if (EMAIL_ERROR_NONE != error) {
307         ThrowMsg(WrtDeviceApis::Commons::PlatformException,
308                  "Couldn't cancel sending for email: " <<
309                  data.mail->getIdRef());
310     }
311
312     m_requests.erase(data.handle);
313 }
314 }
315 }