or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-messaging.mdevent-handling.mdfolder-operations.mdindex.mdinternet-messaging.mdsearch-capabilities.md

folder-operations.mddocs/

0

# Folder Operations

1

2

This document covers folder management, message storage operations, hierarchical navigation, and folder-based message manipulation in the Jakarta Mail API.

3

4

## Folder Management

5

6

The Folder class represents a container for messages with support for hierarchical organization and various access modes.

7

8

### Folder Access and Navigation

9

10

```java { .api }

11

abstract class Folder implements AutoCloseable {

12

public abstract String getName() throws MessagingException;

13

public abstract String getFullName() throws MessagingException;

14

public URLName getURLName() throws MessagingException;

15

public abstract Folder getParent() throws MessagingException;

16

public abstract boolean exists() throws MessagingException;

17

}

18

```

19

20

### Folder Hierarchy

21

22

```java { .api }

23

abstract class Folder {

24

public abstract Folder[] list() throws MessagingException;

25

public abstract Folder[] list(String pattern) throws MessagingException;

26

public abstract Folder[] listSubscribed() throws MessagingException;

27

public abstract Folder[] listSubscribed(String pattern) throws MessagingException;

28

29

public abstract char getSeparator() throws MessagingException;

30

public abstract int getType() throws MessagingException;

31

32

public abstract boolean create(int type) throws MessagingException;

33

public abstract boolean delete(boolean recurse) throws MessagingException;

34

public abstract boolean renameTo(Folder f) throws MessagingException;

35

}

36

```

37

38

**Folder Types:**

39

- `HOLDS_MESSAGES` (0x01) - Can contain messages

40

- `HOLDS_FOLDERS` (0x02) - Can contain subfolders

41

42

**Access Modes:**

43

- `READ_ONLY` (1) - Read-only access

44

- `READ_WRITE` (2) - Read-write access

45

46

### Folder Lifecycle

47

48

```java { .api }

49

abstract class Folder {

50

public abstract void open(int mode) throws MessagingException;

51

public abstract void close() throws MessagingException;

52

public abstract void close(boolean expunge) throws MessagingException;

53

public abstract boolean isOpen();

54

55

public Store getStore();

56

public int getMode();

57

public String toString();

58

}

59

```

60

61

### Usage Example

62

63

```java

64

Store store = session.getStore("imap");

65

store.connect("imap.example.com", "username", "password");

66

67

// Navigate folder hierarchy

68

Folder defaultFolder = store.getDefaultFolder();

69

Folder[] folders = defaultFolder.list("*");

70

71

// Work with INBOX

72

Folder inbox = store.getFolder("INBOX");

73

if (inbox.exists()) {

74

inbox.open(Folder.READ_WRITE);

75

76

// Folder operations here

77

78

inbox.close(false); // Don't expunge on close

79

}

80

81

// Create new folder

82

Folder customFolder = store.getFolder("My Messages");

83

if (!customFolder.exists()) {

84

customFolder.create(Folder.HOLDS_MESSAGES);

85

}

86

```

87

88

## Message Access and Counting

89

90

### Message Retrieval

91

92

```java { .api }

93

abstract class Folder {

94

public abstract int getMessageCount() throws MessagingException;

95

public abstract int getNewMessageCount() throws MessagingException;

96

public abstract int getUnreadMessageCount() throws MessagingException;

97

public abstract int getDeletedMessageCount() throws MessagingException;

98

99

public abstract Message getMessage(int msgnum) throws MessagingException;

100

public abstract Message[] getMessages() throws MessagingException;

101

public abstract Message[] getMessages(int start, int end) throws MessagingException;

102

public abstract Message[] getMessages(int[] msgnums) throws MessagingException;

103

}

104

```

105

106

### Message Properties

107

108

```java { .api }

109

abstract class Folder {

110

public abstract boolean hasNewMessages() throws MessagingException;

111

public abstract Flags getPermanentFlags() throws MessagingException;

112

113

public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException;

114

public void setFlags(Message[] msgs, Flags flag, boolean value) throws MessagingException;

115

public void setFlags(int start, int end, Flags flag, boolean value) throws MessagingException;

116

public void setFlags(int[] msgnums, Flags flag, boolean value) throws MessagingException;

117

}

118

```

