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();
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;
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;
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 * ) ),
293 connect(job, TQ_SIGNAL(infoMessage( TDEIO::Job*,
const TQString & )),
301 mMsgsPendingDownload.clear();
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();
354 if (stage == Idle)
return;
355 if ( mMailCheckProgressItem )
356 disconnect( mMailCheckProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem* ) ),
359 if (job) job->kill();
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* ) ),
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);
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]] );
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 );
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 );
817 kdDebug(5006) << k_funcinfo << endl;
819 processMsgsTimer.stop();
822 if ( kmkernel && kmkernel->folderMgr() ) {
823 kmkernel->folderMgr()->syncAllFolders();
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() ) );
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() );
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 );
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();
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()));
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"