00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kalarm.h"
00022 #include "kamail.h"
00023
00024 #include "functions.h"
00025 #include "kalarmapp.h"
00026 #include "mainwindow.h"
00027 #include "preferences.h"
00028
00029 #include <stdlib.h>
00030 #include <time.h>
00031 #include <sys/stat.h>
00032 #include <sys/time.h>
00033 #include <pwd.h>
00034
00035 #include <QFile>
00036 #include <QList>
00037 #include <QRegExp>
00038 #include <QByteArray>
00039 #include <QTextStream>
00040 #include <QtDBus/QtDBus>
00041
00042 #include <kstandarddirs.h>
00043 #include <kmessagebox.h>
00044 #include <kshell.h>
00045 #include <klocale.h>
00046 #include <kaboutdata.h>
00047 #include <kfileitem.h>
00048 #include <kio/netaccess.h>
00049 #include <ktemporaryfile.h>
00050 #include <kemailsettings.h>
00051 #include <kdebug.h>
00052 #include <k3resolver.h>
00053
00054 #include <kpimidentities/identitymanager.h>
00055 #include <kpimidentities/identity.h>
00056 #include <kpimutils/email.h>
00057 #include <mailtransport/transportmanager.h>
00058 #include <mailtransport/transport.h>
00059 #include <mailtransport/transportjob.h>
00060 #include <kcal/person.h>
00061
00062 #include <kmime/kmime_header_parsing.h>
00063
00064 #ifdef KMAIL_SUPPORTED
00065 #include "kmailinterface.h"
00066
00067 static const char* KMAIL_DBUS_SERVICE = "org.kde.kmail";
00068 static const char* KMAIL_DBUS_PATH = "/KMail";
00069 #endif
00070
00071
00072 namespace HeaderParsing
00073 {
00074 bool parseAddress( const char* & scursor, const char * const send,
00075 KMime::Types::Address & result, bool isCRLF=false );
00076 bool parseAddressList( const char* & scursor, const char * const send,
00077 QList<KMime::Types::Address> & result, bool isCRLF=false );
00078 }
00079
00080
00081 static QString initHeaders(const KAMail::JobData&, bool dateId);
00082
00083 QString KAMail::i18n_NeedFromEmailAddress()
00084 { return i18nc("@info/plain", "A 'From' email address must be configured in order to execute email alarms."); }
00085
00086 QString KAMail::i18n_sent_mail()
00087 { return i18nc("@info/plain KMail folder name: this should be translated the same as in kmail", "sent-mail"); }
00088
00089 KAMail* KAMail::mInstance = 0;
00090 QQueue<MailTransport::TransportJob*> KAMail::mJobs;
00091 QQueue<KAMail::JobData> KAMail::mJobData;
00092 KPIMIdentities::IdentityManager* KAMail::mIdentityManager = 0;
00093
00094 KAMail* KAMail::instance()
00095 {
00096 if (!mInstance)
00097 mInstance = new KAMail();
00098 return mInstance;
00099 }
00100
00101 KPIMIdentities::IdentityManager* KAMail::identityManager()
00102 {
00103 if (!mIdentityManager)
00104 mIdentityManager = new KPIMIdentities::IdentityManager(true);
00105 return mIdentityManager;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 int KAMail::send(JobData& jobdata, QStringList& errmsgs)
00116 {
00117 QString err;
00118 KPIMIdentities::Identity identity;
00119 if (!jobdata.event.emailFromId())
00120 jobdata.from = Preferences::emailAddress();
00121 else
00122 {
00123 identity = mIdentityManager->identityForUoid(jobdata.event.emailFromId());
00124 if (identity.isNull())
00125 {
00126 kError() << "Identity" << jobdata.event.emailFromId() << "not found";
00127 errmsgs = errors(i18nc("@info", "Invalid 'From' email address.<nl/>Email identity <resource>%1</resource> not found", jobdata.event.emailFromId()));
00128 return -1;
00129 }
00130 jobdata.from = identity.fullEmailAddr();
00131 if (jobdata.from.isEmpty())
00132 {
00133 kError() << "Identity" << identity.identityName() << "uoid" << identity.uoid() << ": no email address";
00134 errmsgs = errors(i18nc("@info", "Invalid 'From' email address.<nl/>Email identity <resource>%1</resource> has no email address", identity.identityName()));
00135 return -1;
00136 }
00137 }
00138 if (jobdata.from.isEmpty())
00139 {
00140 switch (Preferences::emailFrom())
00141 {
00142 #ifdef KMAIL_SUPPORTED
00143 case Preferences::MAIL_FROM_KMAIL:
00144 errmsgs = errors(i18nc("@info", "<para>No 'From' email address is configured (no default email identity found)</para>"
00145 "<para>Please set it in <application>KMail</application> or in the <application>KAlarm</application> Preferences dialog.</para>"));
00146 break;
00147 #endif
00148 case Preferences::MAIL_FROM_SYS_SETTINGS:
00149 errmsgs = errors(i18nc("@info", "<para>No 'From' email address is configured.</para>"
00150 "<para>Please set it in the KDE System Settings or in the <application>KAlarm</application> Preferences dialog.</para>"));
00151 break;
00152 case Preferences::MAIL_FROM_ADDR:
00153 default:
00154 errmsgs = errors(i18nc("@info", "<para>No 'From' email address is configured.</para>"
00155 "<para>Please set it in the <application>KAlarm</application> Preferences dialog.</para>"));
00156 break;
00157 }
00158 return -1;
00159 }
00160 jobdata.bcc = (jobdata.event.emailBcc() ? Preferences::emailBccAddress() : QString());
00161 kDebug() << "To:" << jobdata.event.emailAddresses(",")
00162 << endl << "Subject:" << jobdata.event.emailSubject();
00163
00164 if (Preferences::emailClient() == Preferences::sendmail)
00165 {
00166
00167 QString textComplete;
00168 QString command = KStandardDirs::findExe(QLatin1String("sendmail"),
00169 QLatin1String("/sbin:/usr/sbin:/usr/lib"));
00170 if (!command.isNull())
00171 {
00172 command += QLatin1String(" -f ");
00173 command += KPIMUtils::extractEmailAddress(jobdata.from);
00174 command += QLatin1String(" -oi -t ");
00175 textComplete = initHeaders(jobdata, false);
00176 }
00177 else
00178 {
00179 command = KStandardDirs::findExe(QLatin1String("mail"));
00180 if (command.isNull())
00181 {
00182 errmsgs = errors(i18nc("@info", "<command>%1</command> not found", QLatin1String("sendmail")));
00183 return -1;
00184 }
00185
00186 command += QLatin1String(" -s ");
00187 command += KShell::quoteArg(jobdata.event.emailSubject());
00188
00189 if (!jobdata.bcc.isEmpty())
00190 {
00191 command += QLatin1String(" -b ");
00192 command += KShell::quoteArg(jobdata.bcc);
00193 }
00194
00195 command += ' ';
00196 command += jobdata.event.emailAddresses(" ");
00197 }
00198
00199
00200
00201 err = appendBodyAttachments(textComplete, jobdata.event);
00202 if (!err.isNull())
00203 {
00204 errmsgs = errors(err);
00205 return -1;
00206 }
00207
00208
00209 FILE* fd = popen(command.toLocal8Bit(), "w");
00210 if (!fd)
00211 {
00212 kError() << "Unable to open a pipe to" << command;
00213 errmsgs = errors();
00214 return -1;
00215 }
00216 fwrite(textComplete.toLocal8Bit(), textComplete.length(), 1, fd);
00217 pclose(fd);
00218
00219 #ifdef KMAIL_SUPPORTED
00220 if (Preferences::emailCopyToKMail())
00221 {
00222
00223 err = addToKMailFolder(jobdata, "sent-mail", true);
00224 if (!err.isNull())
00225 errmsgs = errors(err, COPY_ERROR);
00226 }
00227 #endif
00228
00229 if (jobdata.allowNotify)
00230 notifyQueued(jobdata.event);
00231 return 1;
00232 }
00233 else
00234 {
00235
00236 MailTransport::TransportManager* manager = MailTransport::TransportManager::self();
00237 MailTransport::Transport* transport = manager->transportByName(identity.transport(), true);
00238 if (!transport)
00239 {
00240 kError() << "No mail transport found for identity" << identity.identityName() << "uoid" << identity.uoid();
00241 errmsgs = errors(i18nc("@info", "No mail transport configured for email identity <resource>%1</resource>", identity.identityName()));
00242 return -1;
00243 }
00244 int transportId = transport->id();
00245 MailTransport::TransportJob* mailjob = manager->createTransportJob(transportId);
00246 if (!mailjob)
00247 {
00248 kError() << "Failed to create mail transport job for identity" << identity.identityName() << "uoid" << identity.uoid();
00249 errmsgs = errors(i18nc("@info", "Unable to create mail transport job"));
00250 return -1;
00251 }
00252 QString message = initHeaders(jobdata, true);
00253 message += jobdata.event.message();
00254 err = appendBodyAttachments(message, jobdata.event);
00255 if (!err.isNull())
00256 {
00257 errmsgs = errors(err);
00258 return -1;
00259 }
00260 mailjob->setSender(jobdata.from);
00261 mailjob->setTo(QStringList(jobdata.event.emailAddresses()));
00262 if (!jobdata.bcc.isEmpty())
00263 mailjob->setBcc(QStringList(jobdata.bcc));
00264 mailjob->setData(message.toLocal8Bit());
00265 mJobs.enqueue(mailjob);
00266 mJobData.enqueue(jobdata);
00267 if (mJobs.count() == 1)
00268 {
00269
00270 connect(mailjob, SIGNAL(result(KJob*)), instance(), SLOT(slotEmailSent(KJob*)));
00271 mailjob->start();
00272 }
00273 return 0;
00274 }
00275 }
00276
00277
00278
00279
00280 void KAMail::slotEmailSent(KJob* job)
00281 {
00282 QStringList errmsgs;
00283 JobData jobdata;
00284 if (job->error())
00285 {
00286 kError() << "Failed:" << job->error();
00287 errmsgs = errors(job->errorString(), SEND_ERROR);
00288 }
00289 if (mJobs.isEmpty() || mJobData.isEmpty() || job != mJobs.head())
00290 {
00291
00292 kError() << "Wrong job at head of queue: wiping queue";
00293 mJobs.clear();
00294 mJobData.clear();
00295 if (!errmsgs.isEmpty())
00296 theApp()->emailSent(jobdata, errmsgs);
00297 errmsgs.clear();
00298 errmsgs += i18nc("@info", "Emails may not have been sent");
00299 errmsgs += i18nc("@info", "Program error");
00300 theApp()->emailSent(jobdata, errmsgs);
00301 return;
00302 }
00303 mJobs.dequeue();
00304 jobdata = mJobData.dequeue();
00305 if (jobdata.allowNotify)
00306 notifyQueued(jobdata.event);
00307 theApp()->emailSent(jobdata, errmsgs);
00308 if (!mJobs.isEmpty())
00309 {
00310
00311 connect(mJobs.head(), SIGNAL(result(KJob*)), instance(), SLOT(slotEmailSent(KJob*)));
00312 mJobs.head()->start();
00313 }
00314 }
00315
00316 #ifdef KMAIL_SUPPORTED
00317
00318
00319
00320
00321
00322 QString KAMail::addToKMailFolder(const JobData& data, const char* folder, bool checkKmailRunning)
00323 {
00324 QString err;
00325 if (checkKmailRunning)
00326 err = KAlarm::runKMail(true);
00327 if (err.isNull())
00328 {
00329 QString message = initHeaders(data, true);
00330 err = appendBodyAttachments(message, data.event);
00331 if (!err.isNull())
00332 return err;
00333
00334
00335 KTemporaryFile tmpFile;
00336 if (!tmpFile.open())
00337 {
00338 kError() << folder << ": Unable to open a temporary mail file";
00339 return QString("");
00340 }
00341 QTextStream stream(&tmpFile);
00342 stream << message;
00343 stream.flush();
00344 if (tmpFile.error() != QFile::NoError)
00345 {
00346 kError() << folder << ": Error" << tmpFile.errorString() << " writing to temporary mail file";
00347 return QString("");
00348 }
00349
00350
00351 org::kde::kmail::kmail kmail(KMAIL_DBUS_SERVICE, KMAIL_DBUS_PATH, QDBusConnection::sessionBus());
00352 QDBusReply<int> reply = kmail.dbusAddMessage(QString::fromLatin1(folder), tmpFile.fileName(), QString());
00353 if (!reply.isValid())
00354 kError() << "D-Bus call failed:" << reply.error().message();
00355 else if (reply.value() <= 0)
00356 kError() << "D-Bus call returned error code =" << reply.value();
00357 else
00358 return QString();
00359 err = i18nc("@info", "Error calling <application>KMail</application>");
00360 }
00361 kError() << folder << ":" << err;
00362 return err;
00363 }
00364 #endif // KMAIL_SUPPORTED
00365
00366
00367
00368
00369 QString initHeaders(const KAMail::JobData& data, bool dateId)
00370 {
00371 QString message;
00372 if (dateId)
00373 {
00374 KDateTime now = KDateTime::currentUtcDateTime();
00375 QString from = data.from;
00376 from.remove(QRegExp("^.*<")).remove(QRegExp(">.*$"));
00377 message = QLatin1String("Date: ");
00378 message += now.toTimeSpec(Preferences::timeZone()).toString(KDateTime::RFCDateDay);
00379 message += QString::fromLatin1("\nMessage-Id: <%1.%2.%3>\n").arg(now.toTime_t()).arg(now.time().msec()).arg(from);
00380 }
00381 message += QLatin1String("From: ") + data.from;
00382 message += QLatin1String("\nTo: ") + data.event.emailAddresses(", ");
00383 if (!data.bcc.isEmpty())
00384 message += QLatin1String("\nBcc: ") + data.bcc;
00385 message += QLatin1String("\nSubject: ") + data.event.emailSubject();
00386 message += QString::fromLatin1("\nX-Mailer: %1/" KALARM_VERSION).arg(KGlobal::mainComponent().aboutData()->programName());
00387 return message;
00388 }
00389
00390
00391
00392
00393
00394
00395 QString KAMail::appendBodyAttachments(QString& message, const KAEvent& event)
00396 {
00397 static const char* textMimeTypes[] = {
00398 "application/x-sh", "application/x-csh", "application/x-shellscript",
00399 "application/x-nawk", "application/x-gawk", "application/x-awk",
00400 "application/x-perl", "application/x-desktop",
00401 0
00402 };
00403 QStringList attachments = event.emailAttachments();
00404 if (!attachments.count())
00405 {
00406
00407 message += "\n\n";
00408 message += event.message();
00409 }
00410 else
00411 {
00412
00413
00414 time_t timenow;
00415 time(&timenow);
00416 QString boundary;
00417 boundary.sprintf("------------_%lu_-%lx=", 2*timenow, timenow);
00418 message += QLatin1String("\nMIME-Version: 1.0");
00419 message += QString::fromLatin1("\nContent-Type: multipart/mixed;\n boundary=\"%1\"\n").arg(boundary);
00420
00421 if (!event.message().isEmpty())
00422 {
00423
00424 message += QString::fromLatin1("\n--%1\nContent-Type: text/plain\nContent-Transfer-Encoding: 8bit\n\n").arg(boundary);
00425 message += event.message();
00426 }
00427
00428
00429 for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at)
00430 {
00431 QString attachment = (*at).toLocal8Bit();
00432 KUrl url(attachment);
00433 QString attachError = i18nc("@info", "Error attaching file: <filename>%1</filename>", attachment);
00434 url.cleanPath();
00435 KIO::UDSEntry uds;
00436 if (!KIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow())) {
00437 kError() << "Not found:" << attachment;
00438 return i18nc("@info", "Attachment not found: <filename>%1</filename>", attachment);
00439 }
00440 KFileItem fi(uds, url);
00441 if (fi.isDir() || !fi.isReadable()) {
00442 kError() << "Not file/not readable:" << attachment;
00443 return attachError;
00444 }
00445
00446
00447 QString mimeType = fi.mimetype();
00448 bool text = mimeType.startsWith("text/");
00449 if (!text)
00450 {
00451 for (int i = 0; !text && textMimeTypes[i]; ++i)
00452 text = (mimeType == textMimeTypes[i]);
00453 }
00454
00455 message += QString::fromLatin1("\n--%1").arg(boundary);
00456 message += QString::fromLatin1("\nContent-Type: %2; name=\"%3\"").arg(mimeType).arg(fi.text());
00457 message += QString::fromLatin1("\nContent-Transfer-Encoding: %1").arg(QLatin1String(text ? "8bit" : "BASE64"));
00458 message += QString::fromLatin1("\nContent-Disposition: attachment; filename=\"%4\"\n\n").arg(fi.text());
00459
00460
00461 QString tmpFile;
00462 if (!KIO::NetAccess::download(url, tmpFile, MainWindow::mainMainWindow())) {
00463 kError() << "Load failure:" << attachment;
00464 return attachError;
00465 }
00466 QFile file(tmpFile);
00467 if (!file.open(QIODevice::ReadOnly)) {
00468 kDebug() << "tmp load error:" << attachment;
00469 return attachError;
00470 }
00471 qint64 size = file.size();
00472 QByteArray contents = file.readAll();
00473 file.close();
00474 bool atterror = false;
00475 if (contents.size() < size) {
00476 kDebug() << "Read error:" << attachment;
00477 atterror = true;
00478 }
00479 else if (text)
00480 {
00481
00482 message += QString::fromLatin1(contents);
00483 }
00484 else
00485 {
00486
00487 message += QString::fromLatin1(contents.toBase64());
00488 }
00489 if (atterror)
00490 return attachError;
00491 }
00492 message += QString::fromLatin1("\n--%1--\n.\n").arg(boundary);
00493 }
00494 return QString();
00495 }
00496
00497
00498
00499
00500
00501 void KAMail::notifyQueued(const KAEvent& event)
00502 {
00503 KMime::Types::Address addr;
00504 QString localhost = QLatin1String("localhost");
00505 QString hostname = KNetwork::KResolver::localHostName();
00506 const EmailAddressList& addresses = event.emailAddresses();
00507 for (int i = 0, end = addresses.count(); i < end; ++i)
00508 {
00509 QByteArray email = addresses[i].email().toLocal8Bit();
00510 const char* em = email;
00511 if (!email.isEmpty()
00512 && HeaderParsing::parseAddress(em, em + email.length(), addr))
00513 {
00514 QString domain = addr.mailboxList.first().addrSpec().domain;
00515 if (!domain.isEmpty() && domain != localhost && domain != hostname)
00516 {
00517 KMessageBox::information(0, i18nc("@info", "An email has been queued to be sent"), QString(), Preferences::EMAIL_QUEUED_NOTIFY);
00518 return;
00519 }
00520 }
00521 }
00522 }
00523
00524
00525
00526
00527 bool KAMail::identitiesExist()
00528 {
00529 identityManager();
00530 return mIdentityManager->begin() != mIdentityManager->end();
00531 }
00532
00533
00534
00535
00536 uint KAMail::identityUoid(const QString& identityUoidOrName)
00537 {
00538 bool ok;
00539 uint id = identityUoidOrName.toUInt(&ok);
00540 if (!ok || identityManager()->identityForUoid(id).isNull())
00541 {
00542 identityManager();
00543 for (KPIMIdentities::IdentityManager::ConstIterator it = mIdentityManager->begin();
00544 it != mIdentityManager->end(); ++it)
00545 {
00546 if ((*it).identityName() == identityUoidOrName)
00547 {
00548 id = (*it).uoid();
00549 break;
00550 }
00551 }
00552 }
00553 return id;
00554 }
00555
00556
00557
00558
00559 QString KAMail::controlCentreAddress()
00560 {
00561 KEMailSettings e;
00562 return e.getSetting(KEMailSettings::EmailAddress);
00563 }
00564
00565
00566
00567
00568
00569
00570 QString KAMail::convertAddresses(const QString& items, EmailAddressList& list)
00571 {
00572 list.clear();
00573 QByteArray addrs = items.toLocal8Bit();
00574 const char* ad = static_cast<const char*>(addrs);
00575
00576
00577 QList<KMime::Types::Address> maybeAddressList;
00578 if (!HeaderParsing::parseAddressList(ad, ad + addrs.length(), maybeAddressList))
00579 return QString::fromLocal8Bit(ad);
00580
00581
00582 for (int i = 0, end = maybeAddressList.count(); i < end; ++i)
00583 {
00584 QString bad = convertAddress(maybeAddressList[i], list);
00585 if (!bad.isEmpty())
00586 return bad;
00587 }
00588 return QString();
00589 }
00590
00591 #if 0
00592
00593
00594
00595
00596
00597 QString KAMail::convertAddress(const QString& item, EmailAddressList& list)
00598 {
00599 QByteArray addr = item.toLocal8Bit();
00600 const char* ad = static_cast<const char*>(addr);
00601 KMime::Types::Address maybeAddress;
00602 if (!HeaderParsing::parseAddress(ad, ad + addr.length(), maybeAddress))
00603 return item;
00604 return convertAddress(maybeAddress, list);
00605 }
00606 #endif
00607
00608
00609
00610
00611
00612 QString KAMail::convertAddress(KMime::Types::Address addr, EmailAddressList& list)
00613 {
00614 if (!addr.displayName.isEmpty())
00615 {
00616 kDebug() << "Mailbox groups not allowed! Name:" << addr.displayName;
00617 return addr.displayName;
00618 }
00619 const QList<KMime::Types::Mailbox>& mblist = addr.mailboxList;
00620 for (int i = 0, end = mblist.count(); i < end; ++i)
00621 {
00622 QString addrPart = mblist[i].addrSpec().localPart;
00623 if (!mblist[i].addrSpec().domain.isEmpty())
00624 {
00625 addrPart += QLatin1Char('@');
00626 addrPart += mblist[i].addrSpec().domain;
00627 }
00628 list += KCal::Person(mblist[i].name(), addrPart);
00629 }
00630 return QString();
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 int KAMail::checkAddress(QString& address)
00664 {
00665 address = address.trimmed();
00666
00667 if (address.indexOf(QLatin1Char(',')) >= 0 || address.indexOf(QLatin1Char(';')) >= 0)
00668 return -1;
00669 int n = address.length();
00670 if (!n)
00671 return 0;
00672 int start = 0;
00673 int end = n - 1;
00674 if (address[end] == QLatin1Char('>'))
00675 {
00676
00677 if ((start = address.indexOf(QLatin1Char('<'))) < 0)
00678 return -1;
00679 ++start;
00680 --end;
00681 }
00682 int i = address.indexOf(QLatin1Char('@'), start);
00683 if (i >= 0)
00684 {
00685 if (i == start || i == end)
00686
00687 return -1;
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 return 1;
00705 }
00706
00707
00708
00709
00710
00711
00712 QString KAMail::convertAttachments(const QString& items, QStringList& list)
00713 {
00714 KUrl url;
00715 list.clear();
00716 int length = items.length();
00717 for (int next = 0; next < length; )
00718 {
00719
00720 int i = items.indexOf(QLatin1Char(','), next);
00721 if (i < 0)
00722 i = items.length();
00723 int sc = items.indexOf(QLatin1Char(';'), next);
00724 if (sc < 0)
00725 sc = items.length();
00726 if (sc < i)
00727 i = sc;
00728 QString item = items.mid(next, i - next).trimmed();
00729 switch (checkAttachment(item))
00730 {
00731 case 1: list += item; break;
00732 case 0: break;
00733 case -1:
00734 default: return item;
00735 }
00736 next = i + 1;
00737 }
00738 return QString();
00739 }
00740
00741 #if 0
00742
00743
00744
00745
00746
00747 QString KAMail::convertAttachments(const QString& items, KUrl::List& list)
00748 {
00749 KUrl url;
00750 list.clear();
00751 QByteArray addrs = items.toLocal8Bit();
00752 int length = items.length();
00753 for (int next = 0; next < length; )
00754 {
00755
00756 int i = items.indexOf(QLatin1Char(','), next);
00757 if (i < 0)
00758 i = items.length();
00759 int sc = items.indexOf(QLatin1Char(';'), next);
00760 if (sc < 0)
00761 sc = items.length();
00762 if (sc < i)
00763 i = sc;
00764 QString item = items.mid(next, i - next);
00765 switch (checkAttachment(item, &url))
00766 {
00767 case 1: list += url; break;
00768 case 0: break;
00769 case -1:
00770 default: return item;
00771 }
00772 next = i + 1;
00773 }
00774 return QString();
00775 }
00776 #endif
00777
00778
00779
00780
00781
00782
00783
00784
00785 int KAMail::checkAttachment(QString& attachment, KUrl* url)
00786 {
00787 attachment = attachment.trimmed();
00788 if (attachment.isEmpty())
00789 {
00790 if (url)
00791 *url = KUrl();
00792 return 0;
00793 }
00794
00795 KUrl u(attachment);
00796 u.cleanPath();
00797 if (url)
00798 *url = u;
00799 return checkAttachment(u) ? 1 : -1;
00800 }
00801
00802
00803
00804
00805 bool KAMail::checkAttachment(const KUrl& url)
00806 {
00807 KIO::UDSEntry uds;
00808 if (!KIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow()))
00809 return false;
00810 KFileItem fi(uds, url);
00811 if (fi.isDir() || !fi.isReadable())
00812 return false;
00813 return true;
00814 }
00815
00816
00817
00818
00819 QStringList KAMail::errors(const QString& err, ErrType prefix)
00820 {
00821 QString error1;
00822 switch (prefix)
00823 {
00824 case SEND_FAIL: error1 = i18nc("@info", "Failed to send email"); break;
00825 case SEND_ERROR: error1 = i18nc("@info", "Error sending email"); break;
00826 case COPY_ERROR: error1 = i18nc("@info", "Error copying sent email to <application>KMail</application> <resource>%1</resource> folder", i18n_sent_mail()); break;
00827 }
00828 if (err.isEmpty())
00829 return QStringList(error1);
00830 QStringList errs(QString::fromLatin1("%1:").arg(error1));
00831 errs += err;
00832 return errs;
00833 }
00834
00835 #ifdef KMAIL_SUPPORTED
00836
00837
00838
00839 QString KAMail::getMailBody(quint32 serialNumber)
00840 {
00841 QList<QVariant> args;
00842 args << serialNumber << (int)0;
00843 #ifdef __GNUC__
00844 #warning Set correct DBus interface/object for kmail
00845 #endif
00846 QDBusInterface iface(KMAIL_DBUS_SERVICE, QString(), QLatin1String("KMailIface"));
00847 QDBusReply<QString> reply = iface.callWithArgumentList(QDBus::Block, QLatin1String("getDecodedBodyPart"), args);
00848 if (!reply.isValid())
00849 {
00850 kError() << "D-Bus call failed:" << reply.error().message();
00851 return QString();
00852 }
00853 return reply.value();
00854 }
00855 #endif
00856
00857
00858
00859
00860
00861
00862
00863 namespace HeaderParsing
00864 {
00865
00866 using namespace KMime;
00867 using namespace KMime::Types;
00868 using namespace KMime::HeaderParsing;
00869
00870
00871
00872
00873
00874 bool parseUserName( const char* & scursor, const char * const send,
00875 QString & result, bool isCRLF ) {
00876
00877 QString maybeLocalPart;
00878 QString tmp;
00879
00880 if ( scursor != send ) {
00881
00882 eatCFWS( scursor, send, isCRLF );
00883
00884 char ch = *scursor++;
00885 switch ( ch ) {
00886 case '.':
00887 case '@':
00888 case '"':
00889 return false;
00890
00891 default:
00892 scursor--;
00893 tmp.clear();
00894 if ( parseAtom( scursor, send, result, false ) ) {
00895 if (getpwnam(result.toLocal8Bit()))
00896 return true;
00897 }
00898 return false;
00899 }
00900 }
00901 return false;
00902 }
00903
00904
00905
00906
00907
00908
00909 bool parseAddress( const char* & scursor, const char * const send,
00910 Address & result, bool isCRLF ) {
00911
00912
00913 eatCFWS( scursor, send, isCRLF );
00914 if ( scursor == send ) return false;
00915
00916
00917 Mailbox maybeMailbox;
00918 const char * oldscursor = scursor;
00919 if ( parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) {
00920
00921 result.displayName.clear();
00922 result.mailboxList.append( maybeMailbox );
00923 return true;
00924 }
00925 scursor = oldscursor;
00926
00927
00928
00929 QString maybeUserName;
00930 if ( parseUserName( scursor, send, maybeUserName, isCRLF ) ) {
00931
00932 maybeMailbox.setName( QString() );
00933 AddrSpec addrSpec;
00934 addrSpec.localPart = maybeUserName;
00935 addrSpec.domain.clear();
00936 maybeMailbox.setAddress( addrSpec );
00937 result.displayName.clear();
00938 result.mailboxList.append( maybeMailbox );
00939 return true;
00940 }
00941 scursor = oldscursor;
00942
00943 Address maybeAddress;
00944
00945
00946 if ( !parseGroup( scursor, send, maybeAddress, isCRLF ) )
00947 {
00948 scursor = oldscursor;
00949 return false;
00950 }
00951
00952 result = maybeAddress;
00953 return true;
00954 }
00955
00956
00957
00958
00959
00960 bool parseAddressList( const char* & scursor, const char * const send,
00961 QList<Address> & result, bool isCRLF ) {
00962 while ( scursor != send ) {
00963 eatCFWS( scursor, send, isCRLF );
00964
00965 if ( scursor == send ) return true;
00966
00967 if ( *scursor == ',' || *scursor == ';' ) { scursor++; continue; }
00968
00969
00970 Address maybeAddress;
00971 if ( !parseAddress( scursor, send, maybeAddress, isCRLF ) ) return false;
00972 result.append( maybeAddress );
00973
00974 eatCFWS( scursor, send, isCRLF );
00975
00976 if ( scursor == send ) return true;
00977
00978 if ( *scursor == ',' || *scursor == ';' ) scursor++;
00979 }
00980 return true;
00981 }
00982
00983 }