119

120

### Usage Examples

121

122

```java

123

folder.open(Folder.READ_ONLY);

124

125

// Get message counts

126

int totalMessages = folder.getMessageCount();

127

int newMessages = folder.getNewMessageCount();

128

int unreadMessages = folder.getUnreadMessageCount();

129

130

System.out.println("Total: " + totalMessages + ", New: " + newMessages + ", Unread: " + unreadMessages);

131

132

// Get all messages

133

Message[] messages = folder.getMessages();

134

135

// Get recent messages (last 10)

136

int count = folder.getMessageCount();

137

Message[] recent = folder.getMessages(Math.max(1, count - 9), count);

138

139

// Mark messages as read

140

folder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);

141

```

142

143

## Message Storage Operations

144

145

### Adding Messages

146

147

```java { .api }

148

abstract class Folder {

149

public abstract void appendMessages(Message[] msgs) throws MessagingException;

150

151

public void copyMessages(Message[] msgs, Folder folder) throws MessagingException;

152

}

153

```

154

155

### Message Deletion

156

157

```java { .api }

158

abstract class Folder {

159

public abstract Message[] expunge() throws MessagingException;

160

public Message[] expunge(Message[] msgs) throws MessagingException;

161

}

162

```

163

164

### Usage Examples

165

166

```java

167

// Append new messages to folder

168

Message[] newMessages = createMessages(); // Your message creation logic

169

folder.appendMessages(newMessages);

170

171

// Copy messages to another folder

172

Folder sentFolder = store.getFolder("Sent");

173

sentFolder.open(Folder.READ_WRITE);

174

folder.copyMessages(messages, sentFolder);

175

176

// Delete messages (mark as deleted, then expunge)

177

folder.setFlags(messages, new Flags(Flags.Flag.DELETED), true);

178

Message[] expunged = folder.expunge(); // Permanently removes deleted messages

179

```

180

181

## UID Support

182

183

The UIDFolder interface provides support for message UIDs (Unique Identifiers).

184

185

```java { .api }

186

interface UIDFolder {

187

public long getUID(Message message) throws MessagingException;

188

public Message getMessageByUID(long uid) throws MessagingException;

189

public Message[] getMessagesByUID(long start, long end) throws MessagingException;

190

public Message[] getMessagesByUID(long[] uids) throws MessagingException;

191

192

public long getUIDValidity() throws MessagingException;

193

public long getUIDNext() throws MessagingException;

194

195

static class FetchProfileItem extends FetchProfile.Item {

196

static final FetchProfileItem UID;

197

}

198

}

199

```

200

201

### UID Usage Example

202

203

```java

204

if (folder instanceof UIDFolder) {

205

UIDFolder uidFolder = (UIDFolder) folder;

206

207

// Get UID for a message

208

long uid = uidFolder.getUID(message);

209

210

// Retrieve message by UID

211

Message msgByUID = uidFolder.getMessageByUID(uid);

212

213

// Get UID validity (changes when folder is recreated)

214

long uidValidity = uidFolder.getUIDValidity();

215

216

// Get messages by UID range

217

Message[] msgs = uidFolder.getMessagesByUID(100L, 200L);

218

}

219

```

220

221

## Quota Management

222

223

The Quota class provides support for storage quotas on folders and stores.

224

225

```java { .api }

226

class Quota {

227

public String quotaRoot;

228

public Resource[] resources;

229

230

public Quota(String quotaRoot);

231

232

static class Resource {

233

public String name;

234

public long usage;

235

public long limit;

236

237

public Resource(String name, long usage, long limit);

238

}

239

}

240

241

interface QuotaAwareStore {

242

public Quota[] getQuota(String quotaRoot) throws MessagingException;

243

public void setQuota(Quota quota) throws MessagingException;

244

}

245

```

246

247

