A heroic IMAP (Internet Message Access Protocol) client for Deno.
- Full IMAP protocol support
- TLS/SSL support
- Authentication (PLAIN, LOGIN)
- Mailbox management (list, create, delete, rename)
- Message operations (search, fetch, move, copy, delete)
- Flag management (mark as read/unread, flag/unflag)
- Comprehensive TypeScript types
- Promise-based API
- Utility functions for common operations
You can import the module directly from the JSR registry:
import { ImapClient } from 'jsr:@workingdevshero/deno-imap';Or import it from GitHub:
import { ImapClient } from 'https://raw.githubusercontent.com/workingdevshero/deno-imap/main/mod.ts';import { ImapClient } from 'jsr:@workingdevshero/deno-imap';
// Create a new IMAP client
const client = new ImapClient({
host: 'imap.example.com',
port: 993,
tls: true,
username: 'user@example.com',
password: 'password',
});
// Connect and authenticate
await client.connect();
await client.authenticate();
// List mailboxes
const mailboxes = await client.listMailboxes();
console.log('Available mailboxes:', mailboxes);
// Select a mailbox
const inbox = await client.selectMailbox('INBOX');
console.log('INBOX has', inbox.exists, 'messages');
// Search for unread messages
const unreadMessages = await client.search({ flags: { has: ['\\Unseen'] } });
console.log('Unread message IDs:', unreadMessages);
// Fetch messages (safely handling mailboxes with fewer than 10 messages)
const messageCount = inbox.exists || 0;
const fetchRange = messageCount > 0 ? `1:${Math.min(messageCount, 10)}` : '1';
const messages = await client.fetch(fetchRange, {
envelope: true,
headers: ['Subject', 'From', 'Date'],
});
// Display message details
for (const message of messages) {
console.log('Message #', message.seq);
console.log('Subject:', message.envelope?.subject);
console.log(
'From:',
message.envelope?.from?.[0]?.mailbox + '@' + message.envelope?.from?.[0]?.host,
);
console.log('Date:', message.envelope?.date);
}
// Disconnect
client.disconnect();For security and flexibility, you can store your IMAP connection details in environment variables:
const client = new ImapClient({
host: Deno.env.get('IMAP_HOST')!,
port: parseInt(Deno.env.get('IMAP_PORT')!),
tls: Deno.env.get('IMAP_USE_TLS') !== 'false',
username: Deno.env.get('IMAP_USERNAME')!,
password: Deno.env.get('IMAP_PASSWORD')!,
});Create a .env file with your connection details:
IMAP_HOST="imap.example.com"
IMAP_PORT=993
IMAP_USERNAME="user@example.com"
IMAP_PASSWORD="your_password_here"
IMAP_USE_TLS="true"
Then run your script with the --env-file flag:
deno run --allow-net --allow-env --env-file=.env your_script.tsThe package includes utility functions for common operations:
import {
decodeAttachment,
deleteMessages,
fetchMessagesFromSender,
fetchUnreadMessages,
hasAttachments,
ImapClient,
markMessagesAsRead,
} from 'jsr:@workingdevshero/deno-imap';
const client = new ImapClient({
host: 'imap.example.com',
port: 993,
tls: true,
username: 'user@example.com',
password: 'password',
});
await client.connect();
await client.authenticate();
// Fetch unread messages
const unreadMessages = await fetchUnreadMessages(client, 'INBOX');
// Fetch messages from a specific sender
const messagesFromSender = await fetchMessagesFromSender(
client,
'INBOX',
'sender@example.com',
);
// Check if a message has attachments
for (const message of unreadMessages) {
if (message.bodyStructure && hasAttachments(message.bodyStructure)) {
console.log(`Message #${message.seq} has attachments`);
}
}
// Mark messages as read using UIDs (more reliable than sequence numbers)
await markMessagesAsRead(
client,
'INBOX',
messagesFromSender.map((msg) => msg.uid || 0).filter((uid) => uid > 0),
true, // Use UIDs instead of sequence numbers
);
// Delete messages
await deleteMessages(
client,
'INBOX',
unreadMessages.slice(0, 5).map((msg) => msg.uid || 0).filter((uid) => uid > 0),
true, // Use UIDs instead of sequence numbers
);
client.disconnect();The main class for interacting with IMAP servers.
new ImapClient(options: ImapOptions)host: IMAP server hostnameport: IMAP server porttls: Whether to use TLS (default: true)username: Username for authenticationpassword: Password for authenticationauthMechanism: Authentication mechanism to use (default: "PLAIN")autoReconnect: Whether to automatically reconnect on connection loss (default: true)maxReconnectAttempts: Maximum number of reconnection attempts (default: 3)reconnectDelay: Delay between reconnection attempts in milliseconds (default: 1000)commandTimeout: Timeout for commands in milliseconds (default: 30000)connectionTimeout: Connection timeout in milliseconds (default: 30000)socketTimeout: Socket timeout in milliseconds (default: 60000)tlsOptions: TLS options
connect(): Connects to the IMAP serverdisconnect(): Disconnects from the IMAP serverauthenticate(mechanism?: ImapAuthMechanism): Authenticates with the IMAP serverlistMailboxes(reference?: string, mailbox?: string): Lists mailboxesgetMailboxStatus(mailbox: string, items?: string[]): Gets the status of a mailboxselectMailbox(mailbox: string): Selects a mailboxexamineMailbox(mailbox: string): Examines a mailbox (read-only mode)closeMailbox(): Closes the currently selected mailboxcreateMailbox(mailbox: string): Creates a new mailboxdeleteMailbox(mailbox: string): Deletes a mailboxrenameMailbox(oldName: string, newName: string): Renames a mailboxsubscribeMailbox(mailbox: string): Subscribes to a mailboxunsubscribeMailbox(mailbox: string): Unsubscribes from a mailboxsearch(criteria: ImapSearchCriteria, charset?: string): Searches for messagesfetch(sequence: string, options: ImapFetchOptions): Fetches messagessetFlags(sequence: string, flags: string[], action?: "set" | "add" | "remove", useUid?: boolean): Sets flags on messagescopyMessages(sequence: string, mailbox: string, useUid?: boolean): Copies messages to another mailboxmoveMessages(sequence: string, mailbox: string, useUid?: boolean): Moves messages to another mailboxexpunge(): Expunges deleted messagesappendMessage(mailbox: string, message: string, flags?: string[], date?: Date): Appends a message to a mailboxforceReconnect(): Forces a reconnection to the serverupdateCapabilities(): Updates the server capabilities
connected: Whether the client is connectedauthenticated: Whether the client is authenticatedcapabilities: Server capabilitiesselectedMailbox: Currently selected mailboxreconnecting: Whether a reconnection is in progress
The package includes utility functions for common operations:
fetchAllMessages(client: ImapClient, mailbox: string, options?: ImapFetchOptions): Fetches all messages in a mailboxsearchAndFetchMessages(client: ImapClient, mailbox: string, criteria: ImapSearchCriteria, options?: ImapFetchOptions): Fetches messages matching search criteriafetchUnreadMessages(client: ImapClient, mailbox: string, options?: ImapFetchOptions): Fetches unread messagesfetchMessagesFromSender(client: ImapClient, mailbox: string, sender: string, options?: ImapFetchOptions): Fetches messages from a specific senderfetchMessagesWithSubject(client: ImapClient, mailbox: string, subject: string, options?: ImapFetchOptions): Fetches messages with a specific subjectfetchMessagesSince(client: ImapClient, mailbox: string, since: Date, options?: ImapFetchOptions): Fetches messages received since a specific datefetchMessagesWithAttachments(client: ImapClient, mailbox: string, options?: ImapFetchOptions): Fetches messages with attachments
markMessagesAsRead(client: ImapClient, mailbox: string, messageIds: number[], useUid?: boolean): Marks messages as readmarkMessagesAsUnread(client: ImapClient, mailbox: string, messageIds: number[], useUid?: boolean): Marks messages as unreaddeleteMessages(client: ImapClient, mailbox: string, messageIds: number[], useUid?: boolean): Deletes messagesmoveMessages(client: ImapClient, sourceMailbox: string, targetMailbox: string, messageIds: number[], useUid?: boolean): Moves messages between mailboxes
createMailboxHierarchy(client: ImapClient, path: string, delimiter?: string): Creates a mailbox hierarchygetMailboxHierarchy(client: ImapClient, reference?: string, pattern?: string): Gets the mailbox hierarchy
hasAttachments(bodyStructure: ImapBodyStructure): Determines if a message has attachmentsfindAttachments(bodyStructure: ImapBodyStructure, path?: string): Extracts detailed information about attachmentsdecodeAttachment(data: Uint8Array, encoding: string): Decodes an attachment based on its encoding
parseBodyStructure(data: string): Parses a body structure responseparseCapabilities(line: string): Parses a capability responseparseEnvelope(data: string): Parses an envelope responseparseFetch(lines: string[]): Parses a fetch responseparseListResponse(line: string): Parses a list responseparseSearch(line: string): Parses a search responseparseSelect(lines: string[]): Parses a select responseparseStatus(line: string): Parses a status response
Determines if a message has attachments based on its body structure.
hasAttachments(bodyStructure: ImapBodyStructure): booleanThis function analyzes the body structure of an email message to determine if it contains attachments. It considers the following criteria:
- Parts with explicit
ATTACHMENTdisposition - Parts with
INLINEdisposition that have a filename - Parts with content types like
APPLICATION,IMAGE,AUDIO, orVIDEO - Parts with a
NAMEparameter MESSAGE/RFC822parts without a disposition
Extracts detailed information about attachments from a message's body structure.
findAttachments(bodyStructure: ImapBodyStructure, path?: string): Array<{
filename: string;
type: string;
subtype: string;
size: number;
encoding: string;
section: string;
}>This function analyzes the body structure of an email message and returns an array of attachment objects with detailed information about each attachment, including:
filename: The name of the attachment filetype: The MIME type (e.g., "IMAGE", "APPLICATION")subtype: The MIME subtype (e.g., "PNG", "PDF")size: The size of the attachment in bytesencoding: The content transfer encoding (e.g., "BASE64", "QUOTED-PRINTABLE")section: The IMAP section path used to fetch the attachment
Decodes an attachment based on its encoding.
decodeAttachment(data: Uint8Array, encoding: string): Uint8ArrayThis function handles different encoding types:
BASE64: Converts base64 to binaryQUOTED-PRINTABLE: Decodes quoted-printable7BIT,8BIT,BINARY: Returns the data as is (no decoding needed)
The examples directory contains sample code demonstrating how to use the IMAP client:
- Basic Example: Demonstrates connecting to an IMAP server, listing mailboxes, and checking the INBOX status.
- Search Example: Shows how to search for messages using various criteria.
- Fetch Example: Demonstrates how to fetch and decode message content, including handling multipart messages and different encodings.
- Mailboxes Example: Shows how to manage mailboxes, including creating, renaming, and deleting them.
- Advanced Example: Shows more advanced features like searching, fetching message content, and manipulating messages.
- Attachments Example: Demonstrates how to find messages with attachments, fetch attachment data, properly decode it based on the encoding (BASE64, QUOTED-PRINTABLE, etc.), and save attachments to a local folder.
To run the examples, create a .env file with your IMAP server details, then run:
# Run the basic example
deno run --allow-net --allow-env --env-file=.env examples/basic.ts
# Run the search example
deno run --allow-net --allow-env --env-file=.env examples/search.ts
# Run the fetch example
deno run --allow-net --allow-env --env-file=.env examples/fetch.ts
# Run the mailboxes example
deno run --allow-net --allow-env --env-file=.env examples/mailboxes.ts
# Run the advanced example
deno run --allow-net --allow-env --env-file=.env examples/advanced.ts
# Run the attachments example
deno run --allow-net --allow-env --env-file=.env --allow-write --allow-read examples/attachments.tsMIT
