• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

KIMAP Library

  • sources
  • kde-4.14
  • kdepimlibs
  • kimap
fetchjob.cpp
1 /*
2  Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "fetchjob.h"
21 
22 #include <QtCore/QTimer>
23 #include <KDE/KDebug>
24 #include <KDE/KLocalizedString>
25 
26 #include "job_p.h"
27 #include "message_p.h"
28 #include "session_p.h"
29 
30 namespace KIMAP
31 {
32  class FetchJobPrivate : public JobPrivate
33  {
34  public:
35  FetchJobPrivate( FetchJob *job, Session *session, const QString& name )
36  : JobPrivate( session, name )
37  , q( job )
38  , uidBased( false )
39  , gmailEnabled(false)
40  { }
41 
42  ~FetchJobPrivate()
43  { }
44 
45  void parseBodyStructure( const QByteArray &structure, int &pos, KMime::Content *content );
46  void parsePart( const QByteArray &structure, int &pos, KMime::Content *content );
47  QByteArray parseString( const QByteArray &structure, int &pos );
48  QByteArray parseSentence( const QByteArray &structure, int &pos );
49  void skipLeadingSpaces( const QByteArray &structure, int &pos );
50 
51  void emitPendings()
52  {
53  if ( pendingUids.isEmpty() ) {
54  return;
55  }
56 
57  if ( !pendingParts.isEmpty() ) {
58  emit q->partsReceived( selectedMailBox,
59  pendingUids, pendingParts );
60  emit q->partsReceived( selectedMailBox,
61  pendingUids, pendingAttributes,
62  pendingParts );
63  }
64  if ( !pendingSizes.isEmpty() || !pendingFlags.isEmpty() ) {
65  emit q->headersReceived( selectedMailBox,
66  pendingUids, pendingSizes,
67  pendingFlags, pendingMessages );
68  emit q->headersReceived( selectedMailBox,
69  pendingUids, pendingSizes,
70  pendingAttributes, pendingFlags,
71  pendingMessages );
72  }
73  if ( !pendingMessages.isEmpty() ) {
74  emit q->messagesReceived( selectedMailBox,
75  pendingUids, pendingMessages );
76  emit q->messagesReceived( selectedMailBox,
77  pendingUids, pendingAttributes,
78  pendingMessages );
79  }
80 
81  pendingUids.clear();
82  pendingMessages.clear();
83  pendingParts.clear();
84  pendingSizes.clear();
85  pendingFlags.clear();
86  pendingAttributes.clear();
87  }
88 
89  FetchJob * const q;
90 
91  ImapSet set;
92  bool uidBased;
93  FetchJob::FetchScope scope;
94  QString selectedMailBox;
95  bool gmailEnabled;
96 
97  QTimer emitPendingsTimer;
98  QMap<qint64, MessagePtr> pendingMessages;
99  QMap<qint64, MessageParts> pendingParts;
100  QMap<qint64, MessageFlags> pendingFlags;
101  QMap<qint64, MessageAttribute> pendingAttributes;
102  QMap<qint64, qint64> pendingSizes;
103  QMap<qint64, qint64> pendingUids;
104  };
105 }
106 
107 using namespace KIMAP;
108 
109 FetchJob::FetchScope::FetchScope():
110  mode( FetchScope::Content ),
111  changedSince( 0 )
112 {
113 
114 }
115 
116 FetchJob::FetchJob( Session *session )
117  : Job( *new FetchJobPrivate( this, session, i18n( "Fetch" ) ) )
118 {
119  Q_D( FetchJob );
120  connect( &d->emitPendingsTimer, SIGNAL(timeout()),
121  this, SLOT(emitPendings()) );
122 }
123 
124 FetchJob::~FetchJob()
125 {
126 }
127 
128 void FetchJob::setSequenceSet( const ImapSet &set )
129 {
130  Q_D( FetchJob );
131  Q_ASSERT( !set.toImapSequenceSet().trimmed().isEmpty() );
132  d->set = set;
133 }
134 
135 ImapSet FetchJob::sequenceSet() const
136 {
137  Q_D( const FetchJob );
138  return d->set;
139 }
140 
141 void FetchJob::setUidBased(bool uidBased)
142 {
143  Q_D( FetchJob );
144  d->uidBased = uidBased;
145 }
146 
147 bool FetchJob::isUidBased() const
148 {
149  Q_D( const FetchJob );
150  return d->uidBased;
151 }
152 
153 void FetchJob::setScope( const FetchScope &scope )
154 {
155  Q_D( FetchJob );
156  d->scope = scope;
157 }
158 
159 FetchJob::FetchScope FetchJob::scope() const
160 {
161  Q_D( const FetchJob );
162  return d->scope;
163 }
164 
165 bool FetchJob::setGmailExtensionsEnabled() const
166 {
167  Q_D( const FetchJob );
168  return d->gmailEnabled;
169 }
170 
171 void FetchJob::setGmailExtensionsEnabled( bool enabled )
172 {
173  Q_D( FetchJob );
174  d->gmailEnabled = enabled;
175 }
176 
177 QMap<qint64, MessagePtr> FetchJob::messages() const
178 {
179  return QMap<qint64, MessagePtr>();
180 }
181 
182 QMap<qint64, MessageParts> FetchJob::parts() const
183 {
184  return QMap<qint64, MessageParts>();
185 }
186 
187 QMap<qint64, MessageFlags> FetchJob::flags() const
188 {
189  return QMap<qint64, MessageFlags>();
190 }
191 
192 QMap<qint64, qint64> FetchJob::sizes() const
193 {
194  return QMap<qint64, qint64>();
195 }
196 
197 QMap<qint64, qint64> FetchJob::uids() const
198 {
199  return QMap<qint64, qint64>();
200 }
201 
202 void FetchJob::doStart()
203 {
204  Q_D( FetchJob );
205 
206  QByteArray parameters = d->set.toImapSequenceSet()+' ';
207  Q_ASSERT( !parameters.trimmed().isEmpty() );
208 
209  switch ( d->scope.mode ) {
210  case FetchScope::Headers:
211  if ( d->scope.parts.isEmpty() ) {
212  parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] FLAGS UID";
213  } else {
214  parameters += '(';
215  foreach ( const QByteArray &part, d->scope.parts ) {
216  parameters += "BODY.PEEK[" + part + ".MIME] ";
217  }
218  parameters += "UID";
219  }
220  break;
221  case FetchScope::Flags:
222  parameters += "(FLAGS UID";
223  break;
224  case FetchScope::Structure:
225  parameters += "(BODYSTRUCTURE UID";
226  break;
227  case FetchScope::Content:
228  if ( d->scope.parts.isEmpty() ) {
229  parameters += "(BODY.PEEK[] UID";
230  } else {
231  parameters += '(';
232  foreach ( const QByteArray &part, d->scope.parts ) {
233  parameters += "BODY.PEEK[" + part + "] ";
234  }
235  parameters += "UID";
236  }
237  break;
238  case FetchScope::Full:
239  parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID";
240  break;
241  case FetchScope::HeaderAndContent:
242  if ( d->scope.parts.isEmpty() ) {
243  parameters += "(BODY.PEEK[] FLAGS UID";
244  } else {
245  parameters += "(BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)]";
246  foreach ( const QByteArray &part, d->scope.parts ) {
247  parameters += " BODY.PEEK[" + part + ".MIME] BODY.PEEK[" + part + "]"; //krazy:exclude=doublequote_chars
248  }
249  parameters += " FLAGS UID";
250  }
251  break;
252  case FetchScope::FullHeaders:
253  parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER] FLAGS UID";
254  break;
255  }
256 
257  if ( d->gmailEnabled ) {
258  parameters += " X-GM-LABELS X-GM-MSGID X-GM-THRID";
259  }
260  parameters += ")";
261 
262  if ( d->scope.changedSince > 0 ) {
263  parameters += " (CHANGEDSINCE " + QByteArray::number( d->scope.changedSince ) + ")";
264  }
265 
266  QByteArray command = "FETCH";
267  if ( d->uidBased ) {
268  command = "UID " + command;
269  }
270 
271  d->emitPendingsTimer.start( 100 );
272  d->selectedMailBox = d->m_session->selectedMailBox();
273  d->tags << d->sessionInternal()->sendCommand( command, parameters );
274 }
275 
276 void FetchJob::handleResponse( const Message &response )
277 {
278  Q_D( FetchJob );
279 
280  // We can predict it'll be handled by handleErrorReplies() so stop
281  // the timer now so that result() will really be the last emitted signal.
282  if ( !response.content.isEmpty() &&
283  d->tags.size() == 1 &&
284  d->tags.contains( response.content.first().toString() ) ) {
285  d->emitPendingsTimer.stop();
286  d->emitPendings();
287  }
288 
289  if ( handleErrorReplies( response ) == NotHandled ) {
290  if ( response.content.size() == 4 &&
291  response.content[2].toString() == "FETCH" &&
292  response.content[3].type() == Message::Part::List ) {
293 
294  qint64 id = response.content[1].toString().toLongLong();
295  QList<QByteArray> content = response.content[3].toList();
296 
297  MessagePtr message( new KMime::Message );
298  bool shouldParseMessage = false;
299  MessageParts parts;
300 
301  for ( QList<QByteArray>::ConstIterator it = content.constBegin();
302  it != content.constEnd(); ++it ) {
303  QByteArray str = *it;
304  ++it;
305 
306  if ( it == content.constEnd() ) { // Uh oh, message was truncated?
307  kWarning() << "FETCH reply got truncated, skipping.";
308  break;
309  }
310 
311  if ( str == "UID" ) {
312  d->pendingUids[id] = it->toLongLong();
313  } else if ( str == "RFC822.SIZE" ) {
314  d->pendingSizes[id] = it->toLongLong();
315  } else if ( str == "INTERNALDATE" ) {
316  message->date()->setDateTime( KDateTime::fromString( QLatin1String(*it), KDateTime::RFCDate ) );
317  } else if ( str == "FLAGS" ) {
318  if ( ( *it ).startsWith( '(' ) && ( *it ).endsWith( ')' ) ) {
319  QByteArray str = *it;
320  str.chop( 1 );
321  str.remove( 0, 1 );
322  d->pendingFlags[id] = str.split( ' ' );
323  } else {
324  d->pendingFlags[id] << *it;
325  }
326  } else if ( str == "X-GM-LABELS" ) {
327  d->pendingAttributes.insert( id, qMakePair<QByteArray, QVariant>( "X-GM-LABELS", *it ) );
328  } else if ( str == "X-GM-THRID" ) {
329  d->pendingAttributes.insert( id, qMakePair<QByteArray, QVariant>( "X-GM-THRID", *it ) );
330  } else if ( str == "X-GM-MSGID" ) {
331  d->pendingAttributes.insert( id, qMakePair<QByteArray, QVariant>( "X-GM-MSGID", *it ) );
332  } else if ( str == "BODYSTRUCTURE" ) {
333  int pos = 0;
334  d->parseBodyStructure( *it, pos, message.get() );
335  message->assemble();
336  d->pendingMessages[id] = message;
337  } else if ( str.startsWith( "BODY[" ) ) { //krazy:exclude=strings
338  if ( !str.endsWith( ']' ) ) { // BODY[ ... ] might have been split, skip until we find the ]
339  while ( !( *it ).endsWith( ']' ) ) {
340  ++it;
341  }
342  ++it;
343  }
344 
345  int index;
346  if ( ( index = str.indexOf( "HEADER" ) ) > 0 || ( index = str.indexOf( "MIME" ) ) > 0 ) { // headers
347  if ( str[index-1] == '.' ) {
348  QByteArray partId = str.mid( 5, index - 6 );
349  if ( !parts.contains( partId ) ) {
350  parts[partId] = ContentPtr( new KMime::Content );
351  }
352  parts[partId]->setHead( *it );
353  parts[partId]->parse();
354  d->pendingParts[id] = parts;
355  } else {
356  message->setHead( *it );
357  shouldParseMessage = true;
358  }
359  } else { // full payload
360  if ( str == "BODY[]" ) {
361  message->setContent( KMime::CRLFtoLF( *it ) );
362  shouldParseMessage = true;
363 
364  d->pendingMessages[id] = message;
365  } else {
366  QByteArray partId = str.mid( 5, str.size() - 6 );
367  if ( !parts.contains( partId ) ) {
368  parts[partId] = ContentPtr( new KMime::Content );
369  }
370  parts[partId]->setBody( *it );
371  parts[partId]->parse();
372 
373  d->pendingParts[id] = parts;
374  }
375  }
376  }
377  }
378 
379  if ( shouldParseMessage ) {
380  message->parse();
381  }
382 
383  // For the headers mode the message is built in several
384  // steps, hence why we wait it to be done until putting it
385  // in the pending queue.
386  if ( d->scope.mode == FetchScope::Headers ||
387  d->scope.mode == FetchScope::HeaderAndContent ||
388  d->scope.mode == FetchScope::FullHeaders ) {
389  d->pendingMessages[id] = message;
390  }
391  }
392  }
393 }
394 
395 void FetchJobPrivate::parseBodyStructure(const QByteArray &structure, int &pos, KMime::Content *content)
396 {
397  skipLeadingSpaces( structure, pos );
398 
399  if ( structure[pos] != '(' ) {
400  return;
401  }
402 
403  pos++;
404 
405  if ( structure[pos] != '(' ) { // simple part
406  pos--;
407  parsePart( structure, pos, content );
408  } else { // multi part
409  content->contentType()->setMimeType( "MULTIPART/MIXED" );
410  while ( pos < structure.size() && structure[pos] == '(' ) {
411  KMime::Content *child = new KMime::Content;
412  content->addContent( child );
413  parseBodyStructure( structure, pos, child );
414  child->assemble();
415  }
416 
417  QByteArray subType = parseString( structure, pos );
418  content->contentType()->setMimeType( "MULTIPART/" + subType );
419 
420  QByteArray parameters = parseSentence( structure, pos ); // FIXME: Read the charset
421  if ( parameters.contains( "BOUNDARY" ) ) {
422  content->contentType()->setBoundary( parameters.remove( 0, parameters.indexOf( "BOUNDARY" ) + 11 ).split( '\"' )[0] );
423  }
424 
425  QByteArray disposition = parseSentence( structure, pos );
426  if ( disposition.contains( "INLINE" ) ) {
427  content->contentDisposition()->setDisposition( KMime::Headers::CDinline );
428  } else if ( disposition.contains( "ATTACHMENT" ) ) {
429  content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
430  }
431 
432  parseSentence( structure, pos ); // Ditch the body language
433  }
434 
435  // Consume what's left
436  while ( pos < structure.size() && structure[pos] != ')' ) {
437  skipLeadingSpaces( structure, pos );
438  parseSentence( structure, pos );
439  skipLeadingSpaces( structure, pos );
440  }
441 
442  pos++;
443 }
444 
445 void FetchJobPrivate::parsePart( const QByteArray &structure, int &pos, KMime::Content *content )
446 {
447  if ( structure[pos] != '(' ) {
448  return;
449  }
450 
451  pos++;
452 
453  QByteArray mainType = parseString( structure, pos );
454  QByteArray subType = parseString( structure, pos );
455 
456  content->contentType()->setMimeType( mainType + '/' + subType );
457 
458  parseSentence( structure, pos ); // Ditch the parameters... FIXME: Read it to get charset and name
459  parseString( structure, pos ); // ... and the id
460 
461  content->contentDescription()->from7BitString( parseString( structure, pos ) );
462 
463  parseString( structure, pos ); // Ditch the encoding too
464  parseString( structure, pos ); // ... and the size
465  parseString( structure, pos ); // ... and the line count
466 
467  QByteArray disposition = parseSentence( structure, pos );
468  if ( disposition.contains( "INLINE" ) ) {
469  content->contentDisposition()->setDisposition( KMime::Headers::CDinline );
470  } else if ( disposition.contains( "ATTACHMENT" ) ) {
471  content->contentDisposition()->setDisposition( KMime::Headers::CDattachment );
472  }
473  if ( ( content->contentDisposition()->disposition() == KMime::Headers::CDattachment ||
474  content->contentDisposition()->disposition() == KMime::Headers::CDinline ) &&
475  disposition.contains( "FILENAME" ) ) {
476  QByteArray filename = disposition.remove( 0, disposition.indexOf( "FILENAME" ) + 11 ).split( '\"' )[0];
477  content->contentDisposition()->setFilename( QLatin1String(filename) );
478  }
479 
480  // Consume what's left
481  while ( pos < structure.size() && structure[pos] != ')' ) {
482  skipLeadingSpaces( structure, pos );
483  parseSentence( structure, pos );
484  skipLeadingSpaces( structure, pos );
485  }
486 }
487 
488 QByteArray FetchJobPrivate::parseSentence( const QByteArray &structure, int &pos )
489 {
490  QByteArray result;
491  int stack = 0;
492 
493  skipLeadingSpaces( structure, pos );
494 
495  if ( structure[pos] != '(' ) {
496  return parseString( structure, pos );
497  }
498 
499  int start = pos;
500 
501  do {
502  switch ( structure[pos] ) {
503  case '(':
504  pos++;
505  stack++;
506  break;
507  case ')':
508  pos++;
509  stack--;
510  break;
511  case '[':
512  pos++;
513  stack++;
514  break;
515  case ']':
516  pos++;
517  stack--;
518  break;
519  default:
520  skipLeadingSpaces( structure, pos );
521  parseString( structure, pos );
522  skipLeadingSpaces( structure, pos );
523  break;
524  }
525  } while ( pos < structure.size() && stack != 0 );
526 
527  result = structure.mid( start, pos - start );
528 
529  return result;
530 }
531 
532 QByteArray FetchJobPrivate::parseString( const QByteArray &structure, int &pos )
533 {
534  QByteArray result;
535 
536  skipLeadingSpaces( structure, pos );
537 
538  int start = pos;
539  bool foundSlash = false;
540 
541  // quoted string
542  if ( structure[pos] == '"' ) {
543  pos++;
544  Q_FOREVER {
545  if ( structure[pos] == '\\' ) {
546  pos += 2;
547  foundSlash = true;
548  continue;
549  }
550  if ( structure[pos] == '"' ) {
551  result = structure.mid( start + 1, pos - start - 1 );
552  pos++;
553  break;
554  }
555  pos++;
556  }
557  } else { // unquoted string
558  Q_FOREVER {
559  if ( structure[pos] == ' ' ||
560  structure[pos] == '(' ||
561  structure[pos] == ')' ||
562  structure[pos] == '[' ||
563  structure[pos] == ']' ||
564  structure[pos] == '\n' ||
565  structure[pos] == '\r' ||
566  structure[pos] == '"' ) {
567  break;
568  }
569  if ( structure[pos] == '\\' ) {
570  foundSlash = true;
571  }
572  pos++;
573  }
574 
575  result = structure.mid( start, pos - start );
576 
577  // transform unquoted NIL
578  if ( result == "NIL" ) {
579  result.clear();
580  }
581  }
582 
583  // simplify slashes
584  if ( foundSlash ) {
585  while ( result.contains( "\\\"" ) ) {
586  result.replace( "\\\"", "\"" );
587  }
588  while ( result.contains( "\\\\" ) ) {
589  result.replace( "\\\\", "\\" );
590  }
591  }
592 
593  return result;
594 }
595 
596 void FetchJobPrivate::skipLeadingSpaces( const QByteArray &structure, int &pos )
597 {
598  while ( pos < structure.size() && structure[pos] == ' ' ) {
599  pos++;
600  }
601 }
602 
603 #include "moc_fetchjob.cpp"
KIMAP::FetchJob::isUidBased
bool isUidBased() const
How to interpret the sequence set.
Definition: fetchjob.cpp:147
KIMAP::FetchJob::setSequenceSet
void setSequenceSet(const ImapSet &set)
Set which messages to fetch data for.
Definition: fetchjob.cpp:128
QByteArray::clear
void clear()
QMap::contains
bool contains(const Key &key) const
KIMAP::FetchJob::FetchScope::Content
Fetch the message content (the UID is also fetched)
Definition: fetchjob.h:110
QByteArray::split
QList< QByteArray > split(char sep) const
QByteArray::trimmed
QByteArray trimmed() const
QByteArray
QMap< qint64, MessagePtr >
QByteArray::chop
void chop(int n)
QByteArray::isEmpty
bool isEmpty() const
QByteArray::startsWith
bool startsWith(const QByteArray &ba) const
KIMAP::FetchJob::FetchScope::Full
Fetch the complete message.
Definition: fetchjob.h:114
KIMAP::FetchJob::flags
KIMAP_DEPRECATED QMap< qint64, MessageFlags > flags() const
Definition: fetchjob.cpp:187
KIMAP::FetchJob::scope
FetchScope scope() const
Specifies what data will be fetched.
Definition: fetchjob.cpp:159
KIMAP::FetchJob::FetchScope::FullHeaders
Fetch message size (in octets), internal date of the message, flags, UID and all RFC822 headers...
Definition: fetchjob.h:142
QByteArray::indexOf
int indexOf(char ch, int from) const
QTimer
KIMAP::FetchJob::FetchScope::Structure
Fetch the MIME message body structure (the UID is also fetched)
Definition: fetchjob.h:103
KIMAP::FetchJob::FetchScope::Headers
Fetch RFC-2822 or MIME message headers.
Definition: fetchjob.h:95
KIMAP::FetchJob
Fetch message data from the server.
Definition: fetchjob.h:58
KIMAP::FetchJob::setUidBased
void setUidBased(bool uidBased)
Set how the sequence set should be interpreted.
Definition: fetchjob.cpp:141
QByteArray::number
QByteArray number(int n, int base)
KIMAP::FetchJob::FetchScope::HeaderAndContent
Fetch the message MIME headers and the content of parts specified in the parts field.
Definition: fetchjob.h:132
KIMAP::FetchJob::FetchScope::Flags
Fetch the message flags (the UID is also fetched)
Definition: fetchjob.h:99
QByteArray::replace
QByteArray & replace(int pos, int len, const char *after)
QString
QList< QByteArray >
QByteArray::mid
QByteArray mid(int pos, int len) const
KIMAP::FetchJob::parts
KIMAP_DEPRECATED QMap< qint64, MessageParts > parts() const
Definition: fetchjob.cpp:182
KIMAP::FetchJob::sizes
KIMAP_DEPRECATED QMap< qint64, qint64 > sizes() const
Definition: fetchjob.cpp:192
QByteArray::toLongLong
qlonglong toLongLong(bool *ok, int base) const
KIMAP::ImapSet
Represents a set of natural numbers (1-> ) in a as compact as possible form.
Definition: imapset.h:140
QLatin1String
QList::insert
void insert(int i, const T &value)
KIMAP::FetchJob::messages
KIMAP_DEPRECATED QMap< qint64, MessagePtr > messages() const
Definition: fetchjob.cpp:177
KIMAP::FetchJob::uids
KIMAP_DEPRECATED QMap< qint64, qint64 > uids() const
Definition: fetchjob.cpp:197
KIMAP::ImapSet::toImapSequenceSet
QByteArray toImapSequenceSet() const
Returns a IMAP-compatible QByteArray representation of this set.
Definition: imapset.cpp:272
QByteArray::contains
bool contains(char ch) const
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
KIMAP::FetchJob::setGmailExtensionsEnabled
bool setGmailExtensionsEnabled() const
Returns whether Gmail support is enabled.
Definition: fetchjob.cpp:165
KIMAP::FetchJob::sequenceSet
ImapSet sequenceSet() const
The messages that will be fetched.
Definition: fetchjob.cpp:135
QByteArray::size
int size() const
QByteArray::remove
QByteArray & remove(int pos, int len)
KIMAP::FetchJob::setScope
void setScope(const FetchScope &scope)
Sets what data should be fetched.
Definition: fetchjob.cpp:153
KIMAP::FetchJob::FetchScope
Used to indicate what message data should be fetched.
Definition: fetchjob.h:73
QByteArray::endsWith
bool endsWith(const QByteArray &ba) const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:03 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIMAP Library

Skip menu "KIMAP Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal