ImapFlow

imapflow~ ImapFlow

IMAP client class for accessing IMAP mailboxes

Constructor

new ImapFlow(options)

Parameters:
Name Type Description
options Object

IMAP connection options

Properties
Name Type Attributes Default Description
host String

Hostname of the IMAP server

port Number

Port number for the IMAP server

secure Boolean <optional>
false

Should the connection be established over TLS. If false then connection is upgraded to TLS using STARTTLS extension before authentication

servername String <optional>

Servername for SNI (or when host is set to an IP address)

disableCompression Boolean <optional>
false

if true then client does not try to use COMPRESS=DEFLATE extension

auth Object

Authentication options. Authentication is requested automatically during connect()

Properties
Name Type Attributes Description
user String

Usename

pass String <optional>

Password, if using regular authentication

accessToken String <optional>

OAuth2 Access Token, if using OAuth2 authentication

clientInfo IdInfoObject <optional>

Client identification info

disableAutoIdle Boolean <optional>
false

if true then IDLE is not started automatically. Useful if you only need to perform specific tasks over the connection

tls Object <optional>

Additional TLS options (see Node.js TLS connect for all available options)

Properties
Name Type Attributes Default Description
rejectUnauthorized Boolean <optional>
true

if false then client accepts self-signed and expired certificates from the server

minVersion String <optional>
TLSv1.2

To improvde security you might need to use something newer, eg 'TLSv1.2'

minDHSize Number <optional>
1024

Minimum size of the DH parameter in bits to accept a TLS connection

logger Object <optional>

Custom logger instance with debug(obj), info(obj), warn(obj) and error(obj) methods. If not provided then ImapFlow logs to console using pino format. Can be disabled by setting to false

logRaw Boolean <optional>
false

If true then log data read from and written to socket encoded in base64

emitLogs Boolean <optional>
false

If true then in addition of sending data to logger, ImapFlow emits 'log' events with the same data

verifyOnly Boolean <optional>
false

If true then logs out automatically after successful authentication

proxy String <optional>

