summaryrefslogtreecommitdiff
path: root/noncore/net/mailit/emailhandler.cpp
Unidiff
Diffstat (limited to 'noncore/net/mailit/emailhandler.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/mailit/emailhandler.cpp630
1 files changed, 0 insertions, 630 deletions
diff --git a/noncore/net/mailit/emailhandler.cpp b/noncore/net/mailit/emailhandler.cpp
deleted file mode 100644
index 06e978d..0000000
--- a/noncore/net/mailit/emailhandler.cpp
+++ b/dev/null
@@ -1,630 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved.
3**
4** This file is part of Qt Palmtop Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <qfileinfo.h>
21#include <stdlib.h>
22#include <qapplication.h>
23#include <qmessagebox.h>
24#include <qcstring.h>
25#include "emailhandler.h"
26#include <qpe/applnk.h>
27#include <qpe/filemanager.h>
28
29QCollection::Item EnclosureList::newItem(QCollection::Item d)
30{
31 return dupl( (Enclosure *) d);
32}
33
34Enclosure* EnclosureList::dupl(Enclosure *in)
35{
36 ac = new Enclosure(*in);
37 return ac;
38}
39
40EmailHandler::EmailHandler()
41{
42 qDebug("EMailHandler::EmailHandler");
43
44 smtpClient = new SmtpClient();
45 popClient = new PopClient();
46
47 connect(smtpClient, SIGNAL(errorOccurred(int, const QString &)), this,
48 SIGNAL(smtpError(int, const QString &)) );
49 connect(smtpClient, SIGNAL(mailSent()), this, SIGNAL(mailSent()) );
50 connect(smtpClient, SIGNAL(updateStatus(const QString &)), this,
51 SIGNAL(updateSmtpStatus(const QString &)) );
52
53 connect(popClient, SIGNAL(errorOccurred(int, const QString &)), this,
54 SIGNAL(popError(int, const QString &)) );
55 connect(popClient, SIGNAL(newMessage(const QString &, int, uint, bool)),
56 this, SLOT(messageArrived(const QString &, int, uint, bool)) );
57 connect(popClient, SIGNAL(updateStatus(const QString &)), this,
58 SIGNAL(updatePopStatus(const QString &)) );
59 connect(popClient, SIGNAL(mailTransfered(int)), this,
60 SIGNAL(mailTransfered(int)) );
61
62
63 //relaying size information
64 connect(popClient, SIGNAL(currentMailSize(int)),
65 this, SIGNAL(currentMailSize(int)) );
66 connect(popClient, SIGNAL(downloadedSize(int)),
67 this, SIGNAL(downloadedSize(int)) );
68}
69
70void EmailHandler::sendMail(QList<Email> *mailList)
71{
72 Email *currentMail;
73 QString temp;
74 QString userName = QString::null;
75 // not supported by ALL SMTP servers in the MAIL From field
76 // userName = "\""+mailAccount.name+"\"";
77 userName += "<" + mailAccount.emailAddress + ">";
78
79 for (currentMail = mailList->first(); currentMail != 0;
80 currentMail = mailList->next()) {
81
82 if (encodeMime(currentMail) == 0) {
83 smtpClient->addMail(userName, currentMail->subject,
84 currentMail->recipients, currentMail->rawMail);
85 } else { //error
86 temp = tr("Could not locate all files in \nmail with subject: ") +
87 currentMail->subject;
88 temp += tr("\nMail has NOT been sent");
89 QMessageBox::warning(qApp->activeWindow(), tr("Attachment error"), temp, tr("OK\n"));
90
91 }
92 }
93 smtpClient->newConnection(mailAccount.smtpServer, 25);
94}
95
96void EmailHandler::setAccount(MailAccount account)
97{
98 mailAccount = account;
99}
100
101void EmailHandler::getMail()
102{
103 popClient->setAccount(mailAccount.popUserName, mailAccount.popPasswd);
104 if (mailAccount.synchronize) {
105 popClient->setSynchronize(mailAccount.lastServerMailCount);
106 } else {
107 popClient->removeSynchronize();
108 }
109
110 headers = FALSE;
111 //popClient->headersOnly(headers, 0);
112 popClient->newConnection(mailAccount.popServer, 110);
113}
114
115void EmailHandler::getMailHeaders()
116{
117 popClient->setAccount(mailAccount.popUserName, mailAccount.popPasswd);
118 mailAccount.synchronize ? popClient->setSynchronize(mailAccount.lastServerMailCount): popClient->removeSynchronize();
119
120 headers = TRUE;
121 popClient->headersOnly(headers, mailAccount.syncLimit); //less than requested syncLimit, download all
122 qDebug("Initiating connection");
123 popClient->newConnection(mailAccount.popServer, 110);
124}
125
126void EmailHandler::getMailByList(MailList *mailList)
127{
128 if (mailList->count() == 0) { //should not occur though
129 emit mailTransfered(0);
130 return;
131 }
132
133 headers = FALSE;
134 popClient->headersOnly(FALSE, 0);
135
136 popClient->setAccount(mailAccount.popUserName,mailAccount.popPasswd);
137 popClient->setSelectedMails(mailList);
138 popClient->newConnection(mailAccount.popServer, 110);
139 }
140
141void EmailHandler::messageArrived(const QString &message, int id, uint size, bool complete)
142{
143 Email mail;
144
145 mail.rawMail = message;
146 mail.serverId = id;
147 mail.size = size;
148 mail.downloaded = complete;
149
150 emit mailArrived(mail, FALSE);
151}
152
153bool EmailHandler::parse(const QString &in, const QString &lineShift, Email *mail)
154{
155 QString temp, boundary;
156 int pos;
157 QString delimiter, header, body, mimeHeader, mimeBody;
158 QString content, contentType, contentAttribute, id, encoding;
159 QString fileName, storedName;
160 int enclosureId = 0;
161
162 mail->rawMail = in;
163 mail->received = TRUE;
164 mail->files.setAutoDelete(TRUE);
165
166 temp = lineShift + "." + lineShift;
167
168 if (in.right(temp.length()) != temp) {
169 mail->rawMail += temp;
170 }
171
172
173 delimiter = lineShift + lineShift; // "\n\n" or "\r\n\r\n"
174 pos = in.find(delimiter, 0, FALSE);
175 header = in.left(pos);
176 body = in.right(in.length() - pos - delimiter.length());
177 if ((body.at(body.length()-2) == '.') && (body.at(body.length()-3) == '\n'))
178 body.truncate(body.length()-2);
179
180 // TextParser p(header, lineShift);
181 TextParser * lp = new TextParser(header, lineShift);
182#define p (*lp)
183
184 if ((pos = p.find("FROM",':', 0, TRUE)) != -1) {
185 pos++;
186 if (p.separatorAt(pos) == ' ') {
187 mail->from = p.getString(&pos, '<', false);
188 mail->from = mail->from.stripWhiteSpace();
189 if ( (mail->from.length() > 2) && (mail->from[0] == '"') ) {
190 mail->from = mail->from.left(mail->from.length() - 1);
191 mail->from = mail->from.right(mail->from.length() - 1);
192 }
193 pos++;
194 mail->fromMail = p.getString(&pos, '>', false);
195 } else {
196 if (p.separatorAt(pos) == '<') //No name.. nasty
197 pos++;
198 //pos++;
199 mail->fromMail = p.getString(&pos, 'z', TRUE);
200 if (mail->fromMail.at(mail->fromMail.length()-1) == '>')
201 mail->fromMail.truncate(mail->fromMail.length() - 1);
202 mail->from=mail->fromMail;
203 }
204 }
205
206 pos=0;
207
208 //Search for To: after the FROM: attribute to prevent hitting the Delivered-To:
209 while((pos = p.find("TO",':', pos+1, TRUE))!=-1)
210 {
211 QString rec;
212
213 if (p.separatorAt(pos-1)!='-') //The - separator means that this is a Delivered-To: or Reply-To:
214 {
215 pos++;
216 mail->recipients.append(p.getString(&pos, '\r', TRUE));
217 }
218 }
219 //
220 //if (pos==-1) mail->recipients.append (tr("undisclosed recipients") );
221
222 if ((pos = p.find("CC",':', 0, TRUE)) != -1)
223 {
224 pos++;
225 mail->carbonCopies.append (p.getString(&pos, 'z', TRUE) );
226 }
227
228 if ((pos = p.find("SUBJECT",':', 0, TRUE)) != -1) {
229 pos++;
230 mail->subject = p.getString(&pos, 'z', TRUE);
231 }
232
233 if ((pos = p.find("DATE",':', 0, TRUE)) != -1) {
234 pos++;
235 mail->date = p.getString(&pos, 'z', TRUE);
236 }
237
238
239
240 if ((pos = p.find("MESSAGE",'-', 0, TRUE)) != -1) {
241 pos++;
242 if ( (p.wordAt(pos).upper() == "ID") &&
243 (p.separatorAt(pos) == ':') ) {
244
245 id = p.getString(&pos, 'z', TRUE);
246 mail->id = id;
247 }
248 }
249
250 pos = 0;
251 while ( ((pos = p.find("MIME",'-', pos, TRUE)) != -1) ) {
252 pos++;
253 if ( (p.wordAt(pos).upper() == "VERSION") &&
254 (p.separatorAt(pos) == ':') ) {
255 pos++;
256 if (p.getString(&pos, 'z', true) == "1.0") {
257 mail->mimeType = 1;
258 }
259 }
260 }
261
262 if (mail->mimeType == 1) {
263 boundary = "";
264 if ((pos = p.find("BOUNDARY", '=', 0, TRUE)) != -1) {
265 pos++;
266 boundary = p.getString(&pos, 'z', true);
267 if (boundary[0] == '"') {
268 boundary = boundary.left(boundary.length() - 1); //strip "
269 boundary = boundary.right(boundary.length() - 1); //strip "
270 }
271 boundary = "--" + boundary; //create boundary field
272 }
273
274 if (boundary == "") { //fooled by Mime-Version
275 mail->body = body;
276 mail->bodyPlain = body;
277 delete lp;
278 return mail;
279 }
280
281 while (body.length() > 0) {
282 pos = body.find(boundary, 0, FALSE);
283 pos = body.find(delimiter, pos, FALSE);
284 mimeHeader = body.left(pos);
285 mimeBody = body.right(body.length() - pos - delimiter.length());
286 TextParser bp(mimeHeader, lineShift);
287
288 contentType = "";
289 contentAttribute = "";
290 fileName = "";
291 if ((pos = bp.find("CONTENT",'-', 0, TRUE)) != -1) {
292 pos++;
293 if ( (bp.wordAt(pos).upper() == "TYPE") &&
294 (bp.separatorAt(pos) == ':') ) {
295 contentType = bp.nextWord().upper();
296 if (bp.nextSeparator() == '/')
297 contentAttribute = bp.nextWord().upper();
298 content = contentType + "/" + contentAttribute;
299 }
300 if ((pos = bp.find("ENCODING",':', 0, TRUE)) != -1) {
301 pos++;
302 encoding = bp.getString(&pos, 'z', TRUE);
303 }
304
305 if ( (pos = bp.find("FILENAME",'=', 0, TRUE)) != -1) {
306 pos++;
307 fileName = bp.getString(&pos, 'z', TRUE);
308 fileName = fileName.right(fileName.length() - 1);
309 fileName = fileName.left(fileName.length() - 1);
310 }
311
312 }
313 pos = mimeBody.find(boundary, 0, FALSE);
314 if (pos == -1) //should not occur, malformed mail
315 pos = mimeBody.length();
316 body = mimeBody.right(mimeBody.length() - pos);
317 mimeBody = mimeBody.left(pos);
318
319 if (fileName != "") { //attatchments of some type, audio, image etc.
320
321 Enclosure e;
322 e.id = enclosureId;
323 e.originalName = fileName;
324 e.contentType = contentType;
325 e.contentAttribute = contentAttribute;
326 e.encoding = encoding;
327 e.body = mimeBody;
328 e.saved = FALSE;
329 mail->addEnclosure(&e);
330 enclosureId++;
331
332 } else if (contentType == "TEXT") {
333 if (contentAttribute == "PLAIN") {
334 mail->body = mimeBody;
335 mail->bodyPlain = mimeBody;
336 }
337 if (contentAttribute == "HTML") {
338 mail->body = mimeBody;
339 }
340 }
341 }
342 } else {
343 mail->bodyPlain = body;
344 mail->body = body;
345 }
346 delete lp;
347 return TRUE;
348}
349
350bool EmailHandler::getEnclosure(Enclosure *ePtr)
351{
352 QFile f(ePtr->path + ePtr->name);
353 char src[4];
354 char *destPtr;
355 QByteArray buffer;
356 uint bufCount, pos, decodedCount, size, x;
357
358 if (! f.open(IO_WriteOnly) ) {
359 qWarning("could not save: " + ePtr->path + ePtr->name);
360 return FALSE;
361 }
362
363 if (ePtr->encoding.upper() == "BASE64") {
364 size = (ePtr->body.length() * 3 / 4); //approximate size (always above)
365 buffer.resize(size);
366 bufCount = 0;
367 pos = 0;
368 destPtr = buffer.data();
369
370 while (pos < ePtr->body.length()) {
371 decodedCount = 4;
372 x = 0;
373 while ( (x < 4) && (pos < ePtr->body.length()) ) {
374 src[x] = ePtr->body[pos].latin1();
375 pos++;
376 if (src[x] == '\r' || src[x] == '\n' || src[x] == ' ')
377 x--;
378 x++;
379 }
380 if (x > 1) {
381 decodedCount = parse64base(src, destPtr);
382 destPtr += decodedCount;
383 bufCount += decodedCount;
384 }
385 }
386
387 buffer.resize(bufCount); //set correct length of file
388 f.writeBlock(buffer);
389 } else {
390 QTextStream t(&f);
391 t << ePtr->body;
392 }
393 return TRUE;
394}
395
396int EmailHandler::parse64base(char *src, char *bufOut) {
397
398 char c, z;
399 char li[4];
400 int processed;
401
402 //conversion table withouth table...
403 for (int x = 0; x < 4; x++) {
404 c = src[x];
405
406 if ( (int) c >= 'A' && (int) c <= 'Z')
407 li[x] = (int) c - (int) 'A';
408 if ( (int) c >= 'a' && (int) c <= 'z')
409 li[x] = (int) c - (int) 'a' + 26;
410 if ( (int) c >= '0' && (int) c <= '9')
411 li[x] = (int) c - (int) '0' + 52;
412 if (c == '+')
413 li[x] = 62;
414 if (c == '/')
415 li[x] = 63;
416 }
417
418 processed = 1;
419 bufOut[0] = (char) li[0] & (32+16+8+4+2+1); //mask out top 2 bits
420 bufOut[0] <<= 2;
421 z = li[1] >> 4;
422 bufOut[0] = bufOut[0] | z; //first byte retrived
423
424 if (src[2] != '=') {
425 bufOut[1] = (char) li[1] & (8+4+2+1); //mask out top 4 bits
426 bufOut[1] <<= 4;
427 z = li[2] >> 2;
428 bufOut[1] = bufOut[1] | z; //second byte retrived
429 processed++;
430
431 if (src[3] != '=') {
432 bufOut[2] = (char) li[2] & (2+1); //mask out top 6 bits
433 bufOut[2] <<= 6;
434 z = li[3];
435 bufOut[2] = bufOut[2] | z; //third byte retrieved
436 processed++;
437 }
438 }
439 return processed;
440}
441
442int EmailHandler::encodeMime(Email *mail)
443{
444
445 QString fileName, fileType, contentType, newBody, boundary;
446 Enclosure *ePtr;
447 QString userName;
448
449 if ( ! mailAccount.name.isEmpty() ) {
450 userName = "\"" + mailAccount.name + "\" <" + mailAccount.emailAddress + ">";
451 } else {
452 userName = "<" + mailAccount.emailAddress + ">";
453 }
454
455 //add standard headers
456 newBody = "From: " + userName + "\r\nTo: ";
457 for (QStringList::Iterator it = mail->recipients.begin(); it != mail->recipients.end(); ++it ) {
458 newBody += *it + " ";
459 }
460
461 newBody += "\r\nCC: ";
462
463 for (QStringList::Iterator it = mail->carbonCopies.begin(); it != mail->carbonCopies.end(); ++it ) {
464 newBody += *it + " ";
465 }
466
467 newBody += "\r\nSubject: " + mail->subject + "\r\n";
468
469 if (mail->files.count() == 0) { //just a simple mail
470 newBody += "\r\n" + mail->body;
471 mail->rawMail = newBody;
472 return 0;
473 }
474
475 //Build mime encoded mail
476 boundary = "-----4345=next_bound=0495----";
477
478 newBody += "Mime-Version: 1.0\r\n";
479 newBody += "Content-Type: multipart/mixed; boundary=\"" +
480 boundary + "\"\r\n\r\n";
481
482 newBody += "This is a multipart message in Mime 1.0 format\r\n\r\n";
483 newBody += "--" + boundary + "\r\nContent-Type: text/plain\r\n\r\n";
484 newBody += mail->body;
485
486 for ( ePtr=mail->files.first(); ePtr != 0; ePtr=mail->files.next() ) {
487 fileName = ePtr->originalName;
488 fileType = ePtr->contentType;
489 QFileInfo fi(fileName);
490
491 // This specification of contentType is temporary
492 contentType = "";
493 if (fileType == "Picture") {
494 contentType = "image/x-image";
495 } else if (fileType == "Document") {
496 contentType = "text/plain";
497 } else if (fileType == "Sound") {
498 contentType = "audio/x-wav";
499 } else if (fileType == "Movie") {
500 contentType = "video/mpeg";
501 } else {
502 contentType = "application/octet-stream";
503 }
504
505 newBody += "\r\n\r\n--" + boundary + "\r\n";
506 newBody += "Content-Type: " + contentType + "; name=\"" +
507 fi.fileName() + "\"\r\n";
508 newBody += "Content-Transfer-Encoding: base64\r\n";
509 newBody += "Content-Disposition: inline; filename=\"" +
510 fi.fileName() + "\"\r\n\r\n";
511
512 if (encodeFile(fileName, &newBody) == -1) //file not found?
513 return -1;
514 }
515
516 newBody += "\r\n\r\n--" + boundary + "--";
517 mail->rawMail = newBody;
518
519 return 0;
520}
521
522int EmailHandler::encodeFile(const QString &fileName, QString *toBody)
523{
524 char *fileData;
525 char *dataPtr;
526 QString temp;
527 uint dataSize, count;
528 QFile f(fileName);
529
530 if (! f.open(IO_ReadOnly) ) {
531 qWarning("could not open file: " + fileName);
532 return -1;
533 }
534 QTextStream s(&f);
535 dataSize = f.size();
536 fileData = (char *) malloc(dataSize + 3);
537 s.readRawBytes(fileData, dataSize);
538
539 temp = "";
540 dataPtr = fileData;
541 count = 0;
542 while (dataSize > 0) {
543 if (dataSize < 3) {
544 encode64base(dataPtr, &temp, dataSize);
545 dataSize = 0;
546 } else {
547 encode64base(dataPtr, &temp, 3);
548 dataSize -= 3;
549 dataPtr += 3;
550 count += 4;
551 }
552 if (count > 72) {
553 count = 0;
554 temp += "\r\n";
555 }
556 }
557 toBody->append(temp);
558
559 delete(fileData);
560 f.close();
561 return 0;
562}
563
564void EmailHandler::encode64base(char *src, QString *dest, int len)
565{
566 QString temp;
567 uchar c;
568 uchar bufOut[4];
569
570 bufOut[0] = src[0];
571 bufOut[0] >>= 2; //Done byte 0
572
573 bufOut[1] = src[0];
574 bufOut[1] = bufOut[1] & (1 + 2); //mask out top 6 bits
575 bufOut[1] <<= 4; //copy up 4 places
576 if (len > 1) {
577 c = src[1];
578 } else {
579 c = 0;
580 }
581
582 c = c & (16 + 32 + 64 + 128);
583 c >>= 4;
584 bufOut[1] = bufOut[1] | c; //Done byte 1
585
586 bufOut[2] = src[1];
587 bufOut[2] = bufOut[2] & (1 + 2 + 4 + 8);
588 bufOut[2] <<= 2;
589 if (len > 2) {
590 c = src[2];
591 } else {
592 c = 0;
593 }
594 c >>= 6;
595 bufOut[2] = bufOut[2] | c;
596
597 bufOut[3] = src[2];
598 bufOut[3] = bufOut[3] & (1 + 2 + 4 + 8 + 16 + 32);
599
600 if (len == 1) {
601 bufOut[2] = 64;
602 bufOut[3] = 64;
603 }
604 if (len == 2) {
605 bufOut[3] = 64;
606 }
607 for (int x = 0; x < 4; x++) {
608 if (bufOut[x] <= 25)
609 bufOut[x] += (uint) 'A';
610 else if (bufOut[x] >= 26 && bufOut[x] <= 51)
611 bufOut[x] += (uint) 'a' - 26;
612 else if (bufOut[x] >= 52 && bufOut[x] <= 61)
613 bufOut[x] += (uint) '0' - 52;
614 else if (bufOut[x] == 62)
615 bufOut[x] = '+';
616 else if (bufOut[x] == 63)
617 bufOut[x] = '/';
618 else if (bufOut[x] == 64)
619 bufOut[x] = '=';
620
621 dest->append(bufOut[x]);
622 }
623}
624
625void EmailHandler::cancel()
626{
627 popClient->errorHandling(ErrCancel);
628 smtpClient->errorHandling(ErrCancel);
629}
630