### Quota Usage Example

248

249

```java

250

if (store instanceof QuotaAwareStore) {

251

QuotaAwareStore quotaStore = (QuotaAwareStore) store;

252

253

// Get quota information

254

Quota[] quotas = quotaStore.getQuota("INBOX");

255

for (Quota quota : quotas) {

256

for (Quota.Resource resource : quota.resources) {

257

System.out.println("Resource: " + resource.name);

258

System.out.println("Usage: " + resource.usage + "/" + resource.limit);

259

}

260

}

261

}

262

```

263

264

## Message Searching in Folders

265

266

### Search Operations

267

268

```java { .api }

269

abstract class Folder {

270

public abstract Message[] search(SearchTerm term) throws MessagingException;

271

public abstract Message[] search(SearchTerm term, Message[] msgs) throws MessagingException;

272

}

273

```

274

275

### Search Examples

276

277

```java

278

// Search for messages from specific sender

279

SearchTerm fromTerm = new FromStringTerm("john@example.com");

280

Message[] fromJohn = folder.search(fromTerm);

281

282

// Search for unread messages with specific subject

283

SearchTerm unreadTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), false);

284

SearchTerm subjectTerm = new SubjectTerm("Important");

285

SearchTerm combinedTerm = new AndTerm(unreadTerm, subjectTerm);

286

Message[] results = folder.search(combinedTerm);

287

288

// Search within a subset of messages

289

Message[] recentMessages = folder.getMessages(100, 200);

290

Message[] filteredResults = folder.search(fromTerm, recentMessages);

291

```

292

293

## Store Implementation

294

295

The Store class provides access to message stores and folder hierarchies.

296

297

### Store Connection and Access

298

299

```java { .api }

300

abstract class Store extends Service {

301

public abstract Folder getDefaultFolder() throws MessagingException;

302

public abstract Folder getFolder(String name) throws MessagingException;

303

public abstract Folder getFolder(URLName url) throws MessagingException;

304

}

305

```

306

307

### Namespace Support

308

309

```java { .api }

310

abstract class Store {

311

public Folder[] getPersonalNamespaces() throws MessagingException;

312

public Folder[] getUserNamespaces(String user) throws MessagingException;

313

public Folder[] getSharedNamespaces() throws MessagingException;

314

}

315

```

316

317

### Store Events

318

319

```java { .api }

320

abstract class Store {

321

public void addStoreListener(StoreListener l);

322

public void removeStoreListener(StoreListener l);

323

public void addFolderListener(FolderListener l);

324

public void removeFolderListener(FolderListener l);

325

}

326

```

327

328

### Store Usage Example

329

330

```java

331

Store store = session.getStore("imap");

332

store.connect();

333

334

// Get namespace folders

335

Folder[] personal = store.getPersonalNamespaces();

336

Folder[] shared = store.getSharedNamespaces();

337

338

System.out.println("Personal folders:");

339

for (Folder f : personal) {

340

listFolderHierarchy(f, 0);

341

}

342

343

System.out.println("Shared folders:");

344

for (Folder f : shared) {

345

listFolderHierarchy(f, 0);

346

}

347

348

store.close();

349

350

// Helper method for recursive folder listing

351

private void listFolderHierarchy(Folder folder, int depth) throws MessagingException {

352

String indent = " ".repeat(depth);

353

System.out.println(indent + folder.getName() + " (" + folder.getMessageCount() + " messages)");

354

355

if ((folder.getType() & Folder.HOLDS_FOLDERS) != 0) {

356

Folder[] subfolders = folder.list();

357

for (Folder subfolder : subfolders) {

358

listFolderHierarchy(subfolder, depth + 1);

359

}

360

}

361

}

362

```

363

364

## Fetch Profiles

365

366

The FetchProfile class optimizes message retrieval by specifying which data to prefetch.

367

368

