kpilot

popmail-conduit.cc

Go to the documentation of this file.
00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 Dan Pilone
00004 ** Copyright (C) 1999,2000 Michael Kropfberger
00005 **
00006 ** This file is part of the popmail conduit, a conduit for KPilot that
00007 ** synchronises the Pilot's email application with the outside world,
00008 ** which currently means:
00009 **  -- sendmail or SMTP for outgoing mail
00010 **  -- POP or mbox for incoming mail
00011 */
00012 
00013 /*
00014 ** This program is free software; you can redistribute it and/or modify
00015 ** it under the terms of the GNU General Public License as published by
00016 ** the Free Software Foundation; either version 2 of the License, or
00017 ** (at your option) any later version.
00018 **
00019 ** This program is distributed in the hope that it will be useful,
00020 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00022 ** GNU General Public License for more details.
00023 **
00024 ** You should have received a copy of the GNU General Public License
00025 ** along with this program in a file called COPYING; if not, write to
00026 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00027 ** MA 02110-1301, USA.
00028 */
00029 
00030 /*
00031 ** Bug reports and questions can be sent to kde-pim@kde.org
00032 */
00033 
00034 #include "options.h"
00035 #include "popmail-conduit.h"
00036 
00037 extern "C"
00038 {
00039 
00040 unsigned long version_conduit_popmail = Pilot::PLUGIN_API;
00041 
00042 }
00043 
00044 #include <qsocket.h>
00045 #include <qregexp.h>
00046 
00047 
00048 #include <sys/types.h>
00049 #include <sys/socket.h>
00050 #include <sys/utsname.h>
00051 #include <ctype.h>
00052 
00053 #include <unistd.h>
00054 #include <errno.h>
00055 
00056 #include <time.h>  // Needed by pilot-link include
00057 #include <pi-version.h>
00058 #if PILOT_LINK_MAJOR < 10
00059 #include <pi-config.h>
00060 #endif
00061 #include <pi-mail.h>
00062 
00063 #include <qdir.h>
00064 #include <qtextstream.h>
00065 #include <qtextcodec.h>
00066 
00067 #include <kapplication.h>
00068 #include <kmessagebox.h>
00069 #include <ksock.h>
00070 #include <kconfig.h>
00071 #include <ksimpleconfig.h>
00072 #include <dcopclient.h>
00073 #include <ktempfile.h>
00074 
00075 #include "pilotRecord.h"
00076 #include "pilotSerialDatabase.h"
00077 
00078 #include "popmailSettings.h"
00079 #include "setupDialog.h"
00080 
00081 static QString DATE_FORMAT("ddd, d MMM yyyy hh:mm:ss");
00082 
00083 PopMailConduit::PopMailConduit(KPilotLink *d,
00084     const char *n,
00085     const QStringList &l) :
00086     ConduitAction(d,n,l)
00087 {
00088     FUNCTIONSETUP;
00089     fConduitName=i18n("KMail");
00090 }
00091 
00092 PopMailConduit::~PopMailConduit()
00093 {
00094     FUNCTIONSETUP;
00095 }
00096 
00097 void PopMailConduit::doSync()
00098 {
00099     FUNCTIONSETUP;
00100 
00101     int sent_count=0;
00102     int mode=MailConduitSettings::syncOutgoing();
00103 
00104     DEBUGKPILOT << fname
00105         << ": Outgoing mail disposition "
00106         << mode << endl;
00107 
00108     if(mode)
00109     {
00110         sent_count=sendPendingMail(mode);
00111     }
00112 
00113     if (sent_count>0)
00114     {
00115         if (sent_count>0)
00116         {
00117             addSyncLogEntry(i18n("Sent one message",
00118                 "Sent %n messages",sent_count));
00119         }
00120     }
00121 }
00122 
00123 
00124 // additional changes by Michael Kropfberger
00125 int PopMailConduit::sendPendingMail(int mode)
00126 {
00127     FUNCTIONSETUP;
00128     int count=0;
00129 
00130     if (mode==PopMailWidgetConfig::SendKMail)
00131     {
00132         count=sendViaKMail();
00133     }
00134 
00135     if (count == 0)
00136     {
00137         WARNINGKPILOT << "Mail was not sent at all!" << endl;
00138         emit logError(i18n("No mail was sent."));
00139     }
00140     else if (count < 0)
00141     {
00142         WARNINGKPILOT
00143             << "Mail sending returned error " << count
00144             << endl;
00145         emit logError(i18n("No mail could be sent."));
00146     }
00147     else
00148     {
00149         DEBUGKPILOT << fname
00150             << ": Sent "
00151             << count
00152             << " messages"
00153             << endl;
00154     }
00155 
00156     return count;
00157 }
00158 
00159 
00160 QString PopMailConduit::getKMailOutbox() const
00161 {
00162     FUNCTIONSETUP;
00163 
00164     // Default to "outbox" with newer KMails.
00165     KSimpleConfig c(CSL1("kmailrc"),true);
00166     c.setGroup("General");
00167 
00168     QString outbox = c.readEntry("outboxFolder");
00169     if (outbox.isEmpty())
00170     {
00171         outbox = MailConduitSettings::outboxFolder();
00172     }
00173 
00174     if (outbox.isEmpty()) outbox=CSL1("outbox");
00175 
00176     return outbox;
00177 }
00178 
00179 /*
00180  * This function uses KMail's DCOP interface to put all the
00181  * outgoing mail into the outbox.
00182  */
00183 int PopMailConduit::sendViaKMail()
00184 {
00185     FUNCTIONSETUP;
00186     int count=0;
00187     QString kmailOutboxName = getKMailOutbox();
00188 
00189     DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
00190     if (!dcopptr)
00191     {
00192         WARNINGKPILOT << "Cannot get DCOP client."
00193             << endl;
00194         KMessageBox::error(0L,
00195             i18n("Could not connect to DCOP server for "
00196                 "the KMail connection."),
00197             i18n("Error Sending Mail"));
00198         return -1;
00199     }
00200 
00201     if (!dcopptr->isAttached())
00202     {
00203         dcopptr->attach();
00204     }
00205 
00206     while (PilotRecord *pilotRec = fDatabase->readNextRecInCategory(1))
00207     {
00208         DEBUGKPILOT << fname
00209             << ": Reading "
00210             << count + 1
00211             << "th message"
00212             << endl;
00213 
00214         if (pilotRec->isDeleted() || pilotRec->isArchived())
00215         {
00216             DEBUGKPILOT << fname
00217                 << ": Skipping record."
00218                 << endl;
00219             continue;
00220         }
00221 
00222         struct Mail theMail;
00223         KTempFile t;
00224         t.setAutoDelete(true);
00225 
00226         if (t.status())
00227         {
00228             WARNINGKPILOT << "Cannot open temp file." << endl;
00229             KMessageBox::error(0L,
00230                 i18n("Cannot open temporary file to store "
00231                     "mail from Pilot in."),
00232                 i18n("Error Sending Mail"));
00233             continue;
00234         }
00235 
00236         FILE *sendf = t.fstream();
00237 
00238         if (!sendf)
00239         {
00240             WARNINGKPILOT
00241                 << "Cannot open temporary file for writing!" << endl;
00242             KMessageBox::error(0L,
00243                 i18n("Cannot open temporary file to store "
00244                     "mail from Pilot in."),
00245                 i18n("Error Sending Mail"));
00246             continue;
00247         }
00248 
00249         unpack_Mail(&theMail,
00250             (unsigned char*)pilotRec->data(),
00251             pilotRec->size());
00252         writeMessageToFile(sendf, theMail);
00253 
00254 
00255         QByteArray data,returnValue;
00256         QCString returnType;
00257         QDataStream arg(data,IO_WriteOnly);
00258 
00259         arg << kmailOutboxName << t.name() << CSL1("N") ;
00260 
00261         if (!dcopptr->call("kmail",
00262             "KMailIface",
00263             "dcopAddMessage(QString,QString,QString)",
00264             data,
00265             returnType,
00266             returnValue,
00267             true))
00268         {
00269             WARNINGKPILOT << "DCOP call failed." << endl;
00270 
00271             KMessageBox::error(0L,
00272                 i18n("DCOP connection with KMail failed."),
00273                 i18n("Error Sending Mail"));
00274             continue;
00275         }
00276 
00277         DEBUGKPILOT << fname
00278             << ": DCOP call returned "
00279             << returnType
00280             << " of "
00281             << (const char *)returnValue
00282             << endl;
00283 
00284         // Mark it as filed...
00285         pilotRec->setCategory(3);
00286         pilotRec->setModified( false );
00287         fDatabase->writeRecord(pilotRec);
00288         delete pilotRec;
00289         // This is ok since we got the mail with unpack mail..
00290         free_Mail(&theMail);
00291 
00292         count++;
00293     }
00294 
00295     return count;
00296 }
00297 
00298 // From pilot-link-0.8.7 by Kenneth Albanowski
00299 // additional changes by Michael Kropfberger
00300 
00301 void PopMailConduit::writeMessageToFile(FILE* sendf, struct Mail& theMail)
00302 {
00303     FUNCTIONSETUP;
00304 
00305     QTextStream mailPipe(sendf, IO_WriteOnly);
00306 
00307     QString fromAddress = MailConduitSettings::emailAddress();
00308     mailPipe << "From: " << fromAddress << "\r\n";
00309     mailPipe << "To: " << theMail.to << "\r\n";
00310     if(theMail.cc)
00311         mailPipe << "Cc: " << theMail.cc << "\r\n";
00312     if(theMail.bcc)
00313         mailPipe << "Bcc: " << theMail.bcc << "\r\n";
00314     if(theMail.replyTo)
00315         mailPipe << "Reply-To: " << theMail.replyTo << "\r\n";
00316     if(theMail.subject)
00317         mailPipe << "Subject: " << theMail.subject << "\r\n";
00318     
00319     // if our struct indicates that it's dated, then use the date it
00320     // holds.  otherwise, provide current date.  either way, we need to
00321     // have a date...
00322     QDateTime date = QDateTime::currentDateTime();
00323     if (theMail.dated)
00324     {
00325         date = readTm(theMail.date);
00326     }
00327 
00328     QString dateString = date.toString(DATE_FORMAT);
00329 
00330     mailPipe << "Date: " << dateString << "\r\n";
00331 
00332     mailPipe << "X-mailer: " << "Popmail-Conduit " << KPILOT_VERSION << "\r\n";
00333     mailPipe << "\r\n";
00334 
00335 
00336     DEBUGKPILOT << fname << ": To: " << theMail.to << endl;
00337 
00338 
00339     if(theMail.body)
00340     {
00341         DEBUGKPILOT << fname << ": Sent body." << endl;
00342         mailPipe << theMail.body << "\r\n";
00343     }
00344 
00345     //insert the real signature file from disk
00346     QString signature = MailConduitSettings::signature();
00347     if(!signature.isEmpty())
00348     {
00349         DEBUGKPILOT << fname << ": Reading signature" << endl;
00350 
00351         QFile f(signature);
00352         if ( f.open(IO_ReadOnly) )
00353         {    // file opened successfully
00354             mailPipe << "-- \r\n";
00355             QTextStream t( &f );        // use a text stream
00356             while ( !t.eof() )
00357             {        // until end of file...
00358                 mailPipe << t.readLine() << "\r\n";
00359             }
00360             f.close();
00361         }
00362     }
00363     mailPipe << "\r\n";
00364 
00365     DEBUGKPILOT << fname << ": Done" << endl;
00366 }
00367 
00368 
00369 /* virtual */ void PopMailConduit::doTest()
00370 {
00371     FUNCTIONSETUP;
00372 
00373     QString outbox = getKMailOutbox();
00374 
00375     DEBUGKPILOT << fname
00376         << ": KMail's outbox is "
00377         << outbox
00378         << endl;
00379 
00380     QDateTime date = QDateTime::currentDateTime();
00381     QString dateString = date.toString(DATE_FORMAT);
00382 
00383     DEBUGKPILOT << fname << ": Date format example: [" << dateString
00384         << "]" << endl;
00385 }
00386 
00387 /* virtual */ bool PopMailConduit::exec()
00388 {
00389     FUNCTIONSETUP;
00390 
00391     if (syncMode().isTest())
00392     {
00393         doTest();
00394     }
00395     else if (syncMode() == SyncMode::eBackup)
00396     {
00397         emit logError(i18n("Cannot perform backup of mail database"));
00398     }
00399     else
00400     {
00401         fDatabase = deviceLink()->database( CSL1("MailDB") );
00402 
00403         if (!fDatabase || !fDatabase->isOpen())
00404         {
00405             emit logError(i18n("Unable to open mail database on handheld"));
00406             KPILOT_DELETE(fDatabase);
00407             return false;
00408         }
00409 
00410         doSync();
00411         fDatabase->resetSyncFlags();
00412         KPILOT_DELETE(fDatabase);
00413     }
00414     delayDone();
00415     return true;
00416 }