Performance Tips for Using Extended MAPI in Delphi Projects
1. Minimize MAPI session and object creation
- Reuse sessions: Open a single MAPI session per application/process and reuse it rather than repeatedly logging on/off.
- Cache objects: Keep frequently used objects (IMAPISession, IMessage, IMAPIFolder) alive while needed; release promptly when done.
2. Batch operations and reduce round-trips
- Use batch property reads/writes: Retrieve or set multiple properties with single calls (GetProps/SetProps) instead of many individual calls.
- Bulk message operations: Use SaveChanges, CopyMessages, MoveMessages on multiple items when supported to avoid per-message calls.
3. Limit property retrieval
- Request only needed props: Use property tags (SPropTagArray) to fetch minimal necessary fields; avoid PR_BODY or PR_RTF_COMPRESSED unless required.
- Use Table restrictions and columns: When enumerating folders/messages, restrict rows and request only columns you need via IMAPITable.
4. Use efficient message access patterns
- Use streaming for large content: Read attachments and large bodies via streams (OpenProperty + IMAPIStream) to avoid loading entire content into memory.
- Avoid repeated full-body reads: Cache downloaded content if reused; prefer PR_BODY_HTML over PR_BODY when only HTML is needed.
5. Optimize searches and filters
- Server-side restrictions: Apply Restrict on IMAPITable to let the server filter rows, reducing client processing.
- Use FindRow/Seek when possible: For indexed searches, use efficient table navigation methods rather than full scans.
6. Handle threads and concurrency carefully
- Single-thread COM apartment: MAPI is STA-based; run MAPI calls from the main thread or ensure proper COM apartment management.
- Serialize MAPI access: Protect shared MAPI objects with synchronization (e.g., critical sections) instead of concurrent calls that can cause stalls or corruption.
7. Proper memory and resource management
- Free MAPI memory correctly: Use MAPIFreeBuffer for buffers returned by MAPI functions and Release for COM-style interfaces.
- Avoid leaks: Track allocated SPropVals and streams; always call FreeProws/FreeBuffer as appropriate.
8. Use appropriate flags and options
- Use MAPI_DEFERRED_ERRORS: When performing bulk operations, defer error handling to improve throughput if acceptable.
- Use MAPI_SUPPRESS_ATTACHMENTS or similar flags when you don’t need attachment data.
9. Monitor and profile
- Measure hotspots: Profile MAPI calls in your app to find slow operations (e.g., repeated GetProps).
- Log timing for key calls: Track durations for session creation, folder enumeration, message fetch, and large transfers.
10. Stay compatible with provider limits
- Respect server limits and throttling: Some Exchange providers limit per-call sizes or rate; design backoff/retry and chunking.
- Test with target environment: Performance varies between local PST stores, Exchange on-prem, and Exchange Online.
Quick checklist
- Reuse sessions and objects
- Batch property operations and limit retrieved properties
- Use server-side filtering and table columns
- Stream large content, avoid full loads
- Serialize MAPI access and manage COM apartments
- Free MAPI buffers and release interfaces promptly
- Profile and adapt to server limits
Date: February 8, 2026
Leave a Reply