```java { .api }

369

class FetchProfile {

370

public FetchProfile();

371

372

public void add(Item item);

373

public void add(String headerName);

374

public boolean contains(Item item);

375

public boolean contains(String headerName);

376

377

public Item[] getItems();

378

public String[] getHeaderNames();

379

380

static class Item {

381

static final Item ENVELOPE;

382

static final Item CONTENT_INFO;

383

static final Item FLAGS;

384

static final Item SIZE;

385

386

protected Item(String name);

387

}

388

}

389

```

390

391

### Fetch Profile Usage

392

393

```java

394

// Create fetch profile for efficient access

395

FetchProfile fp = new FetchProfile();

396

fp.add(FetchProfile.Item.ENVELOPE); // From, To, Subject, Date

397

fp.add(FetchProfile.Item.FLAGS); // Message flags

398

fp.add("X-Priority"); // Custom header

399

400

// Fetch data efficiently

401

Message[] messages = folder.getMessages();

402

folder.fetch(messages, fp);

403

404

// Access prefetched data

405

for (Message msg : messages) {

406

// These accesses are now efficient (data already fetched)

407

System.out.println("From: " + msg.getFrom()[0]);

408

System.out.println("Subject: " + msg.getSubject());

409

System.out.println("Seen: " + msg.isSet(Flags.Flag.SEEN));

410

}

411

```

412

413

## Advanced Folder Operations

414

415

### Subscription Management

416

417

```java { .api }

418

abstract class Folder {

419

public void setSubscribed(boolean subscribe) throws MessagingException;

420

public boolean isSubscribed() throws MessagingException;

421

}

422

```

423

424

### Access Rights

425

426

```java { .api }

427

interface Rights {

428

public Right[] getRights();

429

430

static class Right {

431

static final Right LOOKUP; // 'l' - Lookup/visible

432

static final Right READ; // 'r' - Read

433

static final Right KEEP_SEEN; // 's' - Keep \Seen flag

434

static final Right WRITE; // 'w' - Write/flag except \Seen

435

static final Right INSERT; // 'i' - Insert/copy messages

436

static final Right POST; // 'p' - Post messages

437

static final Right CREATE; // 'c' - Create subfolders

438

static final Right DELETE; // 'd' - Delete messages

439

static final Right ADMINISTER;// 'a' - Administer rights

440

}

441

}

442

443

interface ACL {

444

public void addRights(ACL.Rights rights) throws MessagingException;

445

public void removeRights(ACL.Rights rights) throws MessagingException;

446

public void setRights(ACL.Rights rights) throws MessagingException;

447

public ACL.Rights[] listRights(String name) throws MessagingException;

448

public ACL.Rights myRights(String name) throws MessagingException;

449

}

450

```

451

452

## Exception Classes

453

454

```java { .api }

455

class FolderClosedException extends MessagingException {

456

public FolderClosedException(Folder folder);

457

public FolderClosedException(Folder folder, String message);

458

459

public Folder getFolder();

460

}

461

462

class FolderNotFoundException extends MessagingException {

463

public FolderNotFoundException();

464

public FolderNotFoundException(String s);

465

public FolderNotFoundException(Folder f);

466

public FolderNotFoundException(String s, Folder f);

467

468

public Folder getFolder();

469

}

470

471

class ReadOnlyFolderException extends MessagingException {

472

public ReadOnlyFolderException(Folder folder);

473

public ReadOnlyFolderException(Folder folder, String message);

474

475

public Folder getFolder();

476

}

477

478

class StoreClosedException extends MessagingException {

479

public StoreClosedException(Store store);

480

public StoreClosedException(Store store, String message);

481

482

public Store getStore();

483

}

484

485

class MessageRemovedException extends MessagingException {

486

public MessageRemovedException();

487

public MessageRemovedException(String s);

488

}

489

```

490

491

### Error Handling Example

492

493

