0
# Message Search and Filtering
1
2
Message search and filtering provides comprehensive capabilities for querying messages based on various criteria including content, headers, dates, flags, and addresses with support for logical operations.
3
4
## Search Foundation
5
6
The SearchTerm abstract class forms the foundation of Jakarta Mail's search system.
7
8
```java { .api }
9
public abstract class SearchTerm implements Serializable {
10
// Core search method - must be implemented by all search terms
11
public abstract boolean match(Message msg);
12
13
// Object operations
14
public boolean equals(Object obj);
15
public int hashCode();
16
}
17
```
18
19
All search operations are performed by implementing the `match()` method that tests whether a message satisfies the search criteria.
20
21
## String-Based Search Terms
22
23
### Base String Search
24
25
```java { .api }
26
public abstract class StringTerm extends SearchTerm {
27
protected String pattern;
28
protected boolean ignoreCase;
29
30
// Constructors
31
protected StringTerm(String pattern);
32
protected StringTerm(String pattern, boolean ignoreCase);
33
34
// Accessors
35
public String getPattern();
36
public boolean getIgnoreCase();
37
}
38
```
39
40
### Content Search Terms
41
42
```java { .api }
43
// Search message body content
44
public final class BodyTerm extends StringTerm {
45
public BodyTerm(String pattern);
46
public BodyTerm(String pattern, boolean ignoreCase);
47
}
48
49
// Search subject line
50
public final class SubjectTerm extends StringTerm {
51
public SubjectTerm(String pattern);
52
public SubjectTerm(String pattern, boolean ignoreCase);
53
}
54
55
// Search specific header
56
public final class HeaderTerm extends StringTerm {
57
public HeaderTerm(String headerName, String pattern);
58
public HeaderTerm(String headerName, String pattern, boolean ignoreCase);
59
60
public String getHeaderName();
61
}
62
63
// Search Message-ID header
64
public final class MessageIDTerm extends StringTerm {
65
public MessageIDTerm(String msgid);
66
}
67
```
68
69
### String Search Usage Example
70
71
```java
72
import jakarta.mail.search.*;
73
import jakarta.mail.*;
74
75
// Search for messages containing "urgent" in body (case-insensitive)
76
SearchTerm bodySearch = new BodyTerm("urgent", true);
77
Message[] urgentMessages = folder.search(bodySearch);
78
79
// Search by subject
80
SearchTerm subjectSearch = new SubjectTerm("Meeting");
81
Message[] meetingMessages = folder.search(subjectSearch);
82
83
// Search specific header
84
SearchTerm headerSearch = new HeaderTerm("X-Priority", "1");
85
Message[] highPriorityMessages = folder.search(headerSearch);
86
87
// Search by Message-ID
88
SearchTerm messageIdSearch = new MessageIDTerm("<12345@example.com>");
89
Message[] specificMessage = folder.search(messageIdSearch);
90
91
// Case-sensitive body search
92
SearchTerm caseSensitiveSearch = new BodyTerm("CONFIDENTIAL", false);
93
Message[] confidentialMessages = folder.search(caseSensitiveSearch);
94
```
95
96
## Address-Based Search Terms
97
98
### Address Object Search
99
100
```java { .api }
101
public abstract class AddressTerm extends SearchTerm {
102
protected Address address;
103
104
// Constructor
105
protected AddressTerm(Address address);
106
107
// Accessor
108
public Address getAddress();
109
}
110
111
// Search sender addresses (Address objects)
112
public final class FromTerm extends AddressTerm {
113
public FromTerm(Address address);
114
}
115
116
// Search recipient addresses (Address objects)
117
public final class RecipientTerm extends AddressTerm {
118
public RecipientTerm(Message.RecipientType type, Address address);
119
120
public Message.RecipientType getRecipientType();
121
}
122
```
123
124
### Address String Search
125
126
```java { .api }
127
public abstract class AddressStringTerm extends StringTerm {
128
// Constructor
129
protected AddressStringTerm(String pattern);
130
protected AddressStringTerm(String pattern, boolean ignoreCase);
131
}
132
133
// Search sender addresses (string pattern)
134
public final class FromStringTerm extends AddressStringTerm {
135
public FromStringTerm(String pattern);
136
public FromStringTerm(String pattern, boolean ignoreCase);
137
}
138
139
// Search recipient addresses (string pattern)
140
public final class RecipientStringTerm extends AddressStringTerm {
141
public RecipientStringTerm(Message.RecipientType type, String pattern);
142
public RecipientStringTerm(Message.RecipientType type, String pattern, boolean ignoreCase);
143
144
public Message.RecipientType getRecipientType();
145
}
146
```
147
148
### Address Search Usage Example
149
150
```java
151
import jakarta.mail.search.*;
152
import jakarta.mail.internet.*;
153
154
// Search by exact sender address
155
InternetAddress senderAddr = new InternetAddress("boss@company.com");
156
SearchTerm fromSearch = new FromTerm(senderAddr);
157
Message[] fromBoss = folder.search(fromSearch);
158
159
// Search by sender address pattern (string)
160
SearchTerm fromStringSearch = new FromStringTerm("@company.com");
161
Message[] fromCompany = folder.search(fromStringSearch);
162
163
// Search by recipient (TO addresses)
164
SearchTerm toSearch = new RecipientStringTerm(Message.RecipientType.TO, "team@company.com");
165
Message[] toTeam = folder.search(toSearch);
166
167
// Search by CC recipients
168
SearchTerm ccSearch = new RecipientStringTerm(Message.RecipientType.CC, "@department.com");
169
Message[] ccDepartment = folder.search(ccSearch);
170
171
// Case-insensitive address search
172
SearchTerm caseInsensitiveSearch = new FromStringTerm("MANAGER", true);
173
Message[] fromManager = folder.search(caseInsensitiveSearch);
174
```
175
176
## Date-Based Search Terms
177
178
### Base Date Search
179
180
```java { .api }
181
public abstract class DateTerm extends ComparisonTerm {
182
protected Date date;
183
184
// Constructor
185
protected DateTerm(int comparison, Date date);
186
187
// Accessor
188
public Date getDate();
189
}
190
```
191
192
### Date Search Terms
193
194
```java { .api }
195
// Search by received date
196
public final class ReceivedDateTerm extends DateTerm {
197
public ReceivedDateTerm(int comparison, Date date);
198
}
199
200
// Search by sent date
201
public final class SentDateTerm extends DateTerm {
202
public SentDateTerm(int comparison, Date date);
203
}
204
```
205
206
### Comparison Operators
207
208
```java { .api }
209
public abstract class ComparisonTerm extends SearchTerm {
210
// Comparison constants
211
public static final int LE = 1; // Less than or equal
212
public static final int LT = 2; // Less than
213
public static final int EQ = 3; // Equal
214
public static final int NE = 4; // Not equal
215
public static final int GT = 5; // Greater than
216
public static final int GE = 6; // Greater than or equal
217
218
protected int comparison;
219
220
// Constructor
221
protected ComparisonTerm(int comparison);
222
223
// Accessor
224
public int getComparison();
225
}
226
```
227
228
### Date Search Usage Example
229
230
```java
231
import jakarta.mail.search.*;
232
import java.util.Date;
233
import java.util.Calendar;
234
235
// Search for messages received today
236
Calendar today = Calendar.getInstance();
237
today.set(Calendar.HOUR_OF_DAY, 0);
238
today.set(Calendar.MINUTE, 0);
239
today.set(Calendar.SECOND, 0);
240
today.set(Calendar.MILLISECOND, 0);
241
242
SearchTerm todaySearch = new ReceivedDateTerm(ComparisonTerm.GE, today.getTime());
243
Message[] todayMessages = folder.search(todaySearch);
244
245
// Search for messages sent last week
246
Calendar weekAgo = Calendar.getInstance();
247
weekAgo.add(Calendar.DAY_OF_YEAR, -7);
248
SearchTerm lastWeekSearch = new SentDateTerm(ComparisonTerm.GE, weekAgo.getTime());
249
Message[] lastWeekMessages = folder.search(lastWeekSearch);
250
251
// Search for messages received between two dates
252
Calendar startDate = Calendar.getInstance();
253
startDate.add(Calendar.DAY_OF_YEAR, -30);
254
Calendar endDate = Calendar.getInstance();
255
endDate.add(Calendar.DAY_OF_YEAR, -1);
256
257
SearchTerm dateRange = new AndTerm(
258
new ReceivedDateTerm(ComparisonTerm.GE, startDate.getTime()),
259
new ReceivedDateTerm(ComparisonTerm.LE, endDate.getTime())
260
);
261
Message[] rangeMessages = folder.search(dateRange);
262
263
// Search for messages sent exactly on a specific date
264
Calendar specificDate = Calendar.getInstance();
265
specificDate.set(2024, Calendar.JANUARY, 1);
266
SearchTerm exactDateSearch = new SentDateTerm(ComparisonTerm.EQ, specificDate.getTime());
267
Message[] exactDateMessages = folder.search(exactDateSearch);
268
```
269
270
## Numeric Search Terms
271
272
### Base Numeric Search
273
274
```java { .api }
275
public abstract class IntegerComparisonTerm extends ComparisonTerm {
276
protected int number;
277
278
// Constructor
279
protected IntegerComparisonTerm(int comparison, int number);
280
281
// Accessor
282
public int getNumber();
283
}
284
```
285
286
### Numeric Search Terms
287
288
```java { .api }
289
// Search by message number
290
public final class MessageNumberTerm extends IntegerComparisonTerm {
291
public MessageNumberTerm(int number);
292
public MessageNumberTerm(int comparison, int number);
293
}
294
295
// Search by message size
296
public final class SizeTerm extends IntegerComparisonTerm {
297
public SizeTerm(int comparison, int size);
298
}
299
```
300
301
### Numeric Search Usage Example
302
303
```java
304
import jakarta.mail.search.*;
305
306
// Search for large messages (over 1MB)
307
SearchTerm largeMessages = new SizeTerm(ComparisonTerm.GT, 1024 * 1024);
308
Message[] bigMessages = folder.search(largeMessages);
309
310
// Search for small messages (under 10KB)
311
SearchTerm smallMessages = new SizeTerm(ComparisonTerm.LT, 10 * 1024);
312
Message[] tinyMessages = folder.search(smallMessages);
313
314
// Search for specific message number
315
SearchTerm messageNumber = new MessageNumberTerm(100);
316
Message[] specificNumber = folder.search(messageNumber);
317
318
// Search for messages in a range of numbers
319
SearchTerm numberRange = new AndTerm(
320
new MessageNumberTerm(ComparisonTerm.GE, 50),
321
new MessageNumberTerm(ComparisonTerm.LE, 100)
322
);
323
Message[] numberRangeMessages = folder.search(numberRange);
324
```
325
326
## Flag-Based Search Terms
327
328
### Flag Search
329
330
```java { .api }
331
public final class FlagTerm extends SearchTerm {
332
// Constructors
333
public FlagTerm(Flags flags, boolean set);
334
335
// Accessors
336
public Flags getFlags();
337
public boolean getTestSet();
338
}
339
```
340
341
### Flag Search Usage Example
342
343
```java
344
import jakarta.mail.search.*;
345
import jakarta.mail.*;
346
347
// Search for unread messages
348
Flags unreadFlags = new Flags(Flags.Flag.SEEN);
349
SearchTerm unreadSearch = new FlagTerm(unreadFlags, false);
350
Message[] unreadMessages = folder.search(unreadSearch);
351
352
// Search for flagged messages
353
Flags flaggedFlags = new Flags(Flags.Flag.FLAGGED);
354
SearchTerm flaggedSearch = new FlagTerm(flaggedFlags, true);
355
Message[] flaggedMessages = folder.search(flaggedSearch);
356
357
// Search for deleted messages
358
Flags deletedFlags = new Flags(Flags.Flag.DELETED);
359
SearchTerm deletedSearch = new FlagTerm(deletedFlags, true);
360
Message[] deletedMessages = folder.search(deletedSearch);
361
362
// Search for draft messages
363
Flags draftFlags = new Flags(Flags.Flag.DRAFT);
364
SearchTerm draftSearch = new FlagTerm(draftFlags, true);
365
Message[] draftMessages = folder.search(draftSearch);
366
367
// Search for answered messages
368
Flags answeredFlags = new Flags(Flags.Flag.ANSWERED);
369
SearchTerm answeredSearch = new FlagTerm(answeredFlags, true);
370
Message[] answeredMessages = folder.search(answeredSearch);
371
372
// Search for recent messages
373
Flags recentFlags = new Flags(Flags.Flag.RECENT);
374
SearchTerm recentSearch = new FlagTerm(recentFlags, true);
375
Message[] recentMessages = folder.search(recentSearch);
376
377
// Search for custom user flags
378
Flags customFlags = new Flags();
379
customFlags.add("Important");
380
SearchTerm customSearch = new FlagTerm(customFlags, true);
381
Message[] importantMessages = folder.search(customSearch);
382
```
383
384
## Logical Operators
385
386
### Logical AND
387
388
```java { .api }
389
public final class AndTerm extends SearchTerm {
390
// Constructors
391
public AndTerm(SearchTerm t1, SearchTerm t2);
392
public AndTerm(SearchTerm[] terms);
393
394
// Accessor
395
public SearchTerm[] getTerms();
396
}
397
```
398
399
### Logical OR
400
401
```java { .api }
402
public final class OrTerm extends SearchTerm {
403
// Constructors
404
public OrTerm(SearchTerm t1, SearchTerm t2);
405
public OrTerm(SearchTerm[] terms);
406
407
// Accessor
408
public SearchTerm[] getTerms();
409
}
410
```
411
412
### Logical NOT
413
414
```java { .api }
415
public final class NotTerm extends SearchTerm {
416
// Constructor
417
public NotTerm(SearchTerm t);
418
419
// Accessor
420
public SearchTerm getTerm();
421
}
422
```
423
424
### Logical Operators Usage Example
425
426
```java
427
import jakarta.mail.search.*;
428
429
// Complex search: Unread messages from specific sender
430
SearchTerm complexSearch = new AndTerm(
431
new FlagTerm(new Flags(Flags.Flag.SEEN), false),
432
new FromStringTerm("important@company.com")
433
);
434
Message[] unreadFromImportant = folder.search(complexSearch);
435
436
// Multiple AND conditions
437
SearchTerm multipleAnd = new AndTerm(new SearchTerm[] {
438
new SubjectTerm("Meeting"),
439
new FromStringTerm("@company.com"),
440
new ReceivedDateTerm(ComparisonTerm.GE, weekAgo.getTime())
441
});
442
Message[] complexResults = folder.search(multipleAnd);
443
444
// OR search: Messages from multiple senders
445
SearchTerm multiSenderSearch = new OrTerm(
446
new FromStringTerm("boss@company.com"),
447
new FromStringTerm("manager@company.com")
448
);
449
Message[] fromBossOrManager = folder.search(multiSenderSearch);
450
451
// NOT search: Messages not from specific domain
452
SearchTerm notFromSpam = new NotTerm(
453
new FromStringTerm("@spam.com")
454
);
455
Message[] nonSpamMessages = folder.search(notFromSpam);
456
457
// Complex nested logic: (urgent OR important) AND not read AND from company
458
SearchTerm urgentOrImportant = new OrTerm(
459
new SubjectTerm("urgent"),
460
new SubjectTerm("important")
461
);
462
463
SearchTerm unreadAndFromCompany = new AndTerm(
464
new FlagTerm(new Flags(Flags.Flag.SEEN), false),
465
new FromStringTerm("@company.com")
466
);
467
468
SearchTerm finalSearch = new AndTerm(urgentOrImportant, unreadAndFromCompany);
469
Message[] complexNestedResults = folder.search(finalSearch);
470
```
471
472
## Advanced Search Patterns
473
474
### Time Range Searches
475
476
```java
477
// Messages from last 24 hours
478
Calendar yesterday = Calendar.getInstance();
479
yesterday.add(Calendar.DAY_OF_YEAR, -1);
480
SearchTerm last24Hours = new ReceivedDateTerm(ComparisonTerm.GE, yesterday.getTime());
481
482
// Messages from this month
483
Calendar startOfMonth = Calendar.getInstance();
484
startOfMonth.set(Calendar.DAY_OF_MONTH, 1);
485
startOfMonth.set(Calendar.HOUR_OF_DAY, 0);
486
startOfMonth.set(Calendar.MINUTE, 0);
487
startOfMonth.set(Calendar.SECOND, 0);
488
SearchTerm thisMonth = new ReceivedDateTerm(ComparisonTerm.GE, startOfMonth.getTime());
489
490
// Messages older than 30 days
491
Calendar thirtyDaysAgo = Calendar.getInstance();
492
thirtyDaysAgo.add(Calendar.DAY_OF_YEAR, -30);
493
SearchTerm oldMessages = new ReceivedDateTerm(ComparisonTerm.LT, thirtyDaysAgo.getTime());
494
```
495
496
### Content and Metadata Searches
497
498
```java
499
// High priority messages
500
SearchTerm highPriority = new OrTerm(new SearchTerm[] {
501
new HeaderTerm("X-Priority", "1"),
502
new HeaderTerm("Priority", "urgent"),
503
new SubjectTerm("URGENT"),
504
new SubjectTerm("IMPORTANT")
505
});
506
507
// Attachment searches (size-based heuristic)
508
SearchTerm hasAttachments = new SizeTerm(ComparisonTerm.GT, 50 * 1024); // > 50KB
509
510
// Meeting-related messages
511
SearchTerm meetingMessages = new OrTerm(new SearchTerm[] {
512
new SubjectTerm("meeting"),
513
new SubjectTerm("conference"),
514
new SubjectTerm("call"),
515
new BodyTerm("calendar")
516
});
517
```
518
519
### Mailbox Management Searches
520
521
```java
522
// Messages to clean up (old, read, not flagged)
523
SearchTerm cleanupCandidates = new AndTerm(new SearchTerm[] {
524
new ReceivedDateTerm(ComparisonTerm.LT, thirtyDaysAgo.getTime()),
525
new FlagTerm(new Flags(Flags.Flag.SEEN), true),
526
new FlagTerm(new Flags(Flags.Flag.FLAGGED), false)
527
});
528
529
// Important messages to preserve
530
SearchTerm importantToKeep = new OrTerm(new SearchTerm[] {
531
new FlagTerm(new Flags(Flags.Flag.FLAGGED), true),
532
new SubjectTerm("contract"),
533
new SubjectTerm("invoice"),
534
new FromStringTerm("legal@")
535
});
536
537
// Spam-like messages
538
SearchTerm potentialSpam = new OrTerm(new SearchTerm[] {
539
new SubjectTerm("free"),
540
new SubjectTerm("urgent action required"),
541
new BodyTerm("click here"),
542
new FromStringTerm("noreply@")
543
});
544
```
545
546
## Search Performance Optimization
547
548
### Using Search with Fetch Profiles
549
550
```java
551
// Optimize search performance with fetch profiles
552
FetchProfile fetchProfile = new FetchProfile();
553
fetchProfile.add(FetchProfile.Item.ENVELOPE);
554
fetchProfile.add(FetchProfile.Item.FLAGS);
555
556
// Perform search
557
Message[] results = folder.search(searchTerm);
558
559
// Fetch needed data in bulk
560
folder.fetch(results, fetchProfile);
561
562
// Now access is optimized
563
for (Message message : results) {
564
// These accesses are now efficient
565
System.out.println("From: " + Arrays.toString(message.getFrom()));
566
System.out.println("Subject: " + message.getSubject());
567
System.out.println("Flags: " + message.getFlags());
568
}
569
```
570
571
### Search on Subsets
572
573
```java
574
// Search within a specific range first
575
Message[] recentMessages = folder.getMessages(folder.getMessageCount() - 100, folder.getMessageCount());
576
577
// Then search within that subset
578
Message[] searchResults = folder.search(searchTerm, recentMessages);
579
```
580
581
## Search Exception Handling
582
583
```java { .api }
584
public class SearchException extends MessagingException {
585
public SearchException();
586
public SearchException(String message);
587
public SearchException(String message, Exception e);
588
}
589
```
590
591
### Search Error Handling Example
592
593
```java
594
try {
595
Message[] results = folder.search(complexSearchTerm);
596
System.out.println("Found " + results.length + " messages");
597
} catch (SearchException e) {
598
System.err.println("Search failed: " + e.getMessage());
599
// Fallback to simpler search or manual filtering
600
} catch (MessagingException e) {
601
System.err.println("Messaging error during search: " + e.getMessage());
602
}
603
```