Optional proxy URL. Supports HTTP CONNECT (http://, https://) and SOCKS (socks://, socks4://, socks5://) proxies

qresync Boolean <optional>
false

If true, then enables QRESYNC support. EXPUNGE notifications will include uid property instead of seq

maxIdleTime Number <optional>

If set, then breaks and restarts IDLE every maxIdleTime ms

missingIdleCommand String <optional>
"NOOP"

Which command to use if server does not support IDLE

disableBinary Boolean <optional>
false

If true, then ignores the BINARY extension when making FETCH and APPEND calls

disableAutoEnable Boolean <optional>

Do not enable supported extensions by default

connectionTimeout Number <optional>
90000

how many milliseconds to wait for the connection to establish (default is 90 seconds)

greetingTimeout Number <optional>
16000

how many milliseconds to wait for the greeting after connection is established (default is 16 seconds)

socketTimeout Number <optional>
300000

how many milliseconds of inactivity to allow (default is 5 minutes)

Extends

  • EventEmitter

Members

authenticated :String|Boolean

Currently authenticated user or false if mailbox is not open or true if connection was authenticated by PREAUTH

capabilities :Map.<string, (boolean|number)>

Active IMAP capabilities. Value is either true for togglabe capabilities (eg. UIDPLUS) or a number for capabilities with a value (eg. APPENDLIMIT)

emitLogs :Boolean

If true then in addition of sending data to logger, ImapFlow emits 'log' events with the same data

enabled :Set.<string>

Enabled capabilities. Usually CONDSTORE and UTF8=ACCEPT if server supports these.

id :String

Instance ID for logs

idling :Boolean

Is current mailbox idling (true) or not (false)

mailbox :MailboxObject|Boolean

Currently selected mailbox or false if mailbox is not open

secureConnection :Boolean

Is the connection currently encrypted or not

serverInfo :IdInfoObject|null

Server identification info. Available after successful connect(). If server does not provide identification info then this value is null.

Example
await client.connect();
console.log(client.serverInfo.vendor);

usable :Boolean

Is the connection currently usable or not

version

Current module version as a static class property

Properties:
Name Type Description
version String

Module version

Methods

(async) append(path, content, flagsopt, idateopt) → {Promise.<AppendResponseObject>}

Appends a new message to a mailbox

Parameters:
Name Type Attributes Default Description
path String

Mailbox path to upload the message to (unicode string)

content string | Buffer

RFC822 formatted email message

flags Array.<string> <optional>

an array of flags to be set for the uploaded message

idate Date | string <optional>
now

internal date to be set for the message

Example
await client.append('INBOX', rawMessageBuffer, ['\\Seen'], new Date(2000, 1, 1));

close()

Closes TCP connection without notifying the server.

Example
let client = new ImapFlow({...});
await client.connect();
...
client.close();

(async) connect() → {Promise.<void>}

Initiates a connection against IMAP server. Throws if anything goes wrong. This is something you have to call before you can run any IMAP commands

Throws:

Will throw an error if connection or authentication fails

Example
let client = new ImapFlow({...});
await client.connect();

(async) download(range, partopt, optionsopt) → {Promise.<DownloadObject>}

Download either full rfc822 formated message or a specific bodystructure part as a Stream. Bodystructure parts are decoded so the resulting stream is a binary file. Text content is automatically converted to UTF-8 charset.

Parameters:
Name Type Attributes Description
range SequenceString

UID or sequence number for the message to fetch

part String <optional>

If not set then downloads entire rfc822 formatted message, otherwise downloads specific bodystructure part

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID number instead of sequence number for range

maxBytes number <optional>

If set then limits download size to specified bytes

chunkSize number <optional>
65536

How large content parts to ask from the server

Example
let mailbox = await client.mailboxOpen('INBOX');
// download body part nr '1.2' from latest message
let {meta, content} = await client.download('*', '1.2');
content.pipe(fs.createWriteStream(meta.filename));

(async) downloadMany(range, parts, optionsopt) → {Promise.<Object>}

Fetch multiple attachments as Buffer values

Parameters:
Name Type Attributes Description
range SequenceString

UID or sequence number for the message to fetch

parts String

A list of bodystructure parts

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then uses UID number instead of sequence number for range

Example
let mailbox = await client.mailboxOpen('INBOX');
// download body parts '2', and '3' from all messages in the selected mailbox
let response = await client.downloadMany('*', ['2', '3']);
process.stdout.write(response[2].content)
process.stdout.write(response[3].content)

(async, generator) fetch(range, query, optionsopt)

Fetch messages from currently opened mailbox

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range of messages to fetch

query FetchQueryObject

Fetch query

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID numbers instead of sequence numbers for range

changedSince BigInt <optional>

If set then only messages with a higher modseq value are returned. Ignored if server does not support CONDSTORE extension.

binary Boolean <optional>
false

If true then requests a binary response if the server supports this

Example
let mailbox = await client.mailboxOpen('INBOX');
// fetch UID for all messages in a mailbox
for await (let msg of client.fetch('1:*', {uid: true})){
    console.log(msg.uid);
    // NB! You can not run any IMAP commands in this loop
    // otherwise you will end up in a deadloop
}

(async) fetchOne(seq, query, optionsopt) → {Promise.<FetchMessageObject>}

Fetch a single message from currently opened mailbox

Parameters:
Name Type Attributes Description
seq SequenceString

Single UID or sequence number of the message to fetch for

query FetchQueryObject

Fetch query

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID number instead of sequence number for seq

binary Boolean <optional>
false

If true then requests a binary response if the server supports this

Example
let mailbox = await client.mailboxOpen('INBOX');
// fetch UID for the last email in the selected mailbox
let lastMsg = await client.fetchOne('*', {uid: true})
console.log(lastMsg.uid);

(async) getMailboxLock(path, optionsopt) → {Promise.<MailboxLockObject>}

Opens a mailbox if not already open and returns a lock. Next call to getMailboxLock() is queued until previous lock is released. This is suggested over mailboxOpen() as getMailboxLock() gives you a weak transaction while mailboxOpen() has no guarantees whatsoever that another mailbox is opened while you try to call multiple fetch or store commands.

Parameters:
Name Type Attributes Description
path string | array

Path for the mailbox to open

options Object <optional>

optional options

Properties
Name Type Attributes Default Description
readOnly Boolean <optional>
false

If true then opens mailbox in read-only mode. You can still try to perform write operations but these would probably fail.

Throws:

Will throw an error if mailbox does not exist or can not be opened

Example
let lock = await client.getMailboxLock('INBOX');
try {
  // do something in the mailbox
} finally {
  // use finally{} to make sure lock is released even if exception occurs
  lock.release();
}

(async) getQuota(pathopt) → {Promise.<(QuotaResponse|Boolean)>}

Returns current quota

Parameters:
Name Type Attributes Description
path String <optional>

Optional mailbox path if you want to check quota for specific folder

Example
let quota = await client.getQuota();
console.log(quota.storage.used, quota.storage.available)

(async) idle() → {Promise.<Boolean>}

Starts listening for new or deleted messages from the currently opened mailbox. Only required if ImapFlow#disableAutoIdle is set to true otherwise IDLE is started by default on connection inactivity. NB! If idle() is called manually then it does not return until IDLE is finished which means you would have to call some other command out of scope.

Example
let mailbox = await client.mailboxOpen('INBOX');

await client.idle();

(async) list(optionsopt) → {Promise.<Array.<ListResponse>>}

Lists available mailboxes as an Array

Parameters:
Name Type Attributes Description
options Object <optional>

defines additional listing options

Properties
Name Type Attributes Description
statusQuery Object <optional>

request status items for every listed entry

Properties
Name Type Attributes Description
messages Boolean <optional>

if true request count of messages

recent Boolean <optional>

if true request count of messages with \Recent tag

uidNext Boolean <optional>

if true request predicted next UID

uidValidity Boolean <optional>

if true request mailbox UIDVALIDITY value

unseen Boolean <optional>

if true request count of unseen messages

highestModseq Boolean <optional>

if true request last known modseq value

specialUseHints Object <optional>

set specific paths as special use folders, this would override special use flags provided from the server

Properties
Name Type Attributes Description
sent String <optional>

Path to "Sent Mail" folder

trash String <optional>

Path to "Trash" folder

junk String <optional>

Path to "Junk Mail" folder

drafts String <optional>

Path to "Drafts" folder

Example
let list = await client.list();
list.forEach(mailbox=>console.log(mailbox.path));

(async) listTree() → {Promise.<ListTreeResponse>}

Lists available mailboxes as a tree structured object

Example
let tree = await client.listTree();
tree.folders.forEach(mailbox=>console.log(mailbox.path));

(async) logout() → {Promise.<void>}

Graceful connection close by sending logout command to server. TCP connection is closed once command is finished.

Example
let client = new ImapFlow({...});
await client.connect();
...
await client.logout();

(async) mailboxClose() → {Promise.<Boolean>}

Closes a previously opened mailbox

Example
let mailbox = await client.mailboxOpen('INBOX');
await client.mailboxClose();

(async) mailboxCreate(path) → {Promise.<MailboxCreateResponse>}

Creates a new mailbox folder and sets up subscription for the created mailbox. Throws on error.

Parameters:
Name Type Description
path string | array

Full mailbox path. Unicode is allowed. If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.

Throws:

Will throw an error if mailbox can not be created

Example
let info = await client.mailboxCreate(['parent', 'child']);
console.log(info.path);
// "INBOX.parent.child" // assumes "INBOX." as namespace prefix and "." as delimiter

(async) mailboxDelete(path) → {Promise.<MailboxDeleteResponse>}

Deletes a mailbox. Throws on error.

Parameters:
Name Type Description
path string | array

Path for the mailbox to delete. Unicode is allowed. If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.

Throws:

Will throw an error if mailbox does not exist or can not be deleted

Example
let info = await client.mailboxDelete('Important stuff ❗️');
console.log(info.path);
// "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix

(async) mailboxOpen(path, optionsopt) → {Promise.<MailboxObject>}

Opens a mailbox to access messages. You can perform message operations only against an opened mailbox. Using getMailboxLock() instead of mailboxOpen() is preferred. Both do the same thing but next getMailboxLock() call is not executed until previous one is released.

Parameters:
Name Type Attributes Description
path string | array

Path for the mailbox to open

options Object <optional>

optional options

Properties
Name Type Attributes Default Description
readOnly Boolean <optional>
false

If true then opens mailbox in read-only mode. You can still try to perform write operations but these would probably fail.

Throws:

Will throw an error if mailbox does not exist or can not be opened

Example
let mailbox = await client.mailboxOpen('Important stuff ❗️');
console.log(mailbox.exists);
// 125

(async) mailboxRename(path, newPath) → {Promise.<MailboxRenameResponse>}

Renames a mailbox. Throws on error.

Parameters:
Name Type Description
path string | array

Path for the mailbox to rename. Unicode is allowed. If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.

newPath string | array

New path for the mailbox

Throws:

Will throw an error if mailbox does not exist or can not be renamed

Example
let info = await client.mailboxRename('parent.child', 'Important stuff ❗️');
console.log(info.newPath);
// "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix

(async) mailboxSubscribe(path) → {Promise.<Boolean>}

Subscribes to a mailbox

Parameters:
Name Type Description
path string | array

Path for the mailbox to subscribe to. Unicode is allowed. If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.

Example
await client.mailboxSubscribe('Important stuff ❗️');

(async) mailboxUnsubscribe(path) → {Promise.<Boolean>}

Unsubscribes from a mailbox

Parameters:
Name Type Description
path string | array

Path for the mailbox to unsubscribe from. Unicode is allowed. If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.

Example
await client.mailboxUnsubscribe('Important stuff ❗️');

(async) messageCopy(range, destination, optionsopt) → {Promise.<CopyResponseObject>}

Copies messages from current mailbox to destination mailbox

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range of messages to copy

destination String

Mailbox path to copy the messages to

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

Example
await client.mailboxOpen('INBOX');
// copy all messages to a mailbox called "Backup" (must exist)
let result = await client.messageCopy('1:*', 'Backup');
console.log('Copied %s messages', result.uidMap.size);

(async) messageDelete(range, optionsopt) → {Promise.<Boolean>}

Delete messages from currently opened mailbox. Method does not indicate info about deleted messages, instead you should be using ImapFlow#expunge event for this

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range to filter the messages

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

Example
let mailbox = await client.mailboxOpen('INBOX');
// delete all seen messages
await client.messageDelete({seen: true});

(async) messageFlagsAdd(range, Array, optionsopt) → {Promise.<Boolean>}

Adds flags for a message or message range

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range to filter the messages

Array Array.<string>

of flags to set. Only flags that are permitted to set are used, other flags are ignored

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

unchangedSince BigInt <optional>

If set then only messages with a lower or equal modseq value are updated. Ignored if server does not support CONDSTORE extension.

useLabels Boolean <optional>
false

If true then update Gmail labels instead of message flags

Example
let mailbox = await client.mailboxOpen('INBOX');
// mark all unseen messages as seen (and keep other flags as is)
await client.messageFlagsAdd({seen: false}, ['\Seen]);

(async) messageFlagsRemove(range, Array, optionsopt) → {Promise.<Boolean>}

Remove specific flags from a message or message range

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range to filter the messages

Array Array.<string>

of flags to remove. Only flags that are permitted to set are used, other flags are ignored

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

unchangedSince BigInt <optional>

If set then only messages with a lower or equal modseq value are updated. Ignored if server does not support CONDSTORE extension.

useLabels Boolean <optional>
false

If true then update Gmail labels instead of message flags

Example
let mailbox = await client.mailboxOpen('INBOX');
// mark all seen messages as unseen by removing \\Seen flag
await client.messageFlagsRemove({seen: true}, ['\Seen]);

(async) messageFlagsSet(range, Array, optionsopt) → {Promise.<Boolean>}

Sets flags for a message or message range

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range to filter the messages

Array Array.<string>

of flags to set. Only flags that are permitted to set are used, other flags are ignored

options Object <optional>
Properties
Name Type Attributes Default Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

unchangedSince BigInt <optional>

If set then only messages with a lower or equal modseq value are updated. Ignored if server does not support CONDSTORE extension.

useLabels Boolean <optional>
false

If true then update Gmail labels instead of message flags

Example
let mailbox = await client.mailboxOpen('INBOX');
// mark all unseen messages as seen (and remove other flags)
await client.messageFlagsSet({seen: false}, ['\Seen]);

(async) messageMove(range, destination, optionsopt) → {Promise.<CopyResponseObject>}

Moves messages from current mailbox to destination mailbox

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range of messages to move

destination String

Mailbox path to move the messages to

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

Example
await client.mailboxOpen('INBOX');
// move all messages to a mailbox called "Trash" (must exist)
let result = await client.messageMove('1:*', 'Trash');
console.log('Moved %s messages', result.uidMap.size);

(async) noop() → {Promise.<void>}

Performs a no-op call against server

Search messages from currently opened mailbox

Parameters:
Name Type Attributes Description
query SearchObject

Query to filter the messages

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then returns UID numbers instead of sequence numbers

Example
let mailbox = await client.mailboxOpen('INBOX');
// find all unseen messages
let list = await client.search({seen: false});
// use OR modifier (array of 2 or more search queries)
let list = await client.search({
  seen: false,
  or: [
    {flagged: true},
    {from: 'andris'},
    {subject: 'test'}
  ]});

(async) setFlagColor(range, The, optionsopt) → {Promise.<Boolean>}

Sets a colored flag for an email. Only supported by mail clients like Apple Mail

Parameters:
Name Type Attributes Description
range SequenceString | Array.<Number> | SearchObject

Range to filter the messages

The string

color to set. One of 'red', 'orange', 'yellow', 'green', 'blue', 'purple', and 'grey'

options Object <optional>
Properties
Name Type Attributes Description
uid Boolean <optional>

If true then uses UID SequenceString instead of sequence numbers

unchangedSince BigInt <optional>

If set then only messages with a lower or equal modseq value are updated. Ignored if server does not support CONDSTORE extension.

Example
let mailbox = await client.mailboxOpen('INBOX');
// add a purple flag for all emails
await client.setFlagColor('1:*', 'Purple');

(async) status(path, query) → {Promise.<StatusObject>}

Requests the status of the indicated mailbox. Only requested status values will be returned.

Parameters:
Name Type Description
path String

mailbox path to check for (unicode string)

query Object

defines requested status items

Properties
Name Type Description
messages Boolean

if true request count of messages

recent Boolean

if true request count of messages with \Recent tag

uidNext Boolean

if true request predicted next UID

uidValidity Boolean

if true request mailbox UIDVALIDITY value

unseen Boolean

if true request count of unseen messages

highestModseq Boolean

if true request last known modseq value

Example
let status = await client.status('INBOX', {unseen: true});
console.log(status.unseen);
// 123

Events

close

Connection close event. NB! ImapFlow does not handle reconncts automatically. So whenever a 'close' event occurs you must create a new connection yourself.

error :Error

Error event. In most cases getting an error event also means that connection is closed and pending operations should return with a failure.

Example
client.on('error', err=>{
    console.log(`Error occurred: ${err.message}`);
});

exists :Object

Message count in currently opened mailbox changed

Properties:
Name Type Description
path String

mailbox path this event applies to

count Number

updated count of messages

prevCount Number

message count before this update

Example
client.on('exists', data=>{
    console.log(`Message count in "${data.path}" is ${data.count}`);
});

expunge :Object

Deleted message sequence number in currently opened mailbox. One event is fired for every deleted email.

Properties:
Name Type Description
path String

mailbox path this event applies to

seq Number

sequence number of deleted message

Example
client.on('expunge', data=>{
    console.log(`Message #${data.seq} was deleted from "${data.path}"`);
});

flags :Object

Flags were updated for a message. Not all servers fire this event.

Properties:
Name Type Attributes Description
path String

mailbox path this event applies to

seq Number

sequence number of updated message

uid Number <optional>

UID number of updated message (if server provided this value)

modseq BigInt <optional>

Updated modseq number for the mailbox (if server provided this value)

flags Set.<string>

A set of all flags for the updated message

Example
client.on('flags', data=>{
    console.log(`Flag set for #${data.seq} is now "${Array.from(data.flags).join(', ')}"`);
});

log :Object

Log event if emitLogs=true

Example
client.on('log', entry => {
    console.log(`${log.cid} ${log.msg}`);
});

mailboxClose :MailboxObject

Mailbox was closed

Example
client.on('mailboxClose', mailbox => {
    console.log(`Mailbox ${mailbox.path} was closed`);
});

mailboxOpen :MailboxObject

Mailbox was opened

Example
client.on('mailboxOpen', mailbox => {
    console.log(`Mailbox ${mailbox.path} was opened`);
});