```java

494

try {

495

folder.open(Folder.READ_WRITE);

496

Message[] messages = folder.getMessages();

497

498

for (Message msg : messages) {

499

try {

500

System.out.println("Subject: " + msg.getSubject());

501

} catch (MessageRemovedException e) {

502

System.out.println("Message was expunged: " + e.getMessage());

503

continue;

504

}

505

}

506

507

folder.close();

508

} catch (FolderNotFoundException e) {

509

System.err.println("Folder not found: " + e.getFolder().getFullName());

510

} catch (ReadOnlyFolderException e) {

511

System.err.println("Folder is read-only: " + e.getFolder().getName());

512

} catch (FolderClosedException e) {

513

System.err.println("Folder was closed: " + e.getFolder().getName());

514

} catch (StoreClosedException e) {

515

System.err.println("Store connection closed: " + e.getStore().getURLName());

516

}

517

```

518

519

## Complete Example: Folder Management

520

521

```java

522

public class FolderOperationsExample {

523

524

public void manageFolders(Session session) throws MessagingException {

525

Store store = session.getStore("imap");

526

store.connect("imap.example.com", "username", "password");

527

528

try {

529

// Create organizational folders

530

createFolderStructure(store);

531

532

// Process messages in INBOX

533

processInbox(store);

534

535

// Archive old messages

536

archiveOldMessages(store);

537

538

} finally {

539

store.close();

540

}

541

}

542

543

private void createFolderStructure(Store store) throws MessagingException {

544

String[] folderNames = {"Archive", "Projects", "Personal"};

545

546

for (String name : folderNames) {

547

Folder folder = store.getFolder(name);

548

if (!folder.exists()) {

549

boolean created = folder.create(Folder.HOLDS_MESSAGES | Folder.HOLDS_FOLDERS);

550

System.out.println("Created folder '" + name + "': " + created);

551

}

552

}

553

}

554

555

private void processInbox(Store store) throws MessagingException {

556

Folder inbox = store.getFolder("INBOX");

557

inbox.open(Folder.READ_WRITE);

558

559

try {

560

Message[] messages = inbox.getMessages();

561

System.out.println("Processing " + messages.length + " messages");

562

563

// Use fetch profile for efficiency

564

FetchProfile fp = new FetchProfile();

565

fp.add(FetchProfile.Item.ENVELOPE);

566

fp.add(FetchProfile.Item.FLAGS);

567

inbox.fetch(messages, fp);

568

569

for (Message msg : messages) {

570

processMessage(msg, store);

571

}

572

573

} finally {

574

inbox.close(false);

575

}

576

}

577

578

private void processMessage(Message message, Store store) throws MessagingException {

579

// Example: Move project-related emails to Projects folder

580

String subject = message.getSubject();

581

if (subject != null && subject.toLowerCase().contains("project")) {

582

Folder projectsFolder = store.getFolder("Projects");

583

projectsFolder.open(Folder.READ_WRITE);

584

585

try {

586

Message[] msgs = {message};

587

message.getFolder().copyMessages(msgs, projectsFolder);

588

message.setFlag(Flags.Flag.DELETED, true);

589

} finally {

590

projectsFolder.close(false);

591

}

592

}

593

}

594

595

private void archiveOldMessages(Store store) throws MessagingException {

596

Calendar cal = Calendar.getInstance();

597

cal.add(Calendar.MONTH, -6); // 6 months ago

598

Date cutoffDate = cal.getTime();

599

600

// Search for old messages

601

SearchTerm oldTerm = new ReceivedDateTerm(ComparisonTerm.LT, cutoffDate);

602

603

Folder inbox = store.getFolder("INBOX");

604

inbox.open(Folder.READ_WRITE);

605

606

try {

607

Message[] oldMessages = inbox.search(oldTerm);

608

if (oldMessages.length > 0) {

609

Folder archiveFolder = store.getFolder("Archive");

610

archiveFolder.open(Folder.READ_WRITE);

611

612

try {

613

inbox.copyMessages(oldMessages, archiveFolder);

614

inbox.setFlags(oldMessages, new Flags(Flags.Flag.DELETED), true);

615

inbox.expunge();

616

617

System.out.println("Archived " + oldMessages.length + " old messages");

618

} finally {

619

archiveFolder.close(false);

620

}

621

}

622

} finally {

623

inbox.close(false);

624

}

625

}

626

}

627

```