28 #include "imapaccountbase.h"
29 using KMail::SieveConfig;
31 #include "accountmanager.h"
34 #include "broadcaststatus.h"
35 using KPIM::BroadcastStatus;
36 #include "kmmainwin.h"
37 #include "kmfolderimap.h"
38 #include "kmmainwidget.h"
39 #include "kmmainwin.h"
40 #include "kmmsgpart.h"
42 #include "kmfoldercachedimap.h"
43 #include "bodyvisitor.h"
44 using KMail::BodyVisitor;
47 #include "protocols.h"
48 #include "progressmanager.h"
49 using KPIM::ProgressManager;
50 #include "kmfoldermgr.h"
53 #include <tdeapplication.h>
55 #include <tdeconfig.h>
56 #include <tdelocale.h>
57 #include <tdemessagebox.h>
58 using TDEIO::MetaData;
59 #include <tdeio/passdlg.h>
60 using TDEIO::PasswordDialog;
61 #include <tdeio/scheduler.h>
62 #include <tdeio/slave.h>
63 #include <mimelib/bodypart.h>
64 #include <mimelib/body.h>
65 #include <mimelib/headers.h>
66 #include <mimelib/message.h>
70 #include <tqstylesheet.h>
74 static const unsigned short int imapDefaultPort = 143;
82 ImapAccountBase::ImapAccountBase(
AccountManager * parent,
const TQString & name, uint
id )
83 : NetworkAccount( parent, name, id ),
84 mIdleTimer( 0,
"mIdleTimer" ),
85 mNoopTimer( 0,
"mNoopTimer" ),
88 mCountLastUnread( 0 ),
90 mHiddenFolders( false ),
91 mOnlySubscribedFolders( false ),
92 mOnlyLocallySubscribedFolders( false ),
93 mLoadOnDemand( true ),
94 mListOnlyOpenFolders( false ),
95 mProgressEnabled( false ),
96 mErrorDialogIsActive( false ),
97 mPasswordDialogIsActive( false ),
99 mAnnotationSupport( true ),
100 mQuotaSupport( true ),
101 mSlaveConnected( false ),
102 mSlaveConnectionError( false ),
103 mCheckingSingleFolder( false ),
104 mListDirProgressItem( 0 )
106 mPort = imapDefaultPort;
107 mBodyPartList.setAutoDelete(
true);
108 TDEIO::Scheduler::connect(TQ_SIGNAL(slaveError(TDEIO::Slave *,
int,
const TQString &)),
109 this, TQ_SLOT(slotSchedulerSlaveError(TDEIO::Slave *,
int,
const TQString &)));
110 TDEIO::Scheduler::connect(TQ_SIGNAL(slaveConnected(TDEIO::Slave *)),
111 this, TQ_SLOT(slotSchedulerSlaveConnected(TDEIO::Slave *)));
112 connect(&mNoopTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotNoopTimeout()));
113 connect(&mIdleTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotIdleTimeout()));
116 ImapAccountBase::~ImapAccountBase() {
117 kdWarning( mSlave, 5006 )
118 <<
"slave should have been destroyed by subclass!" << endl;
121 void ImapAccountBase::init() {
123 mHiddenFolders =
false;
124 mOnlySubscribedFolders =
false;
125 mOnlyLocallySubscribedFolders =
false;
126 mLoadOnDemand =
true;
127 mListOnlyOpenFolders =
false;
128 mProgressEnabled =
false;
131 void ImapAccountBase::pseudoAssign(
const KMAccount * a ) {
132 NetworkAccount::pseudoAssign( a );
134 const ImapAccountBase * i =
dynamic_cast<const ImapAccountBase*
>( a );
137 setAutoExpunge( i->autoExpunge() );
138 setHiddenFolders( i->hiddenFolders() );
139 setOnlySubscribedFolders( i->onlySubscribedFolders() );
140 setOnlyLocallySubscribedFolders( i->onlyLocallySubscribedFolders() );
141 setLoadOnDemand( i->loadOnDemand() );
142 setListOnlyOpenFolders( i->listOnlyOpenFolders() );
143 setNamespaces( i->namespaces() );
144 setNamespaceToDelimiter( i->namespaceToDelimiter() );
145 localBlacklistFromStringList( i->locallyBlacklistedFolders() );
148 unsigned short int ImapAccountBase::defaultPort()
const {
149 return imapDefaultPort;
152 TQString ImapAccountBase::protocol()
const {
153 return useSSL() ? IMAP_SSL_PROTOCOL : IMAP_PROTOCOL;
162 void ImapAccountBase::setAutoExpunge(
bool expunge ) {
163 mAutoExpunge = expunge;
166 void ImapAccountBase::setHiddenFolders(
bool show ) {
167 mHiddenFolders = show;
170 void ImapAccountBase::setOnlySubscribedFolders(
bool show ) {
171 mOnlySubscribedFolders = show;
174 void ImapAccountBase::setOnlyLocallySubscribedFolders(
bool show ) {
175 mOnlyLocallySubscribedFolders = show;
178 void ImapAccountBase::setLoadOnDemand(
bool load ) {
179 mLoadOnDemand = load;
182 void ImapAccountBase::setListOnlyOpenFolders(
bool only ) {
183 mListOnlyOpenFolders = only;
192 void ImapAccountBase::readConfig( TDEConfig & config ) {
193 NetworkAccount::readConfig( config );
195 setAutoExpunge( config.readBoolEntry(
"auto-expunge",
false ) );
196 setHiddenFolders( config.readBoolEntry(
"hidden-folders",
false ) );
197 setOnlySubscribedFolders( config.readBoolEntry(
"subscribed-folders",
false ) );
198 setOnlyLocallySubscribedFolders( config.readBoolEntry(
"locally-subscribed-folders",
false ) );
199 setLoadOnDemand( config.readBoolEntry(
"loadondemand",
false ) );
200 setListOnlyOpenFolders( config.readBoolEntry(
"listOnlyOpenFolders",
false ) );
201 mCapabilities = config.readListEntry(
"capabilities", TQStringList() );
204 TQStringList list = config.readListEntry( TQString::number( PersonalNS ) );
205 if ( !list.isEmpty() )
206 map[PersonalNS] = list.gres(
"\"",
"" );
207 list = config.readListEntry( TQString::number( OtherUsersNS ) );
208 if ( !list.isEmpty() )
209 map[OtherUsersNS] = list.gres(
"\"",
"" );
210 list = config.readListEntry( TQString::number( SharedNS ) );
211 if ( !list.isEmpty() )
212 map[SharedNS] = list.gres(
"\"",
"" );
213 setNamespaces( map );
215 namespaceDelim entries = config.entryMap( config.group() );
216 namespaceDelim namespaceToDelimiter;
217 for ( namespaceDelim::ConstIterator it = entries.begin();
218 it != entries.end(); ++it ) {
219 if ( it.key().startsWith(
"Namespace:" ) ) {
220 TQString key = it.key().right( it.key().length() - 10 );
221 namespaceToDelimiter[key] = it.data();
224 setNamespaceToDelimiter( namespaceToDelimiter );
225 mOldPrefix = config.readEntry(
"prefix" );
226 if ( !mOldPrefix.isEmpty() ) {
229 localBlacklistFromStringList( config.readListEntry(
"locallyUnsubscribedFolders" ) );
232 void ImapAccountBase::writeConfig( TDEConfig & config ) {
233 NetworkAccount::writeConfig( config );
235 config.writeEntry(
"auto-expunge", autoExpunge() );
236 config.writeEntry(
"hidden-folders", hiddenFolders() );
237 config.writeEntry(
"subscribed-folders", onlySubscribedFolders() );
238 config.writeEntry(
"locally-subscribed-folders", onlyLocallySubscribedFolders() );
239 config.writeEntry(
"loadondemand", loadOnDemand() );
240 config.writeEntry(
"listOnlyOpenFolders", listOnlyOpenFolders() );
241 config.writeEntry(
"capabilities", mCapabilities );
243 for ( nsMap::Iterator it = mNamespaces.begin(); it != mNamespaces.end(); ++it ) {
244 if ( !it.data().isEmpty() ) {
245 data =
"\"" + it.data().join(
"\",\"") +
"\"";
246 config.writeEntry( TQString::number( it.key() ), data );
250 for ( namespaceDelim::ConstIterator it = mNamespaceToDelimiter.begin();
251 it != mNamespaceToDelimiter.end(); ++it ) {
252 key =
"Namespace:" + it.key();
253 config.writeEntry( key, it.data() );
255 config.writeEntry(
"locallyUnsubscribedFolders", locallyBlacklistedFolders() );
264 MetaData ImapAccountBase::slaveConfig()
const {
265 MetaData m = NetworkAccount::slaveConfig();
267 m.insert(
"auth", auth() );
269 m.insert(
"expunge",
"auto" );
274 ImapAccountBase::ConnectionState ImapAccountBase::makeConnection()
276 if ( mSlave && mSlaveConnected ) {
279 if ( mPasswordDialogIsActive )
return Connecting;
281 if( mAskAgain || ( ( passwd().isEmpty() || login().isEmpty() ) &&
282 auth() !=
"GSSAPI" ) ) {
285 TQString log = login();
286 TQString pass = passwd();
291 TDEConfigGroup passwords( TDEGlobal::config(),
"Passwords" );
292 passwords.writeEntry(
"Keep", storePasswd() );
293 TQString msg = i18n(
"You need to supply a username and a password to "
294 "access this mailbox.");
295 mPasswordDialogIsActive =
true;
297 PasswordDialog dlg( msg, log,
true ,
true,
KMKernel::self()->mainWin() );
298 dlg.setPlainCaption( i18n(
"Authorization Dialog") );
299 dlg.addCommentLine( i18n(
"Account:"), name() );
300 int ret = dlg.exec();
301 if (ret != TQDialog::Accepted ) {
302 mPasswordDialogIsActive =
false;
304 emit connectionResult( TDEIO::ERR_USER_CANCELED, TQString() );
307 mPasswordDialogIsActive =
false;
310 setPasswd( dlg.password(), dlg.keepPassword() );
311 setLogin( dlg.username() );
315 if ( mSlave && !mSlaveConnected )
return Connecting;
317 mSlaveConnected =
false;
318 mSlave = TDEIO::Scheduler::getConnectedSlave( getUrl(), slaveConfig() );
320 KMessageBox::error(0, i18n(
"Could not start process for %1.")
321 .arg( getUrl().protocol() ) );
324 if ( mSlave->isConnected() ) {
325 slotSchedulerSlaveConnected( mSlave );
332 bool ImapAccountBase::handleJobError( TDEIO::Job *job,
const TQString& context,
bool abortSync )
334 JobIterator it = findJob( job );
335 if ( it != jobsEnd() && (*it).progressItem )
337 (*it).progressItem->setComplete();
338 (*it).progressItem = 0;
340 return handleError( job->error(), job->errorText(), job, context, abortSync );
344 void ImapAccountBase::postProcessNewMail(
bool showStatusMsg ) {
345 setCheckingMail(
false);
347 if ( mCountUnread > 0 && mCountUnread > mCountLastUnread ) {
348 newMails = mCountUnread - mCountLastUnread;
349 mCountLastUnread = mCountUnread;
351 checkDone(
true, CheckOK );
354 checkDone(
false, CheckOK );
357 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
362 void ImapAccountBase::changeSubscription(
bool subscribe,
const TQString& imapPath,
bool quiet )
366 url.setPath(imapPath);
368 TQByteArray packedArgs;
369 TQDataStream stream( packedArgs, IO_WriteOnly);
372 stream << (int)
'u' << url;
374 stream << (int)
'U' << url;
377 if ( makeConnection() != Connected )
379 TDEIO::SimpleJob *job = TDEIO::special(url, packedArgs,
false);
380 TDEIO::Scheduler::assignJobToSlave(mSlave, job);
381 jobData jd( url.url(), NULL );
383 if (subscribe) jd.onlySubscribed =
true;
384 else jd.onlySubscribed =
false;
388 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
389 TQ_SLOT(slotSubscriptionResult(TDEIO::Job *)));
393 void ImapAccountBase::slotSubscriptionResult( TDEIO::Job * job )
396 JobIterator it = findJob( job );
397 if ( it == jobsEnd() )
return;
398 bool onlySubscribed = (*it).onlySubscribed;
399 TQString path =
static_cast<TDEIO::SimpleJob*
>(job)->url().path();
403 handleJobError( job, i18n(
"Error while trying to subscribe to %1:" ).arg( path ) +
'\n' );
404 emit subscriptionChangeFailed( job->errorString() );
409 emit subscriptionChanged( path, onlySubscribed );
410 if (mSlave) removeJob(job);
416 void ImapAccountBase::getUserRights(
KMFolder* parent,
const TQString& imapPath )
422 if ( imapPath ==
"/INBOX/" ) {
423 if ( parent->
folderType() == KMFolderTypeImap )
424 static_cast<KMFolderImap*
>( parent->storage() )->setUserRights( ACLJobs::All, ACLJobs::Ok );
425 else if ( parent->
folderType() == KMFolderTypeCachedImap )
426 static_cast<KMFolderCachedImap*
>( parent->storage() )->setUserRights( ACLJobs::All, ACLJobs::Ok );
427 emit receivedUserRights( parent );
432 url.setPath(imapPath);
434 ACLJobs::GetUserRightsJob* job = ACLJobs::getUserRights( mSlave, url );
436 jobData jd( url.url(), parent );
437 jd.cancellable =
true;
440 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
441 TQ_SLOT(slotGetUserRightsResult(TDEIO::Job *)));
444 void ImapAccountBase::slotGetUserRightsResult( TDEIO::Job* _job )
446 ACLJobs::GetUserRightsJob* job =
static_cast<ACLJobs::GetUserRightsJob *
>( _job );
447 JobIterator it = findJob( job );
448 if ( it == jobsEnd() )
return;
451 if ( job->error() ) {
452 if ( job->error() == TDEIO::ERR_UNSUPPORTED_ACTION )
455 kdWarning(5006) <<
"slotGetUserRightsResult: " << job->errorString() << endl;
462 if ( folder->
folderType() == KMFolderTypeImap )
463 static_cast<KMFolderImap*
>( folder->storage() )->setUserRights( job->permissions(),
465 else if ( folder->
folderType() == KMFolderTypeCachedImap )
466 static_cast<KMFolderCachedImap*
>( folder->storage() )->setUserRights( job->permissions(),
469 if (mSlave) removeJob(job);
470 emit receivedUserRights( folder );
474 void ImapAccountBase::getACL(
KMFolder* parent,
const TQString& imapPath )
477 url.setPath(imapPath);
479 ACLJobs::GetACLJob* job = ACLJobs::getACL( mSlave, url );
480 jobData jd( url.url(), parent );
481 jd.cancellable =
true;
484 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
485 TQ_SLOT(slotGetACLResult(TDEIO::Job *)));
488 void ImapAccountBase::slotGetACLResult( TDEIO::Job* _job )
490 ACLJobs::GetACLJob* job =
static_cast<ACLJobs::GetACLJob *
>( _job );
491 JobIterator it = findJob( job );
492 if ( it == jobsEnd() )
return;
495 emit receivedACL( folder, job, job->entries() );
496 if (mSlave) removeJob(job);
501 void ImapAccountBase::getStorageQuotaInfo(
KMFolder* parent,
const TQString& imapPath )
503 if ( !mSlave )
return;
505 url.setPath(imapPath);
507 QuotaJobs::GetStorageQuotaJob* job = QuotaJobs::getStorageQuota( mSlave, url );
508 jobData jd( url.url(), parent );
509 jd.cancellable =
true;
512 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
513 TQ_SLOT(slotGetStorageQuotaInfoResult(TDEIO::Job *)));
516 void ImapAccountBase::slotGetStorageQuotaInfoResult( TDEIO::Job* _job )
518 QuotaJobs::GetStorageQuotaJob* job =
static_cast<QuotaJobs::GetStorageQuotaJob *
>( _job );
519 JobIterator it = findJob( job );
520 if ( it == jobsEnd() )
return;
521 if ( job->error() && job->error() == TDEIO::ERR_UNSUPPORTED_ACTION )
522 setHasNoQuotaSupport();
525 emit receivedStorageQuotaInfo( folder, job, job->storageQuotaInfo() );
526 if (mSlave) removeJob(job);
529 void ImapAccountBase::slotNoopTimeout()
532 TQByteArray packedArgs;
533 TQDataStream stream( packedArgs, IO_WriteOnly );
535 stream << ( int )
'N';
537 TDEIO::SimpleJob *job = TDEIO::special( getUrl(), packedArgs,
false );
538 TDEIO::Scheduler::assignJobToSlave(mSlave, job);
539 connect( job, TQ_SIGNAL(result( TDEIO::Job * ) ),
540 this, TQ_SLOT( slotSimpleResult( TDEIO::Job * ) ) );
548 void ImapAccountBase::slotIdleTimeout()
551 TDEIO::Scheduler::disconnectSlave(mSlave);
553 mSlaveConnected =
false;
560 void ImapAccountBase::slotAbortRequested( KPIM::ProgressItem* item )
569 void ImapAccountBase::slotSchedulerSlaveError(TDEIO::Slave *aSlave,
int errorCode,
570 const TQString &errorMsg)
572 if (aSlave != mSlave)
return;
573 handleError( errorCode, errorMsg, 0, TQString(),
true );
575 if ( makeConnection() != ImapAccountBase::Error )
578 if ( !mSlaveConnected ) {
579 mSlaveConnectionError =
true;
580 resetConnectionList(
this );
583 TDEIO::Scheduler::disconnectSlave( slave() );
587 emit connectionResult( errorCode, errorMsg );
591 void ImapAccountBase::slotSchedulerSlaveConnected(TDEIO::Slave *aSlave)
593 if (aSlave != mSlave)
return;
594 mSlaveConnected =
true;
595 mNoopTimer.start( 60000 );
596 emit connectionResult( 0, TQString() );
598 if ( mNamespaces.isEmpty() || mNamespaceToDelimiter.isEmpty() ) {
599 connect(
this, TQ_SIGNAL( namespacesFetched(
const ImapAccountBase::nsDelimMap& ) ),
600 this, TQ_SLOT( slotSaveNamespaces(
const ImapAccountBase::nsDelimMap& ) ) );
605 TQByteArray packedArgs;
606 TQDataStream stream( packedArgs, IO_WriteOnly);
608 TDEIO::SimpleJob *job = TDEIO::special( getUrl(), packedArgs,
false );
609 TDEIO::Scheduler::assignJobToSlave( mSlave, job );
610 connect( job, TQ_SIGNAL(infoMessage(TDEIO::Job*,
const TQString&)),
611 TQ_SLOT(slotCapabilitiesResult(TDEIO::Job*,
const TQString&)) );
615 void ImapAccountBase::slotCapabilitiesResult( TDEIO::Job*,
const TQString& result )
617 mCapabilities = TQStringList::split(
' ', result.lower() );
618 kdDebug(5006) <<
"capabilities:" << mCapabilities << endl;
622 void ImapAccountBase::getNamespaces()
624 disconnect(
this, TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
625 this, TQ_SLOT( getNamespaces() ) );
626 if ( makeConnection() != Connected || !mSlave ) {
627 kdDebug(5006) <<
"getNamespaces - wait for connection" << endl;
628 if ( mNamespaces.isEmpty() || mNamespaceToDelimiter.isEmpty() ) {
632 connect(
this, TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
633 this, TQ_SLOT( getNamespaces() ) );
638 TQByteArray packedArgs;
639 TQDataStream stream( packedArgs, IO_WriteOnly);
642 jd.total = 1; jd.done = 0; jd.cancellable =
true;
643 jd.progressItem = ProgressManager::createProgressItem(
644 ProgressManager::getUniqueID(),
645 i18n(
"Retrieving Namespaces"),
646 TQString(),
true, useSSL() || useTLS() );
647 jd.progressItem->setTotalItems( 1 );
648 connect ( jd.progressItem,
649 TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
651 TQ_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
652 TDEIO::SimpleJob *job = TDEIO::special( getUrl(), packedArgs,
false );
653 TDEIO::Scheduler::assignJobToSlave( mSlave, job );
654 insertJob( job, jd );
655 connect( job, TQ_SIGNAL( infoMessage(TDEIO::Job*,
const TQString&) ),
656 TQ_SLOT( slotNamespaceResult(TDEIO::Job*,
const TQString&) ) );
660 void ImapAccountBase::slotNamespaceResult( TDEIO::Job* job,
const TQString& str )
662 JobIterator it = findJob( job );
663 if ( it == jobsEnd() )
return;
666 namespaceDelim nsDelim;
667 TQStringList ns = TQStringList::split(
",", str );
668 for ( TQStringList::Iterator it = ns.begin(); it != ns.end(); ++it ) {
670 TQStringList parts = TQStringList::split(
"=", *it,
true );
671 imapNamespace section = imapNamespace( parts[0].toInt() );
672 if ( map.contains( section ) ) {
673 nsDelim = map[section];
678 nsDelim[parts[1]] = parts[2];
679 map[section] = nsDelim;
683 kdDebug(5006) <<
"namespaces fetched" << endl;
684 emit namespacesFetched( map );
688 void ImapAccountBase::slotSaveNamespaces(
const ImapAccountBase::nsDelimMap& map )
690 kdDebug(5006) <<
"slotSaveNamespaces " << name() << endl;
693 mNamespaceToDelimiter.clear();
694 for ( uint i = 0; i < 3; ++i ) {
695 imapNamespace section = imapNamespace( i );
696 namespaceDelim ns = map[ section ];
697 namespaceDelim::ConstIterator it;
699 for ( it = ns.begin(); it != ns.end(); ++it ) {
701 mNamespaceToDelimiter[ it.key() ] = it.data();
703 if ( !list.isEmpty() ) {
704 mNamespaces[section] = list;
708 if ( !mOldPrefix.isEmpty() ) {
711 emit namespacesFetched();
715 void ImapAccountBase::migratePrefix()
717 if ( !mOldPrefix.isEmpty() && mOldPrefix !=
"/" ) {
719 if ( mOldPrefix.startsWith(
"/") ) {
720 mOldPrefix = mOldPrefix.right( mOldPrefix.length()-1 );
722 if ( mOldPrefix.endsWith(
"/") ) {
723 mOldPrefix = mOldPrefix.left( mOldPrefix.length()-1 );
725 TQStringList list = mNamespaces[PersonalNS];
727 for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
728 if ( (*it).startsWith( mOldPrefix ) ) {
731 kdDebug(5006) <<
"migratePrefix - no migration needed" << endl;
736 TQString msg = i18n(
"KMail has detected a prefix entry in the "
737 "configuration of the account \"%1\" which is obsolete with the "
738 "support of IMAP namespaces.").arg( name() );
739 if ( list.contains(
"" ) ) {
743 mNamespaces[PersonalNS] = list;
744 if ( mNamespaceToDelimiter.contains(
"" ) ) {
745 TQString delim = mNamespaceToDelimiter[
""];
746 mNamespaceToDelimiter.remove(
"" );
747 mNamespaceToDelimiter[mOldPrefix] = delim;
749 kdDebug(5006) <<
"migratePrefix - replaced empty with " << mOldPrefix << endl;
750 msg += i18n(
"The configuration was automatically migrated but you should check "
751 "your account configuration.");
752 }
else if ( list.count() == 1 ) {
754 TQString old = list.first();
757 mNamespaces[PersonalNS] = list;
758 if ( mNamespaceToDelimiter.contains( old ) ) {
759 TQString delim = mNamespaceToDelimiter[old];
760 mNamespaceToDelimiter.remove( old );
761 mNamespaceToDelimiter[mOldPrefix] = delim;
763 kdDebug(5006) <<
"migratePrefix - replaced single with " << mOldPrefix << endl;
764 msg += i18n(
"The configuration was automatically migrated but you should check "
765 "your account configuration.");
767 kdDebug(5006) <<
"migratePrefix - migration failed" << endl;
768 msg += i18n(
"It was not possible to migrate your configuration automatically "
769 "so please check your account configuration.");
771 KMessageBox::information( kmkernel->getKMMainWidget(), msg );
775 kdDebug(5006) <<
"migratePrefix - no migration needed" << endl;
781 TQString ImapAccountBase::namespaceForFolder(
FolderStorage* storage )
784 if ( storage->
folderType() == KMFolderTypeImap ) {
785 path =
static_cast<KMFolderImap*
>( storage )->imapPath();
786 }
else if ( storage->
folderType() == KMFolderTypeCachedImap ) {
787 path =
static_cast<KMFolderCachedImap*
>( storage )->imapPath();
791 for ( it = mNamespaces.begin(); it != mNamespaces.end(); ++it )
793 TQStringList::Iterator strit;
794 for ( strit = it.data().begin(); strit != it.data().end(); ++strit )
796 TQString ns = *strit;
797 if ( ns.endsWith(
"/") || ns.endsWith(
".") ) {
799 ns = ns.left( ns.length()-1 );
802 if ( !ns.isEmpty() && path.find( ns ) != -1 ) {
811 TQString ImapAccountBase::delimiterForNamespace(
const TQString& prefix )
815 if ( mNamespaceToDelimiter.contains(prefix) ) {
816 return mNamespaceToDelimiter[prefix];
821 for ( namespaceDelim::ConstIterator it = mNamespaceToDelimiter.begin();
822 it != mNamespaceToDelimiter.end(); ++it ) {
825 TQString stripped = it.key().left( it.key().length() - 1 );
826 if ( !it.key().isEmpty() &&
827 ( prefix.contains( it.key() ) || prefix.contains( stripped ) ) ) {
833 if ( mNamespaceToDelimiter.contains(
"" ) ) {
834 return mNamespaceToDelimiter[
""];
842 TQString ImapAccountBase::delimiterForFolder(
FolderStorage* storage )
844 TQString prefix = namespaceForFolder( storage );
845 TQString delim = delimiterForNamespace( prefix );
850 void ImapAccountBase::slotSimpleResult(TDEIO::Job * job)
852 JobIterator it = findJob( job );
854 if (it != mapJobData.end()) {
856 if ( !(job->error() && !quiet) )
861 handleJobError(job, TQString() );
863 if ( job->error() == TDEIO::ERR_CONNECTION_BROKEN && slave() ) {
866 TDEIO::Scheduler::disconnectSlave( slave() );
869 if (job->error() == TDEIO::ERR_SLAVE_DIED)
876 bool ImapAccountBase::handlePutError( TDEIO::Job* job, jobData& jd,
KMFolder* folder )
878 Q_ASSERT( !jd.msgList.isEmpty() );
882 const TQString subject = msg->
subject().isEmpty() ? i18n(
"<unknown>" ) : TQString(
"\"%1\"").arg( msg->subject() );
883 const TQString from = msg->
from().isEmpty() ? i18n(
"<unknown>" ) : msg->from();
884 TQString myError =
"<p><b>" + i18n(
"Error while uploading message")
886 + i18n(
"Could not upload the message dated %1 from <i>%2</i> with subject <i>%3</i> to the server.").arg( msg->
dateStr(), TQStyleSheet::escape( from ), TQStyleSheet::escape( subject ) )
888 + i18n(
"The destination folder was: <b>%1</b>.").arg( TQStyleSheet::escape( folder->
prettyURL() ) )
890 + i18n(
"The server reported:") +
"</p>";
891 return handleJobError( job, myError );
894 TQString ImapAccountBase::prettifyQuotaError(
const TQString& _error, TDEIO::Job * job )
896 TQString error = _error;
897 if ( error.find(
"quota", 0,
false ) == -1 )
return error;
899 JobIterator it = findJob( job );
900 TQString quotaAsString( i18n(
"No detailed quota information available.") );
901 bool readOnly =
false;
902 if (it != mapJobData.end()) {
903 const KMFolder *
const folder = (*it).parent;
904 if( !folder )
return _error;
905 const KMFolderCachedImap *
const imap =
dynamic_cast<const KMFolderCachedImap*
>( folder->storage() );
907 quotaAsString = imap->quotaInfo().toString();
911 error = i18n(
"The folder is too close to its quota limit. (%1)").arg( quotaAsString );
913 error += i18n(
"\nSince you do not have write privileges on this folder, "
914 "please ask the owner of the folder to free up some space in it.");
920 bool ImapAccountBase::handleError(
int errorCode,
const TQString &errorMsg, TDEIO::Job* job,
const TQString& context,
bool abortSync )
924 if ( job && job->error() != TDEIO::ERR_SLAVE_DEFINED )
925 errors = job->detailedErrorStrings();
927 bool jobsKilled =
true;
928 switch( errorCode ) {
929 case TDEIO::ERR_SLAVE_DIED: slaveDied(); killAllJobs(
true );
break;
930 case TDEIO::ERR_COULD_NOT_AUTHENTICATE:
933 case TDEIO::ERR_CONNECTION_BROKEN:
934 case TDEIO::ERR_COULD_NOT_CONNECT:
935 case TDEIO::ERR_SERVER_TIMEOUT:
939 case TDEIO::ERR_COULD_NOT_LOGIN:
940 case TDEIO::ERR_USER_CANCELED:
941 killAllJobs(
false );
945 killAllJobs(
false );
952 if ( !mErrorDialogIsActive && errorCode != TDEIO::ERR_USER_CANCELED ) {
953 mErrorDialogIsActive =
true;
954 TQString msg = context +
'\n' + prettifyQuotaError( TDEIO::buildErrorString( errorCode, errorMsg ), job );
955 TQString caption = i18n(
"Error");
957 if ( jobsKilled || errorCode == TDEIO::ERR_COULD_NOT_LOGIN ) {
958 if ( errorCode == TDEIO::ERR_SERVER_TIMEOUT || errorCode == TDEIO::ERR_CONNECTION_BROKEN ) {
959 msg = i18n(
"The connection to the server %1 was unexpectedly closed or timed out. It will be re-established automatically if possible.").
961 KMessageBox::information( kapp->activeWindow(), msg, caption,
"kmailConnectionBrokenErrorDialog" );
963 if ( errorCode == TDEIO::ERR_CONNECTION_BROKEN )
964 KPIM::BroadcastStatus::instance()->setStatusMsg(
965 i18n(
"The connection to account %1 was broken." ).arg( name() ) );
966 else if ( errorCode == TDEIO::ERR_SERVER_TIMEOUT )
967 KPIM::BroadcastStatus::instance()->setStatusMsg(
968 i18n(
"The connection to account %1 timed out." ).arg( name() ) );
970 if ( !errors.isEmpty() )
971 KMessageBox::detailedError( kapp->activeWindow(), msg, errors.join(
"\n").prepend(
"<qt>"), caption );
973 KMessageBox::error( kapp->activeWindow(), msg, caption );
976 if ( errors.count() >= 3 ) {
977 TQString error = prettifyQuotaError( errors[1], job );
978 msg = TQString(
"<qt>") + context + error +
'\n' + errors[2];
981 int ret = KMessageBox::warningContinueCancel( kapp->activeWindow(), msg, caption );
982 if ( ret == KMessageBox::Cancel ) {
984 killAllJobs(
false );
987 mErrorDialogIsActive =
false;
989 if ( mErrorDialogIsActive )
990 kdDebug(5006) <<
"suppressing error:" << errorMsg << endl;
992 if ( job && !jobsKilled )
998 void ImapAccountBase::cancelMailCheck()
1000 TQMap<TDEIO::Job*, jobData>::Iterator it = mapJobData.begin();
1001 while ( it != mapJobData.end() ) {
1002 kdDebug(5006) <<
"cancelMailCheck: job is cancellable: " << (*it).cancellable << endl;
1003 if ( (*it).cancellable ) {
1005 TQMap<TDEIO::Job*, jobData>::Iterator rmit = it;
1007 mapJobData.remove( rmit );
1014 for( TQPtrListIterator<FolderJob> it( mJobList ); it.current(); ++it ) {
1015 if ( it.current()->isCancellable() ) {
1016 FolderJob* job = it.current();
1017 job->setPassiveDestructor(
true );
1018 mJobList.remove( job );
1026 void ImapAccountBase::processNewMailInFolder(
KMFolder* folder, FolderListType type )
1028 if ( mFoldersQueuedForChecking.contains( folder ) )
1030 mFoldersQueuedForChecking.append( folder );
1031 mCheckingSingleFolder = ( type == Single );
1032 if ( checkingMail() )
1034 disconnect(
this, TQ_SIGNAL( finishedCheck(
bool, CheckStatus ) ),
1035 this, TQ_SLOT( slotCheckQueuedFolders() ) );
1036 connect(
this, TQ_SIGNAL( finishedCheck(
bool, CheckStatus ) ),
1037 this, TQ_SLOT( slotCheckQueuedFolders() ) );
1039 slotCheckQueuedFolders();
1044 void ImapAccountBase::slotCheckQueuedFolders()
1046 disconnect(
this, TQ_SIGNAL( finishedCheck(
bool, CheckStatus ) ),
1047 this, TQ_SLOT( slotCheckQueuedFolders() ) );
1049 TQValueList<TQGuardedPtr<KMFolder> > mSaveList = mMailCheckFolders;
1050 mMailCheckFolders = mFoldersQueuedForChecking;
1051 if ( kmkernel->acctMgr() )
1052 kmkernel->acctMgr()->singleCheckMail(
this,
true);
1053 mMailCheckFolders = mSaveList;
1054 mFoldersQueuedForChecking.clear();
1058 bool ImapAccountBase::checkingMail(
KMFolder *folder )
1060 if (checkingMail() && mFoldersQueuedForChecking.contains(folder))
1066 void ImapAccountBase::handleBodyStructure( TQDataStream & stream,
KMMessage * msg,
1067 const AttachmentStrategy *as )
1069 mBodyPartList.clear();
1074 constructParts( stream, 1, 0, 0, msg->asDwMessage() );
1075 if ( mBodyPartList.count() == 1 )
1080 kdWarning(5006) << k_funcinfo <<
" - found no attachment strategy!" << endl;
1085 BodyVisitor *visitor = BodyVisitorFactory::getVisitor( as );
1086 visitor->visit( mBodyPartList );
1087 TQPtrList<KMMessagePart> parts = visitor->partsToLoad();
1089 TQPtrListIterator<KMMessagePart> it( parts );
1090 KMMessagePart *part;
1091 int partsToLoad = 0;
1093 while ( (part = it.current()) != 0 )
1096 if ( part->loadPart() )
1104 if ( mBodyPartList.count() == 1 && partsToLoad == 0 )
1107 if ( (mBodyPartList.count() * 0.5) < partsToLoad )
1111 kdDebug(5006) <<
"Falling back to normal mode" << endl;
1112 FolderJob *job = msg->parent()->createJob(
1113 msg, FolderJob::tGetMessage, 0,
"TEXT" );
1118 while ( (part = it.current()) != 0 )
1121 kdDebug(5006) <<
"ImapAccountBase::handleBodyStructure - load " << part->partSpecifier()
1122 <<
" (" << part->originalContentTypeStr() <<
")" << endl;
1123 if ( part->loadHeaders() )
1125 kdDebug(5006) <<
"load HEADER" << endl;
1126 FolderJob *job = msg->parent()->createJob(
1127 msg, FolderJob::tGetMessage, 0, part->partSpecifier()+
".MIME" );
1130 if ( part->loadPart() )
1132 kdDebug(5006) <<
"load Part" << endl;
1133 FolderJob *job = msg->parent()->createJob(
1134 msg, FolderJob::tGetMessage, 0, part->partSpecifier() );
1141 void ImapAccountBase::constructParts( TQDataStream & stream,
int count, KMMessagePart* parentKMPart,
1142 DwBodyPart * parent,
const DwMessage * dwmsg )
1145 for (
int i = 0; i < count; i++)
1148 KMMessagePart* part =
new KMMessagePart( stream );
1149 part->setParent( parentKMPart );
1150 mBodyPartList.append( part );
1151 kdDebug(5006) <<
"ImapAccountBase::constructParts - created id " << part->partSpecifier()
1152 <<
" of type " << part->originalContentTypeStr() << endl;
1153 DwBodyPart *dwpart = mCurrentMsg->createDWBodyPart( part );
1158 parent->Body().AddBodyPart( dwpart );
1162 }
else if ( part->partSpecifier() !=
"0" &&
1163 !part->partSpecifier().endsWith(
".HEADER") )
1166 dwmsg->Body().AddBodyPart( dwpart );
1173 if ( !parentKMPart )
1174 parentKMPart = part;
1178 DwBodyPart* newparent = dwpart;
1179 const DwMessage* newmsg = dwmsg;
1180 if ( part->originalContentTypeStr() ==
"MESSAGE/RFC822" && dwpart &&
1181 dwpart->Body().Message() )
1185 newmsg = dwpart->Body().Message();
1187 KMMessagePart* newParentKMPart = part;
1188 if ( part->partSpecifier().endsWith(
".HEADER") )
1189 newParentKMPart = parentKMPart;
1191 constructParts( stream, children, newParentKMPart, newparent, newmsg );
1197 void ImapAccountBase::setImapStatus(
KMFolder* folder,
const TQString& path,
const TQCString& flags )
1200 kdDebug(5006) <<
"setImapStatus path=" << path <<
" to: " << flags << endl;
1201 KURL url = getUrl();
1204 TQByteArray packedArgs;
1205 TQDataStream stream( packedArgs, IO_WriteOnly);
1207 stream << (int)
'S' << url << flags;
1209 if ( makeConnection() != Connected )
1212 TDEIO::SimpleJob *job = TDEIO::special(url, packedArgs,
false);
1213 TDEIO::Scheduler::assignJobToSlave(slave(), job);
1214 ImapAccountBase::jobData jd( url.url(), folder );
1217 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1218 TQ_SLOT(slotSetStatusResult(TDEIO::Job *)));
1221 void ImapAccountBase::setImapSeenStatus(
KMFolder * folder,
const TQString & path,
bool seen)
1223 KURL url = getUrl();
1226 TQByteArray packedArgs;
1227 TQDataStream stream( packedArgs, IO_WriteOnly);
1229 stream << (int)
's' << url << seen;
1231 if ( makeConnection() != Connected )
1234 TDEIO::SimpleJob *job = TDEIO::special(url, packedArgs,
false);
1235 TDEIO::Scheduler::assignJobToSlave(slave(), job);
1236 ImapAccountBase::jobData jd( url.url(), folder );
1239 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1240 TQ_SLOT(slotSetStatusResult(TDEIO::Job *)));
1244 void ImapAccountBase::slotSetStatusResult(TDEIO::Job * job)
1246 ImapAccountBase::JobIterator it = findJob(job);
1247 if ( it == jobsEnd() )
return;
1248 int errorCode = job->error();
1249 KMFolder *
const parent = (*it).parent;
1250 const TQString path = (*it).path;
1251 if (errorCode && errorCode != TDEIO::ERR_CANNOT_OPEN_FOR_WRITING)
1253 bool cont = handleJobError( job, i18n(
"Error while uploading status of messages to server: " ) +
'\n' );
1254 emit imapStatusChanged( parent, path, cont );
1258 emit imapStatusChanged( parent, path,
true );
1264 void ImapAccountBase::setFolder(
KMFolder* folder,
bool addAccount)
1268 folder->setSystemLabel(name());
1269 folder->setId(
id());
1271 NetworkAccount::setFolder(folder, addAccount);
1275 void ImapAccountBase::removeJob( JobIterator& it )
1277 if( (*it).progressItem ) {
1278 (*it).progressItem->setComplete();
1279 (*it).progressItem = 0;
1281 mapJobData.remove( it );
1285 void KMail::ImapAccountBase::removeJob( TDEIO::Job* job )
1287 mapJobData.remove( job );
1291 KPIM::ProgressItem* ImapAccountBase::listDirProgressItem()
1293 if ( !mListDirProgressItem )
1295 mListDirProgressItem = ProgressManager::createProgressItem(
1297 TQStyleSheet::escape( name() ),
1298 i18n(
"retrieving folders"),
1300 useSSL() || useTLS() );
1301 connect ( mListDirProgressItem,
1302 TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
1304 TQ_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
1308 unsigned int count = folderCount();
1309 mListDirProgressItem->setTotalItems( count + (
unsigned int)(count*0.05) );
1311 return mListDirProgressItem;
1315 unsigned int ImapAccountBase::folderCount()
const
1317 if ( !rootFolder() || !rootFolder()->folder() || !rootFolder()->folder()->child() )
1319 return kmkernel->imapFolderMgr()->folderCount( rootFolder()->folder()->child() );
1323 TQString ImapAccountBase::addPathToNamespace(
const TQString& prefix )
1325 TQString myPrefix = prefix;
1326 if ( !myPrefix.startsWith(
"/" ) ) {
1327 myPrefix =
"/" + myPrefix;
1329 if ( !myPrefix.endsWith(
"/" ) ) {
1337 bool ImapAccountBase::isNamespaceFolder( TQString& name )
1339 TQStringList ns = mNamespaces[OtherUsersNS];
1340 ns += mNamespaces[SharedNS];
1341 ns += mNamespaces[PersonalNS];
1342 TQString nameWithDelimiter;
1343 for ( TQStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
1345 nameWithDelimiter = name + delimiterForNamespace( *it );
1346 if ( *it == name || *it == nameWithDelimiter )
1353 ImapAccountBase::nsDelimMap ImapAccountBase::namespacesWithDelimiter()
1356 nsMap::ConstIterator it;
1357 for ( uint i = 0; i < 3; ++i )
1359 imapNamespace section = imapNamespace( i );
1360 TQStringList namespaces = mNamespaces[section];
1361 namespaceDelim nsDelim;
1362 TQStringList::Iterator lit;
1363 for ( lit = namespaces.begin(); lit != namespaces.end(); ++lit )
1365 nsDelim[*lit] = delimiterForNamespace( *lit );
1367 map[section] = nsDelim;
1373 TQString ImapAccountBase::createImapPath(
const TQString& parent,
1374 const TQString& folderName )
1376 kdDebug(5006) <<
"createImapPath parent="<<parent<<
", folderName="<<folderName<<endl;
1377 TQString newName = parent;
1379 if ( newName.endsWith(
"/") ) {
1380 newName = newName.left( newName.length() - 1 );
1383 TQString delim = delimiterForNamespace( newName );
1385 if ( delim.isEmpty() ) {
1388 if ( !newName.isEmpty() &&
1389 !newName.endsWith( delim ) && !folderName.startsWith( delim ) ) {
1390 newName = newName + delim;
1392 newName = newName + folderName;
1394 if ( !newName.endsWith(
"/") ) {
1395 newName = newName +
"/";
1402 TQString ImapAccountBase::createImapPath(
FolderStorage* parent,
1403 const TQString& folderName )
1406 if ( parent->
folderType() == KMFolderTypeImap ) {
1407 path =
static_cast<KMFolderImap*
>( parent )->imapPath();
1408 }
else if ( parent->
folderType() == KMFolderTypeCachedImap ) {
1409 path =
static_cast<KMFolderCachedImap*
>( parent )->imapPath();
1415 return createImapPath( path, folderName );
1419 bool ImapAccountBase::locallySubscribedTo(
const TQString& imapPath )
1421 return mLocalSubscriptionBlackList.find( imapPath ) == mLocalSubscriptionBlackList.end();
1424 void ImapAccountBase::changeLocalSubscription(
const TQString& imapPath,
bool subscribe )
1428 mLocalSubscriptionBlackList.erase( imapPath );
1431 mLocalSubscriptionBlackList.insert( imapPath );
1436 TQStringList ImapAccountBase::locallyBlacklistedFolders()
const
1439 std::set<TQString>::const_iterator it = mLocalSubscriptionBlackList.begin();
1440 std::set<TQString>::const_iterator end = mLocalSubscriptionBlackList.end();
1441 for ( ; it != end ; ++it )
1446 void ImapAccountBase::localBlacklistFromStringList(
const TQStringList &list )
1448 for( TQStringList::ConstIterator it = list.constBegin( ); it != list.constEnd( ); ++it )
1449 mLocalSubscriptionBlackList.insert( *it );
1454 #include "imapaccountbase.moc"
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
virtual KMFolderType folderType() const
Returns the type of this folder.
virtual TQString prettyURL() const
URL of the node for visualization purposes.
KMFolderType folderType() const
Returns the type of this folder.
bool isReadOnly() const
Is the folder read-only?
static KMKernel * self()
normal control stuff
TQString from() const
Get or set the 'From' header field.
TQString subject() const
Get or set the 'Subject' header field.
void deleteBodyParts()
Delete all body parts.
TQString dateStr() const
Get or set the 'Date' header field.
The account manager is responsible for creating accounts of various types via the factory method crea...
@ Ok
The user rights/ACL have been fetched from the server sucessfully.
@ FetchFailed
The attempt to fetch the user rights/ACL from the server failed.