561a0c086bd0882f14f1b319f081beb1d3919833
[framework/web/wrt-plugins-common.git] / src / modules / 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  * @author          Zbigniew Kostrzewa (z.kostrzewa@samsung.com)
18  */
19 #include <utility>
20 #include <emf-types.h>
21 #include <Emf_Mapi_Network.h>
22 #include <dpl/log/log.h>
23 #include <dpl/assert.h>
24 #include <Commons/Exception.h>
25 #include <Commons/ThreadPool.h>
26 #include <API/Messaging/ReqReceiverMessage.h>
27 #include <API/Messaging/EventSendMessage.h>
28 #include <API/Messaging/EventOnSendingFailed.h>
29 #include "MailSender.h"
30 #include "NetworkStatus.h"
31 #include "Messaging.h"
32
33 namespace {
34 const char* DBUS_FILTER_NETWORK_STATUS =
35     "type='signal',interface='User.Email.NetworkStatus'";
36 }
37
38 namespace WrtDeviceApis {
39 namespace Messaging {
40 MailSender& MailSender::getInstance()
41 {
42     static MailSender instance;
43     return instance;
44 }
45
46 void MailSender::send(const Api::IEmailPtr& mail)
47 {
48     Assert(mail && "Mail must not be NULL.");
49
50     int mailId = mail->convertId(mail->getIdRef());
51     SendRequestsIterator it = m_requests.find(mailId);
52     if (m_requests.end() != it) {
53         ThrowMsg(Commons::PlatformException,
54                  "Email: " << mailId << " already requested to be send.");
55     }
56
57     sendInternal(mail);
58 }
59
60 void MailSender::cancel(int mailId)
61 {
62     SendRequestsIterator it = m_requests.find(mailId);
63     if (m_requests.end() == it) {
64         ThrowMsg(Commons::PlatformException,
65                  "Email: " << mailId << " not found.");
66     }
67
68     cancelInternal(it->second);
69 }
70
71 // TODO Copied from former solution, refactor it.
72 void MailSender::OnEventReceived(const DBus::MessageEvent& event)
73 {
74     LogDebug("HERE");
75     NetworkStatusPtr msg(new NetworkStatus(event.GetArg0()));
76     int mailId = msg->getMailId();
77
78     SendRequestsIterator it = m_requests.find(mailId);
79     if (m_requests.end() != it) {
80         switch (msg->getStatus()) {
81         case NOTI_SEND_START:
82             LogInfo("Start sending e-mail: " << mailId);
83             break;
84
85         case NOTI_SEND_FINISH:
86         {
87             const Api::IEmailPtr& mail = it->second.mail;
88             Api::EventSendMessageReqReceiver* requestReceiver =
89                 mail->getRequestReceiver();
90             if (requestReceiver)
91             {
92                 Api::EventSendMessagePtr event = mail->getSendMessageEvent();
93                 event->addRecipientsSendResult(
94                         mail->getToRecipientsPtr()->getRecipientsRef(),
95                         true);
96                 event->addRecipientsSendResult(
97                         mail->getCcRecipientsPtr()->getRecipientsRef(),
98                         true);
99                 event->addRecipientsSendResult(
100                         mail->getBccRecipientsPtr()->getRecipientsRef(),
101                         true);
102                 requestReceiver->ManualAnswer(event);
103             }
104             LogInfo("E-mail sent: " << mailId);
105             m_requests.erase(mailId);
106             break;
107         }
108
109         case NOTI_SEND_FAIL:
110         {
111             const Api::IEmailPtr& mail = it->second.mail;
112             Api::EventOnSendingFailedEmitterPtr emitter = mail->getEmitter();
113             Api::EventSendMessageReqReceiver *requestReceiver =
114                 mail->getRequestReceiver();
115             if (emitter) {
116                 Api::EventOnSendingFailedPtr event(
117                     new Api::EventOnSendingFailed()
118                     );
119                 switch (msg->getErrorCode()) {
120                 case EMF_ERROR_NO_SIM_INSERTED:
121                 case EMF_ERROR_FLIGHT_MODE:
122                     event->setError(
123                         Api::EventOnSendingFailed::NO_NETWORKING
124                         );
125                     break;
126
127                 case EMF_ERROR_SMTP_SEND_FAILURE:
128                 case EMF_ERROR_NO_SUCH_HOST:
129                 case EMF_ERROR_CONNECTION_FAILURE:
130                 case EMF_ERROR_CONNECTION_BROKEN:
131                 case EMF_ERROR_INVALID_SERVER:
132                 case EMF_ERROR_NO_RESPONSE:
133                     event->setError(
134                         Api::EventOnSendingFailed::NO_CONNECTION
135                         );
136                     break;
137
138                 default:
139                     event->setError(Api::EventOnSendingFailed::UNKNOWN);
140                 }
141                 emitter->emit(event);
142             }
143             else if (requestReceiver)
144             {
145                 Api::EventSendMessagePtr event = mail->getSendMessageEvent();
146                 event->addRecipientsSendResult(
147                         mail->getToRecipientsPtr()->getRecipientsRef(),
148                         false);
149                 event->addRecipientsSendResult(
150                         mail->getCcRecipientsPtr()->getRecipientsRef(),
151                         false);
152                 event->addRecipientsSendResult(
153                         mail->getBccRecipientsPtr()->getRecipientsRef(),
154                         false);
155                 event->setExceptionCode(
156                     Commons::ExceptionCodes::UnknownException
157                     );
158                 requestReceiver->ManualAnswer(event);
159             }
160             LogInfo("Sending e-mail: " << mailId <<
161                     " failed with error: " << msg->getErrorCode());
162             m_requests.erase(mailId);
163             break;
164         }
165         }
166     }
167 }
168
169 MailSender::MailSender() :
170     m_dbusThread(new DPL::Thread()),
171     m_dbus(new DBus::Connection())
172 {
173     m_dbusThread->Run();
174
175     m_dbus->setWorkerThread(m_dbusThread.Get());
176     m_dbus->AddListener(this);
177     m_dbus->SwitchAllListenersToThread(
178         Commons::ThreadPool::getInstance().getThreadRef(Commons::ThreadEnum::MESSAGING_THREAD)
179         );
180     m_dbus->addFilter(DBUS_FILTER_NETWORK_STATUS);
181     m_dbus->open(DBUS_BUS_SYSTEM);
182 }
183
184 MailSender::~MailSender()
185 {
186     m_dbus->RemoveListener(this);
187     m_dbus->close();
188
189     m_dbusThread->Quit();
190 }
191
192 void MailSender::sendInternal(const Api::IEmailPtr& mail)
193 {
194     int mailId = mail->convertId(mail->getIdRef());
195
196     emf_mailbox_t mailbox;
197     memset(&mailbox, 0, sizeof(emf_mailbox_t));
198     mailbox.account_id =
199         Messaging::getInstance().getEmailAccountId(mail->getFromRef());
200     // TODO remove ugly casting.
201     mailbox.name = (char*)EMF_SENTBOX_NAME;
202
203     emf_option_t options;
204     memset(&options, 0, sizeof(emf_option_t));
205     options.keep_local_copy = 1;
206
207     m_requests.insert(std::make_pair(mailId, SendRequestData(mail)));
208
209     int error = email_send_mail(&mailbox,
210                                 mailId,
211                                 &options,
212                                 &m_requests.at(mailId).handle);
213     if (EMF_ERROR_NONE != error) {
214         m_requests.erase(mailId);
215         ThrowMsg(Commons::PlatformException,
216                  "Failed to initialize send request. [" << error << "]");
217     }
218 }
219
220 void MailSender::cancelInternal(const SendRequestData& data)
221 {
222     int mailId = data.mail->convertId(data.mail->getIdRef());
223
224     int error = email_cancel_job(data.mail->getAccountId(), data.handle);
225     if (EMF_ERROR_NONE != error) {
226         ThrowMsg(Commons::PlatformException,
227                  "Couldn't cancel sending for email: " <<
228                  data.mail->getIdRef());
229     }
230
231     m_requests.erase(mailId);
232 }
233 }
234 }