kmail Library API Documentation

vacation.cpp

00001 /* -*- c++ -*- 00002 vacation.cpp 00003 00004 KMail, the KDE mail client. 00005 Copyright (c) 2002 Marc Mutz <mutz@kde.org> 00006 00007 This program is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU General Public License, 00009 version 2.0, as published by the Free Software Foundation. 00010 You should have received a copy of the GNU General Public License 00011 along with this program; if not, write to the Free Software Foundation, 00012 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US 00013 */ 00014 00015 #ifdef HAVE_CONFIG_H 00016 #include <config.h> 00017 #endif 00018 00019 #include "vacation.h" 00020 #include <limits.h> 00021 00022 #include "vacationdialog.h" 00023 #include "sievejob.h" 00024 using KMail::SieveJob; 00025 #include "kmkernel.h" 00026 #include "kmacctmgr.h" 00027 #include "kmacctimap.h" 00028 #include "kmmessage.h" 00029 #include "identitymanager.h" 00030 #include "kmidentity.h" 00031 00032 #include <kmime_header_parsing.h> 00033 using KMime::Types::AddrSpecList; 00034 00035 #include <ksieve/parser.h> 00036 #include <ksieve/scriptbuilder.h> 00037 #include <ksieve/error.h> 00038 00039 #include <klocale.h> 00040 #include <kmessagebox.h> 00041 #include <kdebug.h> 00042 00043 #include <qdatetime.h> 00044 00045 #include <cassert> 00046 00047 namespace { 00048 00049 class VacationDataExtractor : public KSieve::ScriptBuilder { 00050 enum Context { 00051 None = 0, 00052 // command itself: 00053 VacationCommand, 00054 // tagged args: 00055 Days, Addresses 00056 }; 00057 public: 00058 VacationDataExtractor() 00059 : KSieve::ScriptBuilder(), 00060 mContext( None ), mNotificationInterval( 0 ) 00061 { 00062 kdDebug() << "VacationDataExtractor instantiated" << endl; 00063 } 00064 virtual ~VacationDataExtractor() {} 00065 00066 int notificationInterval() const { return mNotificationInterval; } 00067 const QString & messageText() const { return mMessageText; } 00068 const QStringList & aliases() const { return mAliases; } 00069 00070 private: 00071 void commandStart( const QString & identifier ) { 00072 kdDebug( 5006 ) << "VacationDataExtractor::commandStart( \"" << identifier << "\" )" << endl; 00073 if ( identifier != "vacation" ) 00074 return; 00075 reset(); 00076 mContext = VacationCommand; 00077 } 00078 00079 void commandEnd() { 00080 kdDebug( 5006 ) << "VacationDataExtractor::commandEnd()" << endl; 00081 mContext = None; 00082 } 00083 00084 void testStart( const QString & ) {} 00085 void testEnd() {} 00086 void testListStart() {} 00087 void testListEnd() {} 00088 void blockStart() {} 00089 void blockEnd() {} 00090 void hashComment( const QString & ) {} 00091 void bracketComment( const QString & ) {} 00092 void lineFeed() {} 00093 void error( const KSieve::Error & e ) { 00094 kdDebug( 5006 ) << "VacationDataExtractor::error() ### " 00095 << e.asString() << " @ " << e.line() << "," << e.column() 00096 << endl; 00097 } 00098 void finished() {} 00099 00100 void taggedArgument( const QString & tag ) { 00101 kdDebug( 5006 ) << "VacationDataExtractor::taggedArgument( \"" << tag << "\" )" << endl; 00102 if ( mContext != VacationCommand ) 00103 return; 00104 if ( tag == "days" ) 00105 mContext = Days; 00106 else if ( tag == "addresses" ) 00107 mContext = Addresses; 00108 } 00109 00110 void stringArgument( const QString & string, bool, const QString & ) { 00111 kdDebug( 5006 ) << "VacationDataExtractor::stringArgument( \"" << string << "\" )" << endl; 00112 if ( mContext == Addresses ) { 00113 mAliases.push_back( string ); 00114 mContext = VacationCommand; 00115 } else if ( mContext == VacationCommand ) { 00116 mMessageText = string; 00117 mContext = VacationCommand; 00118 } 00119 } 00120 00121 void numberArgument( unsigned long number, char ) { 00122 kdDebug( 5006 ) << "VacationDataExtractor::numberArgument( \"" << number << "\" )" << endl; 00123 if ( mContext != Days ) 00124 return; 00125 if ( number > INT_MAX ) 00126 mNotificationInterval = INT_MAX; 00127 else 00128 mNotificationInterval = number; 00129 mContext = VacationCommand; 00130 } 00131 00132 void stringListArgumentStart() {} 00133 void stringListEntry( const QString & string, bool, const QString & ) { 00134 kdDebug( 5006 ) << "VacationDataExtractor::stringListEntry( \"" << string << "\" )" << endl; 00135 if ( mContext != Addresses ) 00136 return; 00137 mAliases.push_back( string ); 00138 } 00139 void stringListArgumentEnd() { 00140 kdDebug( 5006 ) << "VacationDataExtractor::stringListArgumentEnd()" << endl; 00141 if ( mContext != Addresses ) 00142 return; 00143 mContext = VacationCommand; 00144 } 00145 00146 private: 00147 Context mContext; 00148 int mNotificationInterval; 00149 QString mMessageText; 00150 QStringList mAliases; 00151 00152 void reset() { 00153 kdDebug() << "VacationDataExtractor::reset()" << endl; 00154 mContext = None; 00155 mNotificationInterval = 0; 00156 mAliases.clear(); 00157 mMessageText = QString::null; 00158 } 00159 }; 00160 00161 } 00162 00163 namespace KMail { 00164 00165 Vacation::Vacation( QObject * parent, const char * name ) 00166 : QObject( parent, name ), mSieveJob( 0 ), mDialog( 0 ), mWasActive( false ) 00167 { 00168 mUrl = findURL(); 00169 kdDebug(5006) << "Vacation: found url \"" << mUrl.prettyURL() << "\"" << endl; 00170 if ( mUrl.isEmpty() ) // nothing to do... 00171 return; 00172 mUrl.setFileName( "kmail-vacation.siv" ); 00173 mSieveJob = SieveJob::get( mUrl ); 00174 connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)), 00175 SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) ); 00176 } 00177 00178 Vacation::~Vacation() { 00179 if ( mSieveJob ) mSieveJob->kill(); mSieveJob = 0; 00180 delete mDialog; mDialog = 0; 00181 kdDebug(5006) << "~Vacation()" << endl; 00182 } 00183 00184 static inline QString dotstuff( QString s ) { 00185 if ( s.startsWith( "." ) ) 00186 return '.' + s.replace( "\n.", "\n.." ); 00187 else 00188 return s.replace( "\n.", "\n.." ); 00189 } 00190 00191 QString Vacation::composeScript( const QString & messageText, 00192 int notificationInterval, 00193 const AddrSpecList & addrSpecs ) 00194 { 00195 QString addressesArgument; 00196 QStringList aliases; 00197 if ( !addrSpecs.empty() ) { 00198 addressesArgument += ":addresses [ "; 00199 QStringList sl; 00200 for ( AddrSpecList::const_iterator it = addrSpecs.begin() ; it != addrSpecs.end() ; ++it ) { 00201 sl.push_back( '"' + (*it).asString().replace( '\\', "\\\\" ).replace( '"', "\\\"" ) + '"' ); 00202 aliases.push_back( (*it).asString() ); 00203 } 00204 addressesArgument += sl.join( ", " ) + " ] "; 00205 } 00206 QString script = QString::fromLatin1("require \"vacation\";\n" 00207 "\n" 00208 "vacation "); 00209 script += addressesArgument; 00210 if ( notificationInterval > 0 ) 00211 script += QString::fromLatin1(":days %1 ").arg( notificationInterval ); 00212 script += QString::fromLatin1("text:\n"); 00213 script += dotstuff( messageText.isEmpty() ? defaultMessageText() : messageText ); 00214 script += QString::fromLatin1( "\n.\n;\n" ); 00215 return script; 00216 } 00217 00218 static KURL findUrlForAccount( const KMail::ImapAccountBase * a ) { 00219 assert( a ); 00220 SieveConfig sieve = a->sieveConfig(); 00221 if ( !sieve.managesieveSupported() ) 00222 return KURL(); 00223 if ( sieve.reuseConfig() ) { 00224 // assemble Sieve url from the settings of the account: 00225 KURL u; 00226 u.setProtocol( "sieve" ); 00227 u.setHost( a->host() ); 00228 u.setUser( a->login() ); 00229 u.setPass( a->passwd() ); 00230 u.setPort( sieve.port() ); 00231 return u; 00232 } else { 00233 return sieve.alternateURL(); 00234 } 00235 } 00236 00237 KURL Vacation::findURL() const { 00238 KMAcctMgr * am = kmkernel->acctMgr(); 00239 assert( am ); 00240 for ( KMAccount * a = am->first() ; a ; a = am->next() ) 00241 if ( KMail::ImapAccountBase * iab = dynamic_cast<KMail::ImapAccountBase*>( a ) ) { 00242 KURL u = findUrlForAccount( iab ); 00243 if ( !u.isEmpty() ) 00244 return u; 00245 } 00246 return KURL(); 00247 } 00248 00249 bool Vacation::parseScript( const QString & script, QString & messageText, 00250 int & notificationInterval, QStringList & aliases ) { 00251 if ( script.stripWhiteSpace().isEmpty() ) { 00252 messageText = defaultMessageText(); 00253 notificationInterval = defaultNotificationInterval(); 00254 aliases = defaultMailAliases(); 00255 return true; 00256 } 00257 00258 // The stripWhiteSpace() call below prevents parsing errors. The 00259 // slave somehow omits the last \n, which results in a lone \r at 00260 // the end, leading to a parse error. 00261 const QCString scriptUTF8 = script.stripWhiteSpace().utf8(); 00262 kdDebug() << "scriptUtf8 = \"" + scriptUTF8 + "\"" << endl; 00263 KSieve::Parser parser( scriptUTF8.begin(), 00264 scriptUTF8.begin() + scriptUTF8.length() ); 00265 VacationDataExtractor vdx; 00266 parser.setScriptBuilder( &vdx ); 00267 if ( !parser.parse() ) 00268 return false; 00269 messageText = vdx.messageText().stripWhiteSpace(); 00270 notificationInterval = vdx.notificationInterval(); 00271 aliases = vdx.aliases(); 00272 return true; 00273 } 00274 00275 QString Vacation::defaultMessageText() { 00276 return i18n("I am out of office till %1.\n" 00277 "\n" 00278 "In urgent cases, please contact Mrs. <vacation replacement>\n" 00279 "\n" 00280 "email: <email address of vacation replacement>\n" 00281 "phone: +49 711 1111 11\n" 00282 "fax.: +49 711 1111 12\n" 00283 "\n" 00284 "Yours sincerely,\n" 00285 "-- <enter your name and email address here>\n") 00286 .arg( KGlobal::locale()->formatDate( QDate::currentDate().addDays( 1 ) ) ); 00287 } 00288 00289 int Vacation::defaultNotificationInterval() { 00290 return 7; // days 00291 } 00292 00293 QStringList Vacation::defaultMailAliases() { 00294 QStringList sl; 00295 for ( IdentityManager::ConstIterator it = kmkernel->identityManager()->begin() ; 00296 it != kmkernel->identityManager()->end() ; ++it ) 00297 if ( !(*it).emailAddr().isEmpty() ) 00298 sl.push_back( (*it).emailAddr() ); 00299 return sl; 00300 } 00301 00302 00303 void Vacation::slotGetResult( SieveJob * job, bool success, 00304 const QString & script, bool active ) { 00305 kdDebug(5006) << "Vacation::slotGetResult( ??, " << success 00306 << ", ?, " << active << " )" << endl 00307 << "script:" << endl 00308 << script << endl; 00309 mSieveJob = 0; // job deletes itself after returning from this slot! 00310 00311 if ( mUrl.protocol() == "sieve" && !job->sieveCapabilities().isEmpty() && 00312 !job->sieveCapabilities().contains("vacation") ) { 00313 KMessageBox::sorry( 0, i18n("Your server didn't list \"vacation\" in " 00314 "it's list of supported Sieve extensions.\n" 00315 "Without it, KMail cannot install out of " 00316 "office replies for you.\n" 00317 "Please contact you system administrator.") ); 00318 emit result( false ); 00319 return; 00320 } 00321 00322 if ( !mDialog ) 00323 mDialog = new VacationDialog( i18n("Configure \"Out of Office\" Replies"), 0, 0, false ); 00324 00325 QString messageText = defaultMessageText(); 00326 int notificationInterval = defaultNotificationInterval(); 00327 QStringList aliases = defaultMailAliases(); 00328 if ( !success ) active = false; // default to inactive 00329 00330 if ( !success || !parseScript( script, messageText, notificationInterval, aliases ) ) 00331 KMessageBox::information( 0, i18n("Someone (probably you) changed the " 00332 "vacation script on the server.\n" 00333 "KMail is no longer able to determine " 00334 "the parameters for the autoreplies.\n" 00335 "Default values will be used." ) ); 00336 00337 mWasActive = active; 00338 mDialog->setActivateVacation( active ); 00339 mDialog->setMessageText( messageText ); 00340 mDialog->setNotificationInterval( notificationInterval ); 00341 mDialog->setMailAliases( aliases.join(", ") ); 00342 00343 connect( mDialog, SIGNAL(okClicked()), SLOT(slotDialogOk()) ); 00344 connect( mDialog, SIGNAL(cancelClicked()), SLOT(slotDialogCancel()) ); 00345 connect( mDialog, SIGNAL(defaultClicked()), SLOT(slotDialogDefaults()) ); 00346 00347 mDialog->show(); 00348 } 00349 00350 void Vacation::slotDialogDefaults() { 00351 if ( !mDialog ) 00352 return; 00353 mDialog->setActivateVacation( true ); 00354 mDialog->setMessageText( defaultMessageText() ); 00355 mDialog->setNotificationInterval( defaultNotificationInterval() ); 00356 mDialog->setMailAliases( defaultMailAliases().join(", ") ); 00357 } 00358 00359 void Vacation::slotDialogOk() { 00360 kdDebug(5006) << "Vacation::slotDialogOk()" << endl; 00361 // compose a new script: 00362 const QString script = composeScript( mDialog->messageText(), 00363 mDialog->notificationInterval(), 00364 mDialog->mailAliases() ); 00365 const bool active = mDialog->activateVacation(); 00366 00367 kdDebug(5006) << "script:" << endl << script << endl; 00368 00369 // and commit the dialog's settings to the server: 00370 mSieveJob = SieveJob::put( mUrl, script, active, mWasActive ); 00371 connect( mSieveJob, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)), 00372 SLOT(slotPutResult(KMail::SieveJob*,bool,const QString&,bool)) ); 00373 00374 // destroy the dialog: 00375 mDialog->delayedDestruct(); 00376 mDialog = 0; 00377 } 00378 00379 void Vacation::slotDialogCancel() { 00380 kdDebug(5006) << "Vacation::slotDialogCancel()" << endl; 00381 mDialog->delayedDestruct(); 00382 mDialog = 0; 00383 emit result( false ); 00384 } 00385 00386 void Vacation::slotPutResult( SieveJob *, bool success, const QString &, bool ) { 00387 if ( success ) 00388 KMessageBox::information( 0, i18n("Out of Office reply installed successfully.") ); 00389 kdDebug(5006) << "Vacation::slotPutResult( ???, " << success << ", ?, ? )" 00390 << endl; 00391 mSieveJob = 0; // job deletes itself after returning from this slot! 00392 emit result( success ); 00393 } 00394 00395 00396 } // namespace KMail 00397 00398 #include "vacation.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:58:04 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003