27 #include "popaccount.h"
29 #include "broadcaststatus.h"
30 using KPIM::BroadcastStatus;
31 #include "progressmanager.h"
32 #include "kmfoldermgr.h"
33 #include "kmfiltermgr.h"
34 #include "kmpopfiltercnfrmdlg.h"
35 #include "protocols.h"
38 #include "accountmanager.h"
41 #include <kstandarddirs.h>
42 #include <tdelocale.h>
43 #include <tdemessagebox.h>
44 #include <tdemainwindow.h>
45 #include <tdeio/scheduler.h>
46 #include <tdeio/passdlg.h>
47 #include <tdeconfig.h>
48 using TDEIO::MetaData;
50 #include <tqstylesheet.h>
52 static const unsigned short int pop3DefaultPort = 110;
56 PopAccount::PopAccount(
AccountManager* aOwner,
const TQString& aAccountName, uint
id)
57 : NetworkAccount(aOwner, aAccountName, id),
58 headerIt(headersOnServer),
59 processMsgsTimer( 0,
"processMsgsTimer" )
64 mPort = defaultPort();
66 indexOfCurrentMsg = -1;
68 processingDelay = 2*100;
71 mUidsOfSeenMsgsDict.setAutoDelete(
false );
72 mUidsOfNextSeenMsgsDict.setAutoDelete(
false );
74 headersOnServer.setAutoDelete(
true);
75 connect(&processMsgsTimer,TQ_SIGNAL(timeout()),TQ_SLOT(slotProcessPendingMsgs()));
76 TDEIO::Scheduler::connect(
77 TQ_SIGNAL(slaveError(TDEIO::Slave *,
int,
const TQString &)),
78 this, TQ_SLOT(slotSlaveError(TDEIO::Slave *,
int,
const TQString &)));
80 mHeaderDeleteUids.clear();
81 mHeaderDownUids.clear();
82 mHeaderLaterUids.clear();
87 PopAccount::~PopAccount()
91 mMsgsPendingDownload.clear();
92 processRemainingQueuedMessages();
99 TQString PopAccount::type(
void)
const
104 TQString PopAccount::protocol()
const {
105 return useSSL() ? POP_SSL_PROTOCOL : POP_PROTOCOL;
108 unsigned short int PopAccount::defaultPort()
const {
109 return pop3DefaultPort;
113 void PopAccount::init(
void)
115 NetworkAccount::init();
117 mUsePipelining =
false;
118 mLeaveOnServer =
false;
119 mLeaveOnServerDays = -1;
120 mLeaveOnServerCount = -1;
121 mLeaveOnServerSize = -1;
122 mFilterOnServer =
false;
124 mFilterOnServerCheckSize = 50000;
128 void PopAccount::pseudoAssign(
const KMAccount * a ) {
129 slotAbortRequested();
130 NetworkAccount::pseudoAssign( a );
145 void PopAccount::processNewMail(
bool _interactive)
149 if ( (mAskAgain || passwd().isEmpty() || mLogin.isEmpty()) &&
150 mAuth !=
"GSSAPI" ) {
151 TQString passwd = NetworkAccount::passwd();
152 bool b = storePasswd();
153 if (TDEIO::PasswordDialog::getNameAndPassword(mLogin, passwd, &b,
154 i18n(
"You need to supply a username and a password to access this "
155 "mailbox."),
false, TQString(), mName, i18n(
"Account:"))
156 != TQDialog::Accepted)
158 checkDone(
false, CheckAborted );
161 setPasswd( passwd, b );
163 kmkernel->acctMgr()->writeConfig(
true );
169 TQString seenUidList = locateLocal(
"data",
"kmail/" + mLogin +
":" +
"@" +
170 mHost +
":" + TQString(
"%1").arg(mPort) );
171 TDEConfig config( seenUidList );
172 TQStringList uidsOfSeenMsgs = config.readListEntry(
"seenUidList" );
173 TQValueList<int> timeOfSeenMsgs = config.readIntListEntry(
"seenUidTimeList" );
174 mUidsOfSeenMsgsDict.clear();
175 mUidsOfSeenMsgsDict.resize( KMail::nextPrime( ( uidsOfSeenMsgs.count() * 11 ) / 10 ) );
177 for ( TQStringList::ConstIterator it = uidsOfSeenMsgs.begin();
178 it != uidsOfSeenMsgs.end(); ++it, idx++ ) {
182 mUidsOfSeenMsgsDict.insert( *it, (
const int *)idx );
184 mTimeOfSeenMsgsVector.clear();
185 mTimeOfSeenMsgsVector.reserve( timeOfSeenMsgs.size() );
186 for ( TQValueList<int>::ConstIterator it = timeOfSeenMsgs.begin();
187 it != timeOfSeenMsgs.end(); ++it) {
188 mTimeOfSeenMsgsVector.append( *it );
193 if ( mTimeOfSeenMsgsVector.count() != mUidsOfSeenMsgsDict.count() )
194 mTimeOfSeenMsgsVector.clear();
195 TQStringList downloadLater = config.readListEntry(
"downloadLater" );
196 for ( TQStringList::Iterator it = downloadLater.begin(); it != downloadLater.end(); ++it ) {
197 mHeaderLaterUids.insert( *it,
true );
199 mUidsOfNextSeenMsgsDict.clear();
200 mTimeOfNextSeenMsgsMap.clear();
201 mSizeOfNextSeenMsgsDict.clear();
203 interactive = _interactive;
204 mUidlFinished =
false;
208 checkDone(
false, CheckIgnored );
215 void PopAccount::readConfig(TDEConfig& config)
217 NetworkAccount::readConfig(config);
219 mUsePipelining = config.readNumEntry(
"pipelining",
false);
220 mLeaveOnServer = config.readNumEntry(
"leave-on-server",
false);
221 mLeaveOnServerDays = config.readNumEntry(
"leave-on-server-days", -1);
222 mLeaveOnServerCount = config.readNumEntry(
"leave-on-server-count", -1);
223 mLeaveOnServerSize = config.readNumEntry(
"leave-on-server-size", -1);
224 mFilterOnServer = config.readNumEntry(
"filter-on-server",
false);
225 mFilterOnServerCheckSize = config.readUnsignedNumEntry(
"filter-os-check-size", 50000);
230 void PopAccount::writeConfig(TDEConfig& config)
232 NetworkAccount::writeConfig(config);
234 config.writeEntry(
"pipelining", mUsePipelining);
235 config.writeEntry(
"leave-on-server", mLeaveOnServer);
236 config.writeEntry(
"leave-on-server-days", mLeaveOnServerDays);
237 config.writeEntry(
"leave-on-server-count", mLeaveOnServerCount);
238 config.writeEntry(
"leave-on-server-size", mLeaveOnServerSize);
239 config.writeEntry(
"filter-on-server", mFilterOnServer);
240 config.writeEntry(
"filter-os-check-size", mFilterOnServerCheckSize);
245 void PopAccount::setUsePipelining(
bool b)
251 void PopAccount::setLeaveOnServer(
bool b)
257 void PopAccount::setLeaveOnServerDays(
int days)
259 mLeaveOnServerDays = days;
263 void PopAccount::setLeaveOnServerCount(
int count)
265 mLeaveOnServerCount = count;
269 void PopAccount::setLeaveOnServerSize(
int size)
271 mLeaveOnServerSize = size;
275 void PopAccount::setFilterOnServer(
bool b)
281 void PopAccount::setFilterOnServerCheckSize(
unsigned int aSize)
283 mFilterOnServerCheckSize = aSize;
287 void PopAccount::connectJob() {
288 TDEIO::Scheduler::assignJobToSlave(mSlave, job);
289 connect(job, TQ_SIGNAL( data( TDEIO::Job*,
const TQByteArray &)),
290 TQ_SLOT( slotData( TDEIO::Job*,
const TQByteArray &)));
291 connect(job, TQ_SIGNAL( result( TDEIO::Job * ) ),
292 TQ_SLOT( slotResult( TDEIO::Job * ) ) );
293 connect(job, TQ_SIGNAL(infoMessage( TDEIO::Job*,
const TQString & )),
294 TQ_SLOT( slotMsgRetrieved(TDEIO::Job*,
const TQString &)));
299 void PopAccount::slotCancel()
301 mMsgsPendingDownload.clear();
302 processRemainingQueuedMessages();
309 void PopAccount::slotProcessPendingMsgs()
316 TQValueList<KMMessage*>::Iterator cur = msgsAwaitingProcessing.begin();
317 TQStringList::Iterator curId = msgIdsAwaitingProcessing.begin();
318 TQStringList::Iterator curUid = msgUidsAwaitingProcessing.begin();
320 while (cur != msgsAwaitingProcessing.end()) {
326 addedOk = processNewMsg(*cur);
329 mMsgsPendingDownload.clear();
330 msgIdsAwaitingProcessing.clear();
331 msgUidsAwaitingProcessing.clear();
335 idsOfMsgsToDelete.append( *curId );
336 mUidsOfNextSeenMsgsDict.insert( *curUid, (
const int *)1 );
337 mTimeOfNextSeenMsgsMap.insert( *curUid, time(0) );
344 msgsAwaitingProcessing.clear();
345 msgIdsAwaitingProcessing.clear();
346 msgUidsAwaitingProcessing.clear();
352 void PopAccount::slotAbortRequested()
354 if (stage == Idle)
return;
355 if ( mMailCheckProgressItem )
356 disconnect( mMailCheckProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
357 this, TQ_SLOT( slotAbortRequested() ) );
359 if (job) job->kill();
367 void PopAccount::startJob()
370 if (!runPrecommand(precommand()))
372 KMessageBox::sorry(0,
373 i18n(
"Could not execute precommand: %1").arg(precommand()),
374 i18n(
"KMail Error Message"));
375 checkDone(
false, CheckError );
382 if ( !url.isValid() ) {
383 KMessageBox::error(0, i18n(
"Source URL is malformed"),
384 i18n(
"Kioslave Error Message") );
388 mMsgsPendingDownload.clear();
390 mUidForIdMap.clear();
391 idsOfMsgsToDelete.clear();
392 idsOfForcedDeletes.clear();
395 headersOnServer.clear();
397 indexOfCurrentMsg = -1;
399 Q_ASSERT( !mMailCheckProgressItem );
400 TQString escapedName = TQStyleSheet::escape( mName );
401 mMailCheckProgressItem = KPIM::ProgressManager::createProgressItem(
404 i18n(
"Preparing transmission from \"%1\"...").arg( escapedName ),
406 useSSL() || useTLS() );
407 connect( mMailCheckProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
408 this, TQ_SLOT( slotAbortRequested() ) );
413 mSlave = TDEIO::Scheduler::getConnectedSlave( url, slaveConfig() );
416 slotSlaveError(0, TDEIO::ERR_CANNOT_LAUNCH_PROCESS, url.protocol());
419 url.setPath(TQString(
"/index"));
420 job = TDEIO::get( url,
false,
false );
424 MetaData PopAccount::slaveConfig()
const {
425 MetaData m = NetworkAccount::slaveConfig();
427 m.insert(
"progress",
"off");
428 m.insert(
"pipelining", (mUsePipelining) ?
"on" :
"off");
429 if (mAuth ==
"PLAIN" || mAuth ==
"LOGIN" || mAuth ==
"CRAM-MD5" ||
430 mAuth ==
"DIGEST-MD5" || mAuth ==
"NTLM" || mAuth ==
"GSSAPI") {
431 m.insert(
"auth",
"SASL");
432 m.insert(
"sasl", mAuth);
433 }
else if ( mAuth ==
"*" )
434 m.insert(
"auth",
"USER");
436 m.insert(
"auth", mAuth);
444 void PopAccount::slotMsgRetrieved(TDEIO::Job*,
const TQString & infoMsg)
446 if (infoMsg !=
"message complete")
return;
451 uint newSize = Util::crlf2lf( curMsgData.data(), curMsgData.size() );
452 curMsgData.resize( newSize );
453 msg->fromByteArray( curMsgData ,
true );
456 int size = mMsgsPendingDownload[ headerIt.current()->id() ];
457 kdDebug(5006) <<
"Size of Message: " << size << endl;
458 msg->setMsgLength( size );
459 headerIt.current()->setHeader(msg);
465 msg->setMsgLength( curMsgData.size() );
466 msgsAwaitingProcessing.append(msg);
467 msgIdsAwaitingProcessing.append(idsOfMsgs[indexOfCurrentMsg]);
468 msgUidsAwaitingProcessing.append( mUidForIdMap[idsOfMsgs[indexOfCurrentMsg]] );
476 void PopAccount::slotJobFinished() {
477 TQStringList emptyList;
479 kdDebug(5006) << k_funcinfo <<
"stage == List" << endl;
482 mUidsOfNextSeenMsgsDict.resize( KMail::nextPrime( ( idsOfMsgs.count() * 11 ) / 10 ) );
484 url.setPath(TQString(
"/uidl"));
485 job = TDEIO::get( url,
false,
false );
489 else if (stage == Uidl) {
490 kdDebug(5006) << k_funcinfo <<
"stage == Uidl" << endl;
491 mUidlFinished =
true;
493 if ( mLeaveOnServer && mUidForIdMap.isEmpty() &&
494 mUidsOfNextSeenMsgsDict.isEmpty() && !idsOfMsgs.isEmpty() ) {
495 KMessageBox::sorry(0, i18n(
"Your POP3 server (Account: %1) does not support "
496 "the UIDL command: this command is required to determine, in a reliable way, "
497 "which of the mails on the server KMail has already seen before;\n"
498 "the feature to leave the mails on the server will therefore not "
499 "work properly.").arg(NetworkAccount::name()) );
501 mUidsOfNextSeenMsgsDict = mUidsOfSeenMsgsDict;
505 if (mFilterOnServer ==
true) {
506 TQMap<TQString, int>::Iterator hids;
507 for ( hids = mMsgsPendingDownload.begin();
508 hids != mMsgsPendingDownload.end(); hids++ ) {
509 kdDebug(5006) <<
"Length: " << hids.data() << endl;
511 if ( (
unsigned int)hids.data() >= mFilterOnServerCheckSize ) {
512 kdDebug(5006) <<
"bigger than " << mFilterOnServerCheckSize << endl;
513 headersOnServer.append(
new KMPopHeaders( hids.key(),
514 mUidForIdMap[hids.key()],
517 if( mHeaderDeleteUids.contains( headersOnServer.current()->uid() ) ) {
518 headersOnServer.current()->setAction(Delete);
520 else if( mHeaderDownUids.contains( headersOnServer.current()->uid() ) ) {
521 headersOnServer.current()->setAction(Down);
523 else if( mHeaderLaterUids.contains( headersOnServer.current()->uid() ) ) {
524 headersOnServer.current()->setAction(Later);
529 mHeaderDeleteUids.clear();
530 mHeaderDownUids.clear();
531 mHeaderLaterUids.clear();
535 if ((headersOnServer.count() > 0) && (mFilterOnServer ==
true)) {
539 while (headerIt.current())
541 headerIds += headerIt.current()->id();
542 if (!headerIt.atLast()) headerIds +=
",";
546 url.setPath(TQString(
"/headers/") + headerIds);
547 job = TDEIO::get( url,
false,
false );
554 numMsgs = mMsgsPendingDownload.count();
556 TQMap<TQString, int>::Iterator len;
557 for ( len = mMsgsPendingDownload.begin();
558 len != mMsgsPendingDownload.end(); len++ )
559 numBytesToRead += len.data();
560 idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
562 url.setPath(
"/download/" + idsOfMsgs.join(
",") );
563 job = TDEIO::get( url,
false,
false );
566 processMsgsTimer.start(processingDelay);
569 else if (stage == Head) {
570 kdDebug(5006) << k_funcinfo <<
"stage == Head" << endl;
577 KMPopFilterAction action;
578 bool dlgPopup =
false;
579 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
580 action = (KMPopFilterAction)kmkernel->popFilterMgr()->process(headersOnServer.current()->header());
584 kdDebug(5006) <<
"PopFilterAction = NoAction" << endl;
587 kdDebug(5006) <<
"PopFilterAction = Later" << endl;
590 kdDebug(5006) <<
"PopFilterAction = Delete" << endl;
593 kdDebug(5006) <<
"PopFilterAction = Down" << endl;
596 kdDebug(5006) <<
"PopFilterAction = default oops!" << endl;
605 if (kmkernel->popFilterMgr()->showLaterMsgs())
609 headersOnServer.current()->setAction(action);
610 headersOnServer.current()->setRuleMatched(
true);
619 KMPopFilterCnfrmDlg dlg(&headersOnServer, this->name(), kmkernel->popFilterMgr()->showLaterMsgs());
623 for (headersOnServer.first(); headersOnServer.current(); headersOnServer.next()) {
624 if (headersOnServer.current()->action() == Delete ||
625 headersOnServer.current()->action() == Later) {
628 if ( mMsgsPendingDownload.contains( headersOnServer.current()->id() ) ) {
629 mMsgsPendingDownload.remove( headersOnServer.current()->id() );
631 if (headersOnServer.current()->action() == Delete) {
632 mHeaderDeleteUids.insert(headersOnServer.current()->uid(),
true);
633 mUidsOfNextSeenMsgsDict.insert( headersOnServer.current()->uid(),
635 idsOfMsgsToDelete.append(headersOnServer.current()->id());
636 mTimeOfNextSeenMsgsMap.insert( headersOnServer.current()->uid(),
640 mHeaderLaterUids.insert(headersOnServer.current()->uid(),
true);
643 else if (headersOnServer.current()->action() == Down) {
644 mHeaderDownUids.insert(headersOnServer.current()->uid(),
true);
648 headersOnServer.clear();
650 numMsgs = mMsgsPendingDownload.count();
652 TQMap<TQString, int>::Iterator len;
653 for (len = mMsgsPendingDownload.begin();
654 len != mMsgsPendingDownload.end(); len++)
655 numBytesToRead += len.data();
656 idsOfMsgs = TQStringList( mMsgsPendingDownload.keys() );
658 url.setPath(
"/download/" + idsOfMsgs.join(
",") );
659 job = TDEIO::get( url,
false,
false );
662 processMsgsTimer.start(processingDelay);
664 else if (stage == Retr) {
665 if ( mMailCheckProgressItem )
666 mMailCheckProgressItem->setProgress( 100 );
667 processRemainingQueuedMessages();
669 mHeaderDeleteUids.clear();
670 mHeaderDownUids.clear();
671 mHeaderLaterUids.clear();
673 kmkernel->folderMgr()->syncAllFolders();
676 TQMap< TQPair<time_t, TQString>,
int > idsToSave;
679 if ( mLeaveOnServer && !idsOfMsgsToDelete.isEmpty() ) {
681 if ( mLeaveOnServerDays == -1 && mLeaveOnServerCount <= 0 &&
682 mLeaveOnServerSize <= 0)
683 idsOfMsgsToDelete.clear();
685 else if ( mLeaveOnServerDays > 0 && !mTimeOfNextSeenMsgsMap.isEmpty() ) {
686 time_t timeLimit = time(0) - (86400 * mLeaveOnServerDays);
687 kdDebug() <<
"timeLimit is " << timeLimit << endl;
688 TQStringList::Iterator cur = idsOfMsgsToDelete.begin();
689 for ( ; cur != idsOfMsgsToDelete.end(); ++cur) {
690 time_t msgTime = mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]];
691 kdDebug() <<
"id: " << *cur <<
" msgTime: " << msgTime << endl;
692 if (msgTime >= timeLimit ||
693 !mTimeOfNextSeenMsgsMap[mUidForIdMap[*cur]]) {
694 kdDebug() <<
"Saving msg id " << *cur << endl;
695 TQPair<time_t, TQString> msg(msgTime, *cur);
696 idsToSave.insert( msg, 1 );
701 if ( mLeaveOnServerCount > 0 ) {
702 int numToDelete = idsToSave.count() - mLeaveOnServerCount;
703 kdDebug() <<
"numToDelete is " << numToDelete << endl;
704 if ( numToDelete > 0 && (
unsigned)numToDelete < idsToSave.count() ) {
705 TQMap< TQPair<time_t, TQString>,
int >::Iterator cur = idsToSave.begin();
706 for (
int deleted = 0; deleted < numToDelete && cur != idsToSave.end()
707 ; deleted++, cur++ ) {
708 kdDebug() <<
"deleting msg id " << cur.key().second << endl;
709 idsToSave.remove( cur );
712 else if ( numToDelete > 0 && (
unsigned)numToDelete >= idsToSave.count() )
716 if ( mLeaveOnServerSize > 0 ) {
717 double sizeOnServer = 0;
718 TQMap< TQPair<time_t, TQString>,
int >::Iterator cur = idsToSave.begin();
719 for ( ; cur != idsToSave.end(); cur++ ) {
721 *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
723 kdDebug() <<
"sizeOnServer is " << sizeOnServer/(1024*1024) <<
"MB" << endl;
724 long limitInBytes = mLeaveOnServerSize * ( 1024 * 1024 );
725 for ( cur = idsToSave.begin(); cur != idsToSave.end()
726 && sizeOnServer > limitInBytes; cur++ ) {
728 *mSizeOfNextSeenMsgsDict[ mUidForIdMap[ cur.key().second ] ];
729 idsToSave.remove( cur );
733 TQMap< TQPair<time_t, TQString>,
int >::Iterator it = idsToSave.begin();
734 kdDebug() <<
"Going to save " << idsToSave.count() << endl;
735 for ( ; it != idsToSave.end(); ++it ) {
736 kdDebug() <<
"saving msg id " << it.key().second << endl;
737 idsOfMsgsToDelete.remove( it.key().second );
741 if ( !idsOfForcedDeletes.isEmpty() ) {
742 idsOfMsgsToDelete += idsOfForcedDeletes;
743 idsOfForcedDeletes.clear();
747 if ( !idsOfMsgsToDelete.isEmpty() ) {
749 if ( mMailCheckProgressItem )
750 mMailCheckProgressItem->setStatus(
751 i18n(
"Fetched 1 message from %1. Deleting messages from server...",
752 "Fetched %n messages from %1. Deleting messages from server...",
755 url.setPath(
"/remove/" + idsOfMsgsToDelete.join(
","));
756 kdDebug(5006) <<
"url: " << url.prettyURL() << endl;
759 if ( mMailCheckProgressItem )
760 mMailCheckProgressItem->setStatus(
761 i18n(
"Fetched 1 message from %1. Terminating transmission...",
762 "Fetched %n messages from %1. Terminating transmission...",
765 url.setPath(TQString(
"/commit"));
766 kdDebug(5006) <<
"url: " << url.prettyURL() << endl;
768 job = TDEIO::get( url,
false,
false );
771 else if (stage == Dele) {
772 kdDebug(5006) << k_funcinfo <<
"stage == Dele" << endl;
774 for ( TQStringList::ConstIterator it = idsOfMsgsToDelete.begin();
775 it != idsOfMsgsToDelete.end(); ++it ) {
776 mUidsOfNextSeenMsgsDict.remove( mUidForIdMap[*it] );
778 idsOfMsgsToDelete.clear();
779 if ( mMailCheckProgressItem )
780 mMailCheckProgressItem->setStatus(
781 i18n(
"Fetched 1 message from %1. Terminating transmission...",
782 "Fetched %n messages from %1. Terminating transmission...",
786 url.setPath(TQString(
"/commit"));
787 job = TDEIO::get( url,
false,
false );
791 else if (stage == Quit) {
792 kdDebug(5006) << k_funcinfo <<
"stage == Quit" << endl;
795 if (mSlave) TDEIO::Scheduler::disconnectSlave(mSlave);
798 if( mMailCheckProgressItem ) {
799 bool canceled = !kmkernel || kmkernel->mailCheckAborted() || mMailCheckProgressItem->canceled();
800 int numMessages = canceled ? indexOfCurrentMsg : idsOfMsgs.count();
801 BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
802 this->name(), numMessages, numBytes, numBytesRead, numBytesToRead, mLeaveOnServer, mMailCheckProgressItem );
805 ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
806 mMailCheckProgressItem = 0;
807 savedMailCheckProgressItem->setComplete();
808 checkDone( ( numMessages > 0 ), canceled ? CheckAborted : CheckOK );
815 void PopAccount::processRemainingQueuedMessages()
817 kdDebug(5006) << k_funcinfo << endl;
818 slotProcessPendingMsgs();
819 processMsgsTimer.stop();
822 if ( kmkernel && kmkernel->folderMgr() ) {
823 kmkernel->folderMgr()->syncAllFolders();
829 void PopAccount::saveUidList()
831 kdDebug(5006) << k_funcinfo << endl;
834 if (!mUidlFinished)
return;
836 TQStringList uidsOfNextSeenMsgs;
837 TQValueList<int> seenUidTimeList;
838 TQDictIterator<int> it( mUidsOfNextSeenMsgsDict );
839 for( ; it.current(); ++it ) {
840 uidsOfNextSeenMsgs.append( it.currentKey() );
841 seenUidTimeList.append( mTimeOfNextSeenMsgsMap[it.currentKey()] );
843 TQString seenUidList = locateLocal(
"data",
"kmail/" + mLogin +
":" +
"@" +
844 mHost +
":" + TQString(
"%1").arg(mPort) );
845 TDEConfig config( seenUidList );
846 config.writeEntry(
"seenUidList", uidsOfNextSeenMsgs );
847 config.writeEntry(
"seenUidTimeList", seenUidTimeList );
848 config.writeEntry(
"downloadLater", TQStringList( mHeaderLaterUids.keys() ) );
854 void PopAccount::slotGetNextMsg()
856 TQMap<TQString, int>::Iterator next = mMsgsPendingDownload.begin();
858 curMsgData.resize(0);
864 if ( next != mMsgsPendingDownload.end() ) {
866 int nextLen = next.data();
867 curMsgStrm =
new TQDataStream( curMsgData, IO_WriteOnly );
870 kdDebug(5006) << TQString(
"Length of message about to get %1").arg( nextLen ) << endl;
871 mMsgsPendingDownload.remove( next.key() );
877 void PopAccount::slotData( TDEIO::Job* job,
const TQByteArray &data)
879 if (data.size() == 0) {
880 kdDebug(5006) <<
"Data: <End>" << endl;
881 if ((stage == Retr) && (numMsgBytesRead < curMsgLen))
882 numBytesRead += curMsgLen - numMsgBytesRead;
883 else if (stage == Head){
884 kdDebug(5006) <<
"Head: <End>" << endl;
889 int oldNumMsgBytesRead = numMsgBytesRead;
892 curMsgStrm->writeRawBytes( data.data(), data.size() );
893 numMsgBytesRead += data.size();
894 if (numMsgBytesRead > curMsgLen)
895 numMsgBytesRead = curMsgLen;
896 numBytesRead += numMsgBytesRead - oldNumMsgBytesRead;
898 if ( mMailCheckProgressItem &&
899 ( dataCounter % 5 == 0 ||
900 ( indexOfCurrentMsg + 1 == numMsgs && numMsgBytesRead == curMsgLen ) ) )
903 if (numBytes != numBytesToRead && mLeaveOnServer)
905 msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6 "
906 "(%7 KB remain on the server).")
907 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
908 .arg(numBytesToRead/1024).arg(mLogin).arg(mHost).arg(numBytes/1024);
912 msg = i18n(
"Fetching message %1 of %2 (%3 of %4 KB) for %5@%6.")
913 .arg(indexOfCurrentMsg+1).arg(numMsgs).arg(numBytesRead/1024)
914 .arg(numBytesToRead/1024).arg(mLogin).arg(mHost);
916 mMailCheckProgressItem->setStatus( msg );
917 mMailCheckProgressItem->setProgress(
918 (numBytesToRead <= 100) ? 50
920 : (numBytesRead / (numBytesToRead / 100)) );
926 curMsgStrm->writeRawBytes( data.data(), data.size() );
931 TQString qdata = data;
932 qdata = qdata.simplifyWhiteSpace();
933 int spc = qdata.find(
' ' );
934 if ( stage == List ) {
936 TQString length = qdata.mid(spc+1);
937 if (length.find(
' ') != -1) length.truncate(length.find(
' '));
938 int len = length.toInt();
940 TQString
id = qdata.left(spc);
941 idsOfMsgs.append(
id );
942 mMsgsPendingDownload.insert(
id, len );
946 if ( job ) job->kill();
949 KMessageBox::error( 0, i18n(
"Unable to complete LIST operation." ),
950 i18n(
"Invalid Response From Server") );
955 Q_ASSERT ( stage == Uidl);
966 int testid = atoi ( qdata.ascii() );
969 kdDebug(5006) <<
"PopAccount::slotData skipping UIDL entry due to parse error "
970 << endl << qdata.ascii() << endl;
973 id.setNum (testid, 10);
975 TQString datestring, serialstring;
977 serialstring.setNum ( ++dataCounter, 10 );
978 datestring.setNum ( time(NULL),10 );
979 uid = TQString(
"uidlgen" ) + datestring + TQString(
"." ) + serialstring;
980 kdDebug(5006) <<
"PopAccount::slotData message " <<
id.ascii()
981 <<
"%d has bad UIDL, cannot keep a copy on server" << endl;
982 idsOfForcedDeletes.append(
id );
985 id = qdata.left( spc );
986 uid = qdata.mid( spc + 1 );
990 *size = mMsgsPendingDownload[id];
991 mSizeOfNextSeenMsgsDict.insert( uid, size );
992 if ( mUidsOfSeenMsgsDict.find( uid ) != 0 ) {
993 if ( mMsgsPendingDownload.contains(
id ) ) {
994 mMsgsPendingDownload.remove(
id );
997 kdDebug(5006) <<
"PopAccount::slotData synchronization failure." << endl;
998 idsOfMsgsToDelete.append(
id );
999 mUidsOfNextSeenMsgsDict.insert( uid, (
const int *)1 );
1000 if ( mTimeOfSeenMsgsVector.empty() ) {
1001 mTimeOfNextSeenMsgsMap.insert( uid, time(0) );
1006 mTimeOfNextSeenMsgsMap.insert( uid, mTimeOfSeenMsgsVector[(
int)(
long )
1007 mUidsOfSeenMsgsDict[uid] - 1] );
1010 mUidForIdMap.insert(
id, uid );
1015 void PopAccount::slotResult( TDEIO::Job* )
1024 if (stage == Head && job->error() == TDEIO::ERR_COULD_NOT_READ)
1026 KMessageBox::error(0, i18n(
"Your server does not support the "
1027 "TOP command. Therefore it is not possible to fetch the headers "
1028 "of large emails first, before downloading them."));
1033 if (!mStorePasswd) mPasswd =
"";
1034 job->showErrorDialog();
1044 void PopAccount::slotSlaveError(TDEIO::Slave *aSlave,
int error,
1045 const TQString &errorMsg)
1047 if (aSlave != mSlave)
return;
1048 if (error == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1051 if ( error == TDEIO::ERR_CONNECTION_BROKEN && mSlave ) {
1052 TDEIO::Scheduler::disconnectSlave( mSlave );
1056 if (interactive && kmkernel) {
1057 KMessageBox::error(kmkernel->mainWin(), TDEIO::buildErrorString(error, errorMsg));
1062 if (error == TDEIO::ERR_COULD_NOT_LOGIN && !mStorePasswd)
1067 TQTimer::singleShot(0,
this, TQ_SLOT(slotCancel()));
1071 void PopAccount::slotGetNextHdr(){
1072 kdDebug(5006) <<
"slotGetNextHeader" << endl;
1074 curMsgData.resize(0);
1078 curMsgStrm =
new TQDataStream( curMsgData, IO_WriteOnly );
1081 void PopAccount::killAllJobs(
bool ) {
1086 #include "popaccount.moc"
void setComplete(bool v)
Set if the message is a complete message.
The account manager is responsible for creating accounts of various types via the factory method crea...
KMail account for pop mail account.
bool filterOnServer(void) const
Shall messages be filter on the server (TRUE) or not (FALSE).
bool usePipelining(void) const
Sending of several commands at once.
int leaveOnServerDays(void) const
If value is positive, leave mail on the server for so many days.
int leaveOnServerSize(void) const
If value is positive, leave so many MBs on the server.
bool leaveOnServer(void) const
Shall messages be left on the server upon retreival (TRUE) or deleted (FALSE).
int leaveOnServerCount(void) const
If value is positive, leave so many messages on the server.
unsigned int filterOnServerCheckSize(void) const
Size of messages which should be check on the pop server before download.