Diffstat (limited to 'kmicromail/libmailwrapper/smtpwrapper.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libmailwrapper/smtpwrapper.cpp | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/kmicromail/libmailwrapper/smtpwrapper.cpp b/kmicromail/libmailwrapper/smtpwrapper.cpp new file mode 100644 index 0000000..04a21ea --- a/dev/null +++ b/kmicromail/libmailwrapper/smtpwrapper.cpp | |||
@@ -0,0 +1,458 @@ | |||
1 | #include "smtpwrapper.h" | ||
2 | #include "mailwrapper.h" | ||
3 | #include "abstractmail.h" | ||
4 | #include "logindialog.h" | ||
5 | #include "mailtypes.h" | ||
6 | #include "sendmailprogress.h" | ||
7 | |||
8 | //#include <opie2/odebug.h> | ||
9 | //#include <qt.h> | ||
10 | #include <qapplication.h> | ||
11 | #include <qmessagebox.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <qpe/config.h> | ||
14 | #include <qpe/qcopenvelope_qws.h> | ||
15 | |||
16 | #include <libetpan/libetpan.h> | ||
17 | |||
18 | |||
19 | using namespace Opie::Core; | ||
20 | progressMailSend*SMTPwrapper::sendProgress = 0; | ||
21 | |||
22 | SMTPwrapper::SMTPwrapper(SMTPaccount * aSmtp ) | ||
23 | : Generatemail() | ||
24 | { | ||
25 | m_SmtpAccount = aSmtp; | ||
26 | Config cfg( "mail" ); | ||
27 | cfg.setGroup( "Status" ); | ||
28 | m_queuedMail = cfg.readNumEntry( "outgoing", 0 ); | ||
29 | emit queuedMails( m_queuedMail ); | ||
30 | connect( this, SIGNAL( queuedMails(int) ), this, SLOT( emitQCop(int) ) ); | ||
31 | m_smtp = 0; | ||
32 | } | ||
33 | |||
34 | SMTPwrapper::~SMTPwrapper() | ||
35 | { | ||
36 | disc_server(); | ||
37 | } | ||
38 | |||
39 | void SMTPwrapper::emitQCop( int queued ) { | ||
40 | QCopEnvelope env( "QPE/Pim", "outgoingMails(int)" ); | ||
41 | env << queued; | ||
42 | } | ||
43 | |||
44 | QString SMTPwrapper::mailsmtpError( int errnum ) { | ||
45 | switch ( errnum ) { | ||
46 | case MAILSMTP_NO_ERROR: | ||
47 | return tr( "No error" ); | ||
48 | case MAILSMTP_ERROR_UNEXPECTED_CODE: | ||
49 | return tr( "Unexpected error code" ); | ||
50 | case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: | ||
51 | return tr( "Service not available" ); | ||
52 | case MAILSMTP_ERROR_STREAM: | ||
53 | return tr( "Stream error" ); | ||
54 | case MAILSMTP_ERROR_HOSTNAME: | ||
55 | return tr( "gethostname() failed" ); | ||
56 | case MAILSMTP_ERROR_NOT_IMPLEMENTED: | ||
57 | return tr( "Not implemented" ); | ||
58 | case MAILSMTP_ERROR_ACTION_NOT_TAKEN: | ||
59 | return tr( "Error, action not taken" ); | ||
60 | case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: | ||
61 | return tr( "Data exceeds storage allocation" ); | ||
62 | case MAILSMTP_ERROR_IN_PROCESSING: | ||
63 | return tr( "Error in processing" ); | ||
64 | case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: | ||
65 | return tr( "Starttls not supported" ); | ||
66 | // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: | ||
67 | // return tr( "Insufficient system storage" ); | ||
68 | case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: | ||
69 | return tr( "Mailbox unavailable" ); | ||
70 | case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: | ||
71 | return tr( "Mailbox name not allowed" ); | ||
72 | case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: | ||
73 | return tr( "Bad command sequence" ); | ||
74 | case MAILSMTP_ERROR_USER_NOT_LOCAL: | ||
75 | return tr( "User not local" ); | ||
76 | case MAILSMTP_ERROR_TRANSACTION_FAILED: | ||
77 | return tr( "Transaction failed" ); | ||
78 | case MAILSMTP_ERROR_MEMORY: | ||
79 | return tr( "Memory error" ); | ||
80 | case MAILSMTP_ERROR_CONNECTION_REFUSED: | ||
81 | return tr( "Connection refused" ); | ||
82 | default: | ||
83 | return tr( "Unknown error code" ); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | |||
88 | void SMTPwrapper::progress( size_t current, size_t maximum ) { | ||
89 | if (SMTPwrapper::sendProgress) { | ||
90 | SMTPwrapper::sendProgress->setSingleMail(current, maximum ); | ||
91 | qApp->processEvents(); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | void SMTPwrapper::storeMail(const char*mail, size_t length, const QString&box) { | ||
96 | if (!mail) | ||
97 | return; | ||
98 | QString localfolders = AbstractMail::defaultLocalfolder(); | ||
99 | AbstractMail*wrap = AbstractMail::getWrapper(localfolders); | ||
100 | wrap->createMbox(box); | ||
101 | wrap->storeMessage(mail,length,box); | ||
102 | delete wrap; | ||
103 | } | ||
104 | |||
105 | void SMTPwrapper::smtpSend( mailmime *mail,bool later) { | ||
106 | clist *rcpts = 0; | ||
107 | char *from, *data; | ||
108 | size_t size; | ||
109 | |||
110 | from = data = 0; | ||
111 | |||
112 | mailmessage * msg = 0; | ||
113 | msg = mime_message_init(mail); | ||
114 | mime_message_set_tmpdir(msg,getenv( "HOME" )); | ||
115 | int r = mailmessage_fetch(msg,&data,&size); | ||
116 | mime_message_detach_mime(msg); | ||
117 | mailmessage_free(msg); | ||
118 | if (r != MAIL_NO_ERROR || !data) { | ||
119 | if (data) | ||
120 | free(data); | ||
121 | ; // odebug << "Error fetching mime..." << oendl; | ||
122 | return; | ||
123 | } | ||
124 | msg = 0; | ||
125 | if (later) { | ||
126 | storeMail(data,size,"Outgoing"); | ||
127 | if (data) | ||
128 | free( data ); | ||
129 | Config cfg( "mail" ); | ||
130 | cfg.setGroup( "Status" ); | ||
131 | cfg.writeEntry( "outgoing", ++m_queuedMail ); | ||
132 | emit queuedMails( m_queuedMail ); | ||
133 | return; | ||
134 | } | ||
135 | from = getFrom( mail ); | ||
136 | rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); | ||
137 | smtpSend(from,rcpts,data,size); | ||
138 | if (data) { | ||
139 | free(data); | ||
140 | } | ||
141 | if (from) { | ||
142 | free(from); | ||
143 | } | ||
144 | if (rcpts) | ||
145 | smtp_address_list_free( rcpts ); | ||
146 | } | ||
147 | |||
148 | void SMTPwrapper::storeFailedMail(const char*data,unsigned int size, const char*failuremessage) | ||
149 | { | ||
150 | if (data) { | ||
151 | storeMail(data,size,"Sendfailed"); | ||
152 | } | ||
153 | if (failuremessage) { | ||
154 | QMessageBox::critical(0,tr("Error sending mail"), | ||
155 | tr("<center>%1</center>").arg(failuremessage)); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | int SMTPwrapper::start_smtp_tls() | ||
160 | { | ||
161 | if (!m_smtp) { | ||
162 | return MAILSMTP_ERROR_IN_PROCESSING; | ||
163 | } | ||
164 | int err = mailesmtp_starttls(m_smtp); | ||
165 | if (err != MAILSMTP_NO_ERROR) return err; | ||
166 | mailstream_low * low; | ||
167 | mailstream_low * new_low; | ||
168 | low = mailstream_get_low(m_smtp->stream); | ||
169 | if (!low) { | ||
170 | return MAILSMTP_ERROR_IN_PROCESSING; | ||
171 | } | ||
172 | int fd = mailstream_low_get_fd(low); | ||
173 | if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) { | ||
174 | mailstream_low_free(low); | ||
175 | mailstream_set_low(m_smtp->stream, new_low); | ||
176 | } else { | ||
177 | return MAILSMTP_ERROR_IN_PROCESSING; | ||
178 | } | ||
179 | return err; | ||
180 | } | ||
181 | |||
182 | void SMTPwrapper::connect_server() | ||
183 | { | ||
184 | const char *server, *user, *pass; | ||
185 | bool ssl; | ||
186 | uint16_t port; | ||
187 | ssl = false; | ||
188 | bool try_tls = true; | ||
189 | bool force_tls=false; | ||
190 | server = user = pass = 0; | ||
191 | QString failuretext = ""; | ||
192 | |||
193 | if (m_smtp || !m_SmtpAccount) { | ||
194 | return; | ||
195 | } | ||
196 | server = m_SmtpAccount->getServer().latin1(); | ||
197 | if ( m_SmtpAccount->ConnectionType() == 2 ) { | ||
198 | ssl = true; | ||
199 | try_tls = false; | ||
200 | } else if (m_SmtpAccount->ConnectionType() == 1) { | ||
201 | force_tls = true; | ||
202 | } | ||
203 | int result = 1; | ||
204 | port = m_SmtpAccount->getPort().toUInt(); | ||
205 | |||
206 | m_smtp = mailsmtp_new( 20, &progress ); | ||
207 | if ( m_smtp == NULL ) { | ||
208 | /* no failure message cause this happens when problems with memory - than we | ||
209 | we can not display any messagebox */ | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | int err = MAILSMTP_NO_ERROR; | ||
214 | ; // odebug << "Servername " << server << " at port " << port << "" << oendl; | ||
215 | if ( ssl ) { | ||
216 | ; // odebug << "SSL session" << oendl; | ||
217 | err = mailsmtp_ssl_connect( m_smtp, server, port ); | ||
218 | } else { | ||
219 | ; // odebug << "No SSL session" << oendl; | ||
220 | err = mailsmtp_socket_connect( m_smtp, server, port ); | ||
221 | } | ||
222 | if ( err != MAILSMTP_NO_ERROR ) { | ||
223 | ; // odebug << "Error init connection" << oendl; | ||
224 | failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); | ||
225 | result = 0; | ||
226 | } | ||
227 | |||
228 | /* switch to tls after init 'cause there it will send the ehlo */ | ||
229 | if (result) { | ||
230 | err = mailsmtp_init( m_smtp ); | ||
231 | if (err != MAILSMTP_NO_ERROR) { | ||
232 | result = 0; | ||
233 | failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if (try_tls) { | ||
238 | err = start_smtp_tls(); | ||
239 | if (err != MAILSMTP_NO_ERROR) { | ||
240 | try_tls = false; | ||
241 | } else { | ||
242 | err = mailesmtp_ehlo(m_smtp); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if (!try_tls && force_tls) { | ||
247 | result = 0; | ||
248 | failuretext = tr("Error init SMTP tls: %1").arg(mailsmtpError(err)); | ||
249 | } | ||
250 | |||
251 | if (result==1 && m_SmtpAccount->getLogin() ) { | ||
252 | ; // odebug << "smtp with auth" << oendl; | ||
253 | if ( m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty() ) { | ||
254 | // get'em | ||
255 | LoginDialog login( m_SmtpAccount->getUser(), | ||
256 | m_SmtpAccount->getPassword(), NULL, 0, true ); | ||
257 | login.show(); | ||
258 | if ( QDialog::Accepted == login.exec() ) { | ||
259 | // ok | ||
260 | user = login.getUser().latin1(); | ||
261 | pass = login.getPassword().latin1(); | ||
262 | } else { | ||
263 | result = 0; | ||
264 | failuretext=tr("Login aborted - storing mail to localfolder"); | ||
265 | } | ||
266 | } else { | ||
267 | user = m_SmtpAccount->getUser().latin1(); | ||
268 | pass = m_SmtpAccount->getPassword().latin1(); | ||
269 | } | ||
270 | ; // odebug << "session->auth: " << m_smtp->auth << "" << oendl; | ||
271 | if (result) { | ||
272 | err = mailsmtp_auth( m_smtp, (char*)user, (char*)pass ); | ||
273 | if ( err == MAILSMTP_NO_ERROR ) { | ||
274 | ; // odebug << "auth ok" << oendl; | ||
275 | } else { | ||
276 | failuretext = tr("Authentification failed"); | ||
277 | result = 0; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | void SMTPwrapper::disc_server() | ||
284 | { | ||
285 | if (m_smtp) { | ||
286 | mailsmtp_quit( m_smtp ); | ||
287 | mailsmtp_free( m_smtp ); | ||
288 | m_smtp = 0; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | int SMTPwrapper::smtpSend(char*from,clist*rcpts,const char*data,size_t size ) | ||
293 | { | ||
294 | int err,result; | ||
295 | QString failuretext = ""; | ||
296 | |||
297 | connect_server(); | ||
298 | |||
299 | result = 1; | ||
300 | if (m_smtp) { | ||
301 | err = mailsmtp_send( m_smtp, from, rcpts, data, size ); | ||
302 | if ( err != MAILSMTP_NO_ERROR ) { | ||
303 | failuretext=tr("Error sending mail: %1").arg(mailsmtpError(err)); | ||
304 | result = 0; | ||
305 | } | ||
306 | } else { | ||
307 | result = 0; | ||
308 | } | ||
309 | |||
310 | if (!result) { | ||
311 | storeFailedMail(data,size,failuretext); | ||
312 | } else { | ||
313 | ; // odebug << "Mail sent." << oendl; | ||
314 | storeMail(data,size,"Sent"); | ||
315 | } | ||
316 | return result; | ||
317 | } | ||
318 | |||
319 | void SMTPwrapper::sendMail(const Opie::Core::OSmartPointer<Mail>&mail,bool later ) | ||
320 | { | ||
321 | mailmime * mimeMail; | ||
322 | |||
323 | mimeMail = createMimeMail(mail ); | ||
324 | if ( mimeMail == NULL ) { | ||
325 | ; // odebug << "sendMail: error creating mime mail" << oendl; | ||
326 | } else { | ||
327 | sendProgress = new progressMailSend(); | ||
328 | sendProgress->show(); | ||
329 | sendProgress->setMaxMails(1); | ||
330 | smtpSend( mimeMail,later); | ||
331 | ; // odebug << "Clean up done" << oendl; | ||
332 | sendProgress->hide(); | ||
333 | delete sendProgress; | ||
334 | sendProgress = 0; | ||
335 | mailmime_free( mimeMail ); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | int SMTPwrapper::sendQueuedMail(AbstractMail*wrap,const RecMailP&which) { | ||
340 | size_t curTok = 0; | ||
341 | mailimf_fields *fields = 0; | ||
342 | mailimf_field*ffrom = 0; | ||
343 | clist *rcpts = 0; | ||
344 | char*from = 0; | ||
345 | int res = 0; | ||
346 | |||
347 | encodedString * data = wrap->fetchRawBody(which); | ||
348 | if (!data) | ||
349 | return 0; | ||
350 | int err = mailimf_fields_parse( data->Content(), data->Length(), &curTok, &fields ); | ||
351 | if (err != MAILIMF_NO_ERROR) { | ||
352 | delete data; | ||
353 | delete wrap; | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | rcpts = createRcptList( fields ); | ||
358 | ffrom = getField(fields, MAILIMF_FIELD_FROM ); | ||
359 | from = getFrom(ffrom); | ||
360 | |||
361 | if (rcpts && from) { | ||
362 | res = smtpSend(from,rcpts,data->Content(),data->Length()); | ||
363 | } | ||
364 | if (fields) { | ||
365 | mailimf_fields_free(fields); | ||
366 | fields = 0; | ||
367 | } | ||
368 | if (data) { | ||
369 | delete data; | ||
370 | } | ||
371 | if (from) { | ||
372 | free(from); | ||
373 | } | ||
374 | if (rcpts) { | ||
375 | smtp_address_list_free( rcpts ); | ||
376 | } | ||
377 | return res; | ||
378 | } | ||
379 | |||
380 | /* this is a special fun */ | ||
381 | bool SMTPwrapper::flushOutbox() { | ||
382 | bool returnValue = true; | ||
383 | |||
384 | ; // odebug << "Sending the queue" << oendl; | ||
385 | if (!m_SmtpAccount) { | ||
386 | ; // odebug << "No smtp account given" << oendl; | ||
387 | return false; | ||
388 | } | ||
389 | |||
390 | bool reset_user_value = false; | ||
391 | QString localfolders = AbstractMail::defaultLocalfolder(); | ||
392 | AbstractMail*wrap = AbstractMail::getWrapper(localfolders); | ||
393 | if (!wrap) { | ||
394 | ; // odebug << "memory error" << oendl; | ||
395 | return false; | ||
396 | } | ||
397 | QString oldPw, oldUser; | ||
398 | QValueList<RecMailP> mailsToSend; | ||
399 | QValueList<RecMailP> mailsToRemove; | ||
400 | QString mbox("Outgoing"); | ||
401 | wrap->listMessages(mbox,mailsToSend); | ||
402 | if (mailsToSend.count()==0) { | ||
403 | delete wrap; | ||
404 | ; // odebug << "No mails to send" << oendl; | ||
405 | return false; | ||
406 | } | ||
407 | |||
408 | oldPw = m_SmtpAccount->getPassword(); | ||
409 | oldUser = m_SmtpAccount->getUser(); | ||
410 | if (m_SmtpAccount->getLogin() && (m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty()) ) { | ||
411 | // get'em | ||
412 | QString user,pass; | ||
413 | LoginDialog login( m_SmtpAccount->getUser(), m_SmtpAccount->getPassword(), NULL, 0, true ); | ||
414 | login.show(); | ||
415 | if ( QDialog::Accepted == login.exec() ) { | ||
416 | // ok | ||
417 | user = login.getUser().latin1(); | ||
418 | pass = login.getPassword().latin1(); | ||
419 | reset_user_value = true; | ||
420 | m_SmtpAccount->setUser(user); | ||
421 | m_SmtpAccount->setPassword(pass); | ||
422 | } else { | ||
423 | return true; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | |||
428 | sendProgress = new progressMailSend(); | ||
429 | sendProgress->show(); | ||
430 | sendProgress->setMaxMails(mailsToSend.count()); | ||
431 | |||
432 | while (mailsToSend.count()>0) { | ||
433 | if (sendQueuedMail(wrap, (*mailsToSend.begin()))==0) { | ||
434 | QMessageBox::critical(0,tr("Error sending mail"), | ||
435 | tr("Error sending queued mail - breaking")); | ||
436 | returnValue = false; | ||
437 | break; | ||
438 | } | ||
439 | mailsToRemove.append((*mailsToSend.begin())); | ||
440 | mailsToSend.remove(mailsToSend.begin()); | ||
441 | sendProgress->setCurrentMails(mailsToRemove.count()); | ||
442 | } | ||
443 | if (reset_user_value) { | ||
444 | m_SmtpAccount->setUser(oldUser); | ||
445 | m_SmtpAccount->setPassword(oldPw); | ||
446 | } | ||
447 | Config cfg( "mail" ); | ||
448 | cfg.setGroup( "Status" ); | ||
449 | m_queuedMail = 0; | ||
450 | cfg.writeEntry( "outgoing", m_queuedMail ); | ||
451 | emit queuedMails( m_queuedMail ); | ||
452 | sendProgress->hide(); | ||
453 | delete sendProgress; | ||
454 | sendProgress = 0; | ||
455 | wrap->deleteMails(mbox,mailsToRemove); | ||
456 | delete wrap; | ||
457 | return returnValue; | ||
458 | } | ||