Code Monkey home page Code Monkey logo

node-imap's Introduction

Description

node-imap is an IMAP client module for node.js.

This module does not perform any magic such as auto-decoding of messages/attachments or parsing of email addresses (node-imap leaves all mail header values as-is).

An upgrade guide from node-imap v0.7.x to v0.8.x can be found here.

Requirements

  • node.js -- v10.0.0 or newer

  • An IMAP server to connect to -- tested with gmail

Installation

npm install imap

Examples

  • Fetch the 'date', 'from', 'to', 'subject' message headers and the message structure of the first 3 messages in the Inbox:
var Imap = require('imap'),
    inspect = require('util').inspect;

var imap = new Imap({
  user: '[email protected]',
  password: 'mygmailpassword',
  host: 'imap.gmail.com',
  port: 993,
  tls: true
});

function openInbox(cb) {
  imap.openBox('INBOX', true, cb);
}

imap.once('ready', function() {
  openInbox(function(err, box) {
    if (err) throw err;
    var f = imap.seq.fetch('1:3', {
      bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)',
      struct: true
    });
    f.on('message', function(msg, seqno) {
      console.log('Message #%d', seqno);
      var prefix = '(#' + seqno + ') ';
      msg.on('body', function(stream, info) {
        var buffer = '';
        stream.on('data', function(chunk) {
          buffer += chunk.toString('utf8');
        });
        stream.once('end', function() {
          console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
        });
      });
      msg.once('attributes', function(attrs) {
        console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
      });
      msg.once('end', function() {
        console.log(prefix + 'Finished');
      });
    });
    f.once('error', function(err) {
      console.log('Fetch error: ' + err);
    });
    f.once('end', function() {
      console.log('Done fetching all messages!');
      imap.end();
    });
  });
});

imap.once('error', function(err) {
  console.log(err);
});

imap.once('end', function() {
  console.log('Connection ended');
});

imap.connect();
  • Retrieve the 'from' header and buffer the entire body of the newest message:
// using the functions and variables already defined in the first example ...

openInbox(function(err, box) {
  if (err) throw err;
  var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM)','TEXT'] });
  f.on('message', function(msg, seqno) {
    console.log('Message #%d', seqno);
    var prefix = '(#' + seqno + ') ';
    msg.on('body', function(stream, info) {
      if (info.which === 'TEXT')
        console.log(prefix + 'Body [%s] found, %d total bytes', inspect(info.which), info.size);
      var buffer = '', count = 0;
      stream.on('data', function(chunk) {
        count += chunk.length;
        buffer += chunk.toString('utf8');
        if (info.which === 'TEXT')
          console.log(prefix + 'Body [%s] (%d/%d)', inspect(info.which), count, info.size);
      });
      stream.once('end', function() {
        if (info.which !== 'TEXT')
          console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
        else
          console.log(prefix + 'Body [%s] Finished', inspect(info.which));
      });
    });
    msg.once('attributes', function(attrs) {
      console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
    });
    msg.once('end', function() {
      console.log(prefix + 'Finished');
    });
  });
  f.once('error', function(err) {
    console.log('Fetch error: ' + err);
  });
  f.once('end', function() {
    console.log('Done fetching all messages!');
    imap.end();
  });
});
  • Save raw unread emails since May 20, 2010 to files:
// using the functions and variables already defined in the first example ...

var fs = require('fs'), fileStream;

openInbox(function(err, box) {
  if (err) throw err;
  imap.search([ 'UNSEEN', ['SINCE', 'May 20, 2010'] ], function(err, results) {
    if (err) throw err;
    var f = imap.fetch(results, { bodies: '' });
    f.on('message', function(msg, seqno) {
      console.log('Message #%d', seqno);
      var prefix = '(#' + seqno + ') ';
      msg.on('body', function(stream, info) {
        console.log(prefix + 'Body');
        stream.pipe(fs.createWriteStream('msg-' + seqno + '-body.txt'));
      });
      msg.once('attributes', function(attrs) {
        console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
      });
      msg.once('end', function() {
        console.log(prefix + 'Finished');
      });
    });
    f.once('error', function(err) {
      console.log('Fetch error: ' + err);
    });
    f.once('end', function() {
      console.log('Done fetching all messages!');
      imap.end();
    });
  });
});

API

Data types

  • MessageSource can be a single message identifier, a message identifier range (e.g. '2504:2507' or '*' or '2504:*'), an array of message identifiers, or an array of message identifier ranges.

  • Box is an object representing the currently open mailbox, and has the following properties:

    • name - string - The name of this mailbox.
    • readOnly - boolean - True if this mailbox was opened in read-only mode. (Only available with openBox() calls)
    • newKeywords - boolean - True if new keywords can be added to messages in this mailbox.
    • uidvalidity - integer - A 32-bit number that can be used to determine if UIDs in this mailbox have changed since the last time this mailbox was opened.
    • uidnext - integer - The uid that will be assigned to the next message that arrives at this mailbox.
    • flags - array - A list of system-defined flags applicable for this mailbox. Flags in this list but not in permFlags may be stored for the current session only. Additional server implementation-specific flags may also be available.
    • permFlags - array - A list of flags that can be permanently added/removed to/from messages in this mailbox.
    • persistentUIDs - boolean - Whether or not this mailbox has persistent UIDs. This should almost always be true for modern mailboxes and should only be false for legacy mail stores where supporting persistent UIDs was not technically feasible.
    • messages - object - Contains various message counts for this mailbox:
      • total - integer - Total number of messages in this mailbox.
      • new - integer - Number of messages in this mailbox having the Recent flag (this IMAP session is the first to see these messages).
      • unseen - integer - (Only available with status() calls) Number of messages in this mailbox not having the Seen flag (marked as not having been read).
  • ImapMessage is an object representing an email message. It consists of:

    • Events:
      • body(< ReadableStream >stream, < object >info) - Emitted for each requested body. Example info properties:
        • which - string - The specifier for this body (e.g. 'TEXT', 'HEADER.FIELDS (TO FROM SUBJECT)', etc).
        • size - integer - The size of this body in bytes.
      • attributes(< object >attrs) - Emitted when all message attributes have been collected. Example attrs properties:
        • uid - integer - A 32-bit ID that uniquely identifies this message within its mailbox.
        • flags - array - A list of flags currently set on this message.
        • date - Date - The internal server date for the message.
        • struct - array - The message's body structure (only set if requested with fetch()). See below for an explanation of the format of this property.
        • size - integer - The RFC822 message size (only set if requested with fetch()).
      • end() - Emitted when all attributes and bodies have been parsed.
  • ImapFetch is an object representing a fetch() request. It consists of:

    • Events:
      • message(< ImapMessage >msg, < integer >seqno) - Emitted for each message resulting from a fetch request. seqno is the message's sequence number.
      • error(< Error >err) - Emitted when an error occurred.
      • end() - Emitted when all messages have been parsed.

A message structure with multiple parts might look something like the following:

[ { type: 'mixed',
    params: { boundary: '000e0cd294e80dc84c0475bf339d' },
    disposition: null,
    language: null,
    location: null
  },
  [ { type: 'alternative',
      params: { boundary: '000e0cd294e80dc83c0475bf339b' },
      disposition: null,
      language: null
    },
    [ { partID: '1.1',
        type: 'text',
        subtype: 'plain',
        params: { charset: 'ISO-8859-1' },
        id: null,
        description: null,
        encoding: '7BIT',
        size: 935,
        lines: 46,
        md5: null,
        disposition: null,
        language: null
      }
    ],
    [ { partID: '1.2',
        type: 'text',
        subtype: 'html',
        params: { charset: 'ISO-8859-1' },
        id: null,
        description: null,
        encoding: 'QUOTED-PRINTABLE',
        size: 1962,
        lines: 33,
        md5: null,
        disposition: null,
        language: null
      }
    ]
  ],
  [ { partID: '2',
      type: 'application',
      subtype: 'octet-stream',
      params: { name: 'somefile' },
      id: null,
      description: null,
      encoding: 'BASE64',
      size: 98,
      lines: null,
      md5: null,
      disposition:
       { type: 'attachment',
         params: { filename: 'somefile' }
       },
      language: null,
      location: null
    }
  ]
]

The above structure describes a message having both an attachment and two forms of the message body (plain text and HTML). Each message part is identified by a partID which is used when you want to fetch the content of that part (see fetch()).

The structure of a message with only one part will simply look something like this:

[ { partID: '1',
    type: 'text',
    subtype: 'plain',
    params: { charset: 'ISO-8859-1' },
    id: null,
    description: null,
    encoding: '7BIT',
    size: 935,
    lines: 46,
    md5: null,
    disposition: null,
    language: null
  }
]

Therefore, an easy way to check for a multipart message is to check if the structure length is >1.

Lastly, here are the system flags defined by RFC3501 that may be added/removed:

  • \Seen - Message has been read
  • \Answered - Message has been answered
  • \Flagged - Message is "flagged" for urgent/special attention
  • \Deleted - Message is marked for removal
  • \Draft - Message has not completed composition (marked as a draft).

It should be noted however that the IMAP server can limit which flags can be permanently modified for any given message. If in doubt, check the mailbox's permFlags first. Additional custom flags may be provided by the server. If available, these will also be listed in the mailbox's permFlags.

require('imap') returns one object: Connection.

Connection Events

  • ready() - Emitted when a connection to the server has been made and authentication was successful.

  • alert(< string >message) - Emitted when the server issues an alert (e.g. "the server is going down for maintenance").

  • mail(< integer >numNewMsgs) - Emitted when new mail arrives in the currently open mailbox.

  • expunge(< integer >seqno) - Emitted when a message was expunged externally. seqno is the sequence number (instead of the unique UID) of the message that was expunged. If you are caching sequence numbers, all sequence numbers higher than this value MUST be decremented by 1 in order to stay synchronized with the server and to keep correct continuity.

  • uidvalidity(< integer >uidvalidity) - Emitted if the UID validity value for the currently open mailbox changes during the current session.

  • update(< integer >seqno, < object >info) - Emitted when message metadata (e.g. flags) changes externally.

  • error(< Error >err) - Emitted when an error occurs. The 'source' property will be set to indicate where the error originated from.

  • close(< boolean >hadError) - Emitted when the connection has completely closed.

  • end() - Emitted when the connection has ended.

Connection Properties

  • state - string - The current state of the connection (e.g. 'disconnected', 'connected', 'authenticated').

  • delimiter - string - The (top-level) mailbox hierarchy delimiter. If the server does not support mailbox hierarchies and only a flat list, this value will be falsey.

  • namespaces - object - Contains information about each namespace type (if supported by the server) with the following properties:

    • personal - array - Mailboxes that belong to the logged in user.
    • other - array - Mailboxes that belong to other users that the logged in user has access to.
    • shared - array - Mailboxes that are accessible by any logged in user.

    There should always be at least one entry (although the IMAP spec allows for more, it doesn't seem to be very common) in the personal namespace list, with a blank namespace prefix. Each property's array contains objects of the following format (with example values):

    { prefix: '', // A string containing the prefix to use to access mailboxes in this namespace
      delimiter: '/', // A string containing the hierarchy delimiter for this namespace, or boolean false
                      //  for a flat namespace with no hierarchy
      extensions: [ // An array of namespace extensions supported by this namespace, or null if none
                    // are specified
        { name: 'X-FOO-BAR', // A string indicating the extension name
          params: [ 'BAZ' ] // An array of strings containing the parameters for this extension,
                            // or null if none are specified
        }
      ]
    }

Connection Static Methods

  • parseHeader(< string >rawHeader[, < boolean >disableAutoDecode]) - object - Parses a raw header and returns an object keyed on header fields and the values are Arrays of header field values. Set disableAutoDecode to true to disable automatic decoding of MIME encoded-words that may exist in header field values.

Connection Instance Methods

Note: Message UID ranges are not guaranteed to be contiguous.

  • (constructor)([< object >config]) - Connection - Creates and returns a new instance of Connection using the specified configuration object. Valid config properties are:

    • user - string - Username for plain-text authentication.
    • password - string - Password for plain-text authentication.
    • xoauth - string - Base64-encoded OAuth token for OAuth authentication for servers that support it (See Andris Reinman's xoauth.js module to help generate this string).
    • xoauth2 - string - Base64-encoded OAuth2 token for The SASL XOAUTH2 Mechanism for servers that support it (See Andris Reinman's xoauth2 module to help generate this string).
    • host - string - Hostname or IP address of the IMAP server. Default: "localhost"
    • port - integer - Port number of the IMAP server. Default: 143
    • tls - boolean - Perform implicit TLS connection? Default: false
    • tlsOptions - object - Options object to pass to tls.connect() Default: (none)
    • autotls - string - Set to 'always' to always attempt connection upgrades via STARTTLS, 'required' only if upgrading is required, or 'never' to never attempt upgrading. Default: 'never'
    • connTimeout - integer - Number of milliseconds to wait for a connection to be established. Default: 10000
    • authTimeout - integer - Number of milliseconds to wait to be authenticated after a connection has been established. Default: 5000
    • socketTimeout - integer - The timeout set for the socket created when communicating with the IMAP server. If not set, the socket will not have a timeout. Default: 0
    • keepalive - mixed - Configures the keepalive mechanism. Set to true to enable keepalive with defaults or set to object to enable and configure keepalive behavior: Default: true
      • interval - integer - This is the interval (in milliseconds) at which NOOPs are sent and the interval at which idleInterval is checked. Default: 10000
      • idleInterval - integer - This is the interval (in milliseconds) at which an IDLE command (for servers that support IDLE) is re-sent. Default: 300000 (5 mins)
      • forceNoop - boolean - Set to true to force use of NOOP keepalive on servers also support IDLE. Default: false
    • debug - function - If set, the function will be called with one argument, a string containing some debug info Default: (no debug output)
  • connect() - (void) - Attempts to connect and authenticate with the IMAP server.

  • end() - (void) - Closes the connection to the server after all requests in the queue have been sent.

  • destroy() - (void) - Immediately destroys the connection to the server.

  • openBox(< string >mailboxName[, < boolean >openReadOnly=false[, < object >modifiers]], < function >callback) - (void) - Opens a specific mailbox that exists on the server. mailboxName should include any necessary prefix/path. modifiers is used by IMAP extensions. callback has 2 parameters: < Error >err, < Box >mailbox.

  • closeBox([< boolean >autoExpunge=true, ]< function >callback) - (void) - Closes the currently open mailbox. If autoExpunge is true, any messages marked as Deleted in the currently open mailbox will be removed if the mailbox was NOT opened in read-only mode. If autoExpunge is false, you disconnect, or you open another mailbox, messages marked as Deleted will NOT be removed from the currently open mailbox. callback has 1 parameter: < Error >err.

  • addBox(< string >mailboxName, < function >callback) - (void) - Creates a new mailbox on the server. mailboxName should include any necessary prefix/path. callback has 1 parameter: < Error >err.

  • delBox(< string >mailboxName, < function >callback) - (void) - Removes a specific mailbox that exists on the server. mailboxName should including any necessary prefix/path. callback has 1 parameter: < Error >err.

  • renameBox(< string >oldMailboxName, < string >newMailboxName, < function >callback) - (void) - Renames a specific mailbox that exists on the server. Both oldMailboxName and newMailboxName should include any necessary prefix/path. callback has 2 parameters: < Error >err, < Box >mailbox. Note: Renaming the 'INBOX' mailbox will instead cause all messages in 'INBOX' to be moved to the new mailbox.

  • subscribeBox(< string >mailboxName, < function >callback) - (void) - Subscribes to a specific mailbox that exists on the server. mailboxName should include any necessary prefix/path. callback has 1 parameter: < Error >err.

  • unsubscribeBox(< string >mailboxName, < function >callback) - (void) - Unsubscribes from a specific mailbox that exists on the server. mailboxName should include any necessary prefix/path. callback has 1 parameter: < Error >err.

  • status(< string >mailboxName, < function >callback) - (void) - Fetches information about a mailbox other than the one currently open. callback has 2 parameters: < Error >err, < Box >mailbox. Note: There is no guarantee that this will be a fast operation on the server. Also, do not call this on the currently open mailbox.

  • getBoxes([< string >nsPrefix, ]< function >callback) - (void) - Obtains the full list of mailboxes. If nsPrefix is not specified, the main personal namespace is used. callback has 2 parameters: < Error >err, < object >boxes. boxes has the following format (with example values):

    { INBOX: // mailbox name
       { attribs: [], // mailbox attributes. An attribute of 'NOSELECT' indicates the mailbox cannot
                      // be opened
         delimiter: '/', // hierarchy delimiter for accessing this mailbox's direct children.
         children: null, // an object containing another structure similar in format to this top level,
                        // otherwise null if no children
         parent: null // pointer to parent mailbox, null if at the top level
       },
      Work:
       { attribs: [],
         delimiter: '/',
         children: null,
         parent: null
       },
      '[Gmail]':
       { attribs: [ '\\NOSELECT' ],
         delimiter: '/',
         children:
          { 'All Mail':
             { attribs: [ '\\All' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            Drafts:
             { attribs: [ '\\Drafts' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            Important:
             { attribs: [ '\\Important' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            'Sent Mail':
             { attribs: [ '\\Sent' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            Spam:
             { attribs: [ '\\Junk' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            Starred:
             { attribs: [ '\\Flagged' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             },
            Trash:
             { attribs: [ '\\Trash' ],
               delimiter: '/',
               children: null,
               parent: [Circular]
             }
          },
         parent: null
       }
    }
  • getSubscribedBoxes([< string >nsPrefix, ]< function >callback) - (void) - Obtains the full list of subscribed mailboxes. If nsPrefix is not specified, the main personal namespace is used. callback has 2 parameters: < Error >err, < object >boxes. boxes has the same format as getBoxes above.

  • expunge([< MessageSource >uids, ]< function >callback) - (void) - Permanently removes all messages flagged as Deleted in the currently open mailbox. If the server supports the 'UIDPLUS' capability, uids can be supplied to only remove messages that both have their uid in uids and have the \Deleted flag set. callback has 1 parameter: < Error >err. Note: At least on Gmail, performing this operation with any currently open mailbox that is not the Spam or Trash mailbox will merely archive any messages marked as Deleted (by moving them to the 'All Mail' mailbox).

  • append(< mixed >msgData, [< object >options, ]< function >callback) - (void) - Appends a message to selected mailbox. msgData is a string or Buffer containing an RFC-822 compatible MIME message. Valid options properties are:

    • mailbox - string - The name of the mailbox to append the message to. Default: the currently open mailbox
    • flags - mixed - A single flag (e.g. 'Seen') or an array of flags (e.g. ['Seen', 'Flagged']) to append to the message. Default: (no flags)
    • date - Date - What to use for message arrival date/time. Default: (current date/time)

    callback has 1 parameter: < Error >err.

All functions below have sequence number-based counterparts that can be accessed by using the 'seq' namespace of the imap connection's instance (e.g. conn.seq.search() returns sequence number(s) instead of UIDs, conn.seq.fetch() fetches by sequence number(s) instead of UIDs, etc):

  • search(< array >criteria, < function >callback) - (void) - Searches the currently open mailbox for messages using given criteria. criteria is a list describing what you want to find. For criteria types that require arguments, use an array instead of just the string criteria type name (e.g. ['FROM', '[email protected]']). Prefix criteria types with an "!" to negate.

    • The following message flags are valid types that do not have arguments:

      • 'ALL' - All messages.
      • 'ANSWERED' - Messages with the Answered flag set.
      • 'DELETED' - Messages with the Deleted flag set.
      • 'DRAFT' - Messages with the Draft flag set.
      • 'FLAGGED' - Messages with the Flagged flag set.
      • 'NEW' - Messages that have the Recent flag set but not the Seen flag.
      • 'SEEN' - Messages that have the Seen flag set.
      • 'RECENT' - Messages that have the Recent flag set.
      • 'OLD' - Messages that do not have the Recent flag set. This is functionally equivalent to "!RECENT" (as opposed to "!NEW").
      • 'UNANSWERED' - Messages that do not have the Answered flag set.
      • 'UNDELETED' - Messages that do not have the Deleted flag set.
      • 'UNDRAFT' - Messages that do not have the Draft flag set.
      • 'UNFLAGGED' - Messages that do not have the Flagged flag set.
      • 'UNSEEN' - Messages that do not have the Seen flag set.
    • The following are valid types that require string value(s):

      • 'BCC' - Messages that contain the specified string in the BCC field.
      • 'CC' - Messages that contain the specified string in the CC field.
      • 'FROM' - Messages that contain the specified string in the FROM field.
      • 'SUBJECT' - Messages that contain the specified string in the SUBJECT field.
      • 'TO' - Messages that contain the specified string in the TO field.
      • 'BODY' - Messages that contain the specified string in the message body.
      • 'TEXT' - Messages that contain the specified string in the header OR the message body.
      • 'KEYWORD' - Messages with the specified keyword set.
      • 'HEADER' - Requires two string values, with the first being the header name and the second being the value to search for. If this second string is empty, all messages that contain the given header name will be returned.
    • The following are valid types that require a string parseable by JavaScript's Date object OR a Date instance:

      • 'BEFORE' - Messages whose internal date (disregarding time and timezone) is earlier than the specified date.
      • 'ON' - Messages whose internal date (disregarding time and timezone) is within the specified date.
      • 'SINCE' - Messages whose internal date (disregarding time and timezone) is within or later than the specified date.
      • 'SENTBEFORE' - Messages whose Date header (disregarding time and timezone) is earlier than the specified date.
      • 'SENTON' - Messages whose Date header (disregarding time and timezone) is within the specified date.
      • 'SENTSINCE' - Messages whose Date header (disregarding time and timezone) is within or later than the specified date.
    • The following are valid types that require one Integer value:

      • 'LARGER' - Messages with a size larger than the specified number of bytes.
      • 'SMALLER' - Messages with a size smaller than the specified number of bytes.
    • The following are valid criterion that require one or more Integer values:

      • 'UID' - Messages with UIDs corresponding to the specified UID set. Ranges are permitted (e.g. '2504:2507' or '*' or '2504:*').
    • Note 1: For the UID-based search (i.e. "conn.search()"), you can retrieve the UIDs for sequence numbers by just supplying an array of sequence numbers and/or ranges as a criteria (e.g. [ '24:29', 19, '66:*' ]).

    • Note 2: By default, all criterion are ANDed together. You can use the special 'OR' on two criterion to find messages matching either search criteria (see example below).

    criteria examples:

    • Unread messages since April 20, 2010: [ 'UNSEEN', ['SINCE', 'April 20, 2010'] ]
    • Messages that are EITHER unread OR are dated April 20, 2010 or later, you could use: [ ['OR', 'UNSEEN', ['SINCE', 'April 20, 2010'] ] ]
    • All messages that have 'node-imap' in the subject header: [ ['HEADER', 'SUBJECT', 'node-imap'] ]
    • All messages that do not have 'node-imap' in the subject header: [ ['!HEADER', 'SUBJECT', 'node-imap'] ]

    callback has 2 parameters: < Error >err, < array >UIDs.

  • fetch(< MessageSource >source, [< object >options]) - ImapFetch - Fetches message(s) in the currently open mailbox.

    Valid options properties are:

    * **markSeen** - _boolean_ - Mark message(s) as read when fetched. **Default:** false
    * **struct** - _boolean_ - Fetch the message structure. **Default:** false
    * **envelope** - _boolean_ - Fetch the message envelope. **Default:** false
    * **size** - _boolean_ - Fetch the RFC822 size. **Default:** false
    * **modifiers** - _object_ - Fetch modifiers defined by IMAP extensions. **Default:** (none)
    * **extensions** - _array_ - Fetch custom fields defined by IMAP extensions, e.g. ['X-MAILBOX', 'X-REAL-UID']. **Default:** (none)
    * **bodies** - _mixed_ - A string or Array of strings containing the body part section to fetch. **Default:** (none) Example sections:
    
        * 'HEADER' - The message header
        * 'HEADER.FIELDS (TO FROM SUBJECT)' - Specific header fields only
        * 'HEADER.FIELDS.NOT (TO FROM SUBJECT)' - Header fields only that do not match the fields given
        * 'TEXT' - The message body
        * '' - The entire message (header + body)
        * 'MIME' - MIME-related header fields only (e.g. 'Content-Type')
    
        **Note:** You can also prefix `bodies` strings (i.e. 'TEXT', 'HEADER', 'HEADER.FIELDS', and 'HEADER.FIELDS.NOT' for `message/rfc822` messages and 'MIME' for any kind of message) with part ids. For example: '1.TEXT', '1.2.HEADER', '2.MIME', etc.
        **Note 2:** 'HEADER*' sections are only valid for parts whose content type is `message/rfc822`, including the root part (no part id).
    
  • copy(< MessageSource >source, < string >mailboxName, < function >callback) - (void) - Copies message(s) in the currently open mailbox to another mailbox. callback has 1 parameter: < Error >err.

  • move(< MessageSource >source, < string >mailboxName, < function >callback) - (void) - Moves message(s) in the currently open mailbox to another mailbox. callback has 1 parameter: < Error >err. Note: The message(s) in the destination mailbox will have a new message UID.

  • addFlags(< MessageSource >source, < mixed >flags, < function >callback) - (void) - Adds flag(s) to message(s). callback has 1 parameter: < Error >err.

  • delFlags(< MessageSource >source, < mixed >flags, < function >callback) - (void) - Removes flag(s) from message(s). callback has 1 parameter: < Error >err.

  • setFlags(< MessageSource >source, < mixed >flags, < function >callback) - (void) - Sets the flag(s) for message(s). callback has 1 parameter: < Error >err.

  • addKeywords(< MessageSource >source, < mixed >keywords, < function >callback) - (void) - Adds keyword(s) to message(s). keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

  • delKeywords(< MessageSource >source, < mixed >keywords, < function >callback) - (void) - Removes keyword(s) from message(s). keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

  • setKeywords(< MessageSource >source, < mixed >keywords, < function >callback) - (void) - Sets keyword(s) for message(s). keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

  • serverSupports(< string >capability) - boolean - Checks if the server supports the specified capability.

Extensions Supported

  • Gmail

    • Server capability: X-GM-EXT-1

    • search() criteria extensions:

      • X-GM-RAW - string - Gmail's custom search syntax. Example: 'has:attachment in:unread'
      • X-GM-THRID - string - Conversation/thread id
      • X-GM-MSGID - string - Account-wide unique id
      • X-GM-LABELS - string - Gmail label
    • fetch() will automatically retrieve the thread id, unique message id, and labels (named 'x-gm-thrid', 'x-gm-msgid', 'x-gm-labels' respectively)

    • Additional Connection instance methods (seqno-based counterparts exist):

      • setLabels(< MessageSource >source, < mixed >labels, < function >callback) - (void) - Replaces labels of message(s) with labels. labels is either a single label or an array of labels. callback has 1 parameter: < Error >err.

      • addLabels(< MessageSource >source, < mixed >labels, < function >callback) - (void) - Adds labels to message(s). labels is either a single label or an array of labels. callback has 1 parameter: < Error >err.

      • delLabels(< MessageSource >source, < mixed >labels, < function >callback) - (void) - Removes labels from message(s). labels is either a single label or an array of labels. callback has 1 parameter: < Error >err.

  • RFC2087

    • Server capability: QUOTA

    • Additional Connection instance methods:

      • setQuota(< string >quotaRoot, < object >quotas, < function >callback) - (void) - Sets the resource limits for quotaRoot using the limits in quotas. callback has 2 parameters: < Error >err, < object >limits. limits has the same format as limits passed to getQuota()'s callback. Example quotas properties (taken from RFC2087):

        • storage - Sum of messages' (RFC822) size, in kilobytes (integer).
        • message - Number of messages (integer).
      • getQuota(< string >quotaRoot, < function >callback) - (void) - Gets the resource usage and limits for quotaRoot. callback has 2 parameters: < Error >err, < object >limits. limits is keyed on the resource name, where the values are objects with the following properties:

        • usage - integer - Resource usage.
        • limit - integer - Resource limit.
      • getQuotaRoot(< string >mailbox, < function >callback) - (void) - Gets the list of quota roots for mailbox and the resource usage and limits for each. callback has 2 parameters: < Error >err, < object >info. info is keyed on the quota root name, where the values are objects structured like limits given by getQuota(). Example info:

          {
            '': {
              storage: { usage: 20480, limit: 102400 }
            },
            foo: {
              storage: { usage: 1024, limit: 4096 },
              message: { usage: 14, limit: 9001 }
            }
          }
  • RFC4315

    • Server capability: UIDPLUS

    • The callback passed to append() will receive an additional argument (the UID of the appended message): < integer >appendedUID.

    • The callback passed to copy(), move(), seq.copy(), seq.move() will receive an additional argument (the UID(s) of the copied message(s) in the destination mailbox): < mixed >newUIDs. newUIDs can be an integer if just one message was copied, or a string for multiple messages (e.g. '100:103' or '100,125,130' or '100,200:201').

  • RFC4551

    • Server capability: CONDSTORE

    • Connection event 'update' info may contain the additional property:

      • modseq - string - The new modification sequence value for the message.
    • search() criteria extensions:

      • MODSEQ - string - Modification sequence value. If this criteria is used, the callback parameters are then: < Error >err, < array >UIDs, < string >modseq. The modseq callback parameter is the highest modification sequence value of all the messages identified in the search results.
    • fetch() will automatically retrieve the modification sequence value (named 'modseq') for each message.

    • fetch() modifier:

      • changedsince - string - Only fetch messages that have changed since the specified modification sequence.
    • The Box type can now have the following property when using openBox() or status():

      • highestmodseq - string - The highest modification sequence value of all messages in the mailbox.
    • Additional Connection instance methods (seqno-based counterparts exist):

      • addFlagsSince(< MessageSource >source, < mixed >flags, < string >modseq, < function >callback) - (void) - Adds flag(s) to message(s) that have not changed since modseq. flags is either a single flag or an array of flags. callback has 1 parameter: < Error >err.

      • delFlagsSince(< MessageSource >source, < mixed >flags, < string >modseq, < function >callback) - (void) - Removes flag(s) from message(s) that have not changed since modseq. flags is either a single flag or an array of flags. callback has 1 parameter: < Error >err.

      • setFlagsSince(< MessageSource >source, < mixed >flags, < string >modseq, < function >callback) - (void) - Sets the flag(s) for message(s) that have not changed since modseq. flags is either a single flag or an array of flags. callback has 1 parameter: < Error >err.

      • addKeywordsSince(< MessageSource >source, < mixed >keywords, < string >modseq, < function >callback) - (void) - Adds keyword(s) to message(s) that have not changed since modseq. keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

      • delKeywordsSince(< MessageSource >source, < mixed >keywords, < string >modseq, < function >callback) - (void) - Removes keyword(s) from message(s) that have not changed since modseq. keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

      • setKeywordsSince(< MessageSource >source, < mixed >keywords, < string >modseq, < function >callback) - (void) - Sets keyword(s) for message(s) that have not changed since modseq. keywords is either a single keyword or an array of keywords. callback has 1 parameter: < Error >err.

  • RFC4731

    • Server capability: ESEARCH

    • Additional Connection instance methods (seqno-based counterpart exists):

      • esearch(< array >criteria, < array >options, < function >callback) - (void) - A variant of search() that can return metadata about results. callback has 2 parameters: < Error >err, < object >info. info has possible keys: 'all', 'min', 'max', 'count'. Valid options:

        • 'ALL' - Retrieves UIDs in a compact form (e.g. [2, '10:11'] instead of search()'s [2, 10, 11]) that match the criteria.
        • 'MIN' - Retrieves the lowest UID that satisfies the criteria.
        • 'MAX' - Retrieves the highest UID that satisfies the criteria.
        • 'COUNT' - Retrieves the number of messages that satisfy the criteria.

        Note: specifying no options or [] for options is the same as ['ALL']

  • RFC5256

    • Server capability: SORT

      • Additional Connection instance methods (seqno-based counterpart exists):

        • sort(< array >sortCriteria, < array >searchCriteria, < function >callback) - (void) - Performs a sorted search(). A seqno-based counterpart also exists for this function. callback has 2 parameters: < Error >err, < array >UIDs. Valid sortCriteria are (reverse sorting of individual criteria is done by prefixing the criteria with '-'):

          • 'ARRIVAL' - Internal date and time of the message. This differs from the ON criteria in search(), which uses just the internal date.
          • 'CC' - The mailbox of the first "cc" address.
          • 'DATE' - Message sent date and time.
          • 'FROM' - The mailbox of the first "from" address.
          • 'SIZE' - Size of the message in octets.
          • 'SUBJECT' - Base subject text.
          • 'TO' - The mailbox of the first "to" address.
    • Server capability: THREAD=REFERENCES, THREAD=ORDEREDSUBJECT

      • Additional Connection instance methods (seqno-based counterpart exists):

        • thread(< string >algorithm, < array >searchCriteria, < function >callback) - (void) - Performs a regular search with searchCriteria and groups the resulting search results using the given algorithm (e.g. 'references', 'orderedsubject'). callback has 2 parameters: < Error >err, < array >UIDs. UIDs is a nested array.

TODO

Several things not yet implemented in no particular order:

  • Support additional IMAP commands/extensions:
    • NOTIFY (via NOTIFY extension -- RFC5465)
    • STATUS addition to LIST (via LIST-STATUS extension -- RFC5819)
    • QRESYNC (RFC5162)

node-imap's People

Contributors

addrummond avatar ajessup avatar angelaigreja avatar antifuchs avatar chotiwat avatar craigp avatar ericz avatar flchs avatar fstab avatar jerem avatar jvah avatar kevinoid avatar killix avatar marksteve avatar mercmobily avatar mikemee avatar mscdex avatar naholyr avatar pmccarren avatar robinqu avatar ronniemb avatar rossj avatar rubycut avatar shinux avatar stuartcarnie avatar svmehta avatar vedmalex avatar vinnitu avatar vvo avatar wismgari avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-imap's Issues

example gives me error

using node 2.5

node.js:63
throw e;
^
TypeError: Cannot read property '1' of null
at parseFetch (/usr/local/lib/node/.npm/imap/0.1.0/package/imap.js:888:21)
at Stream. (/usr/local/lib/node/.npm/imap/0.1.0/package/imap.js:249:114)
at Stream.emit (events:27:15)
at Array. (/usr/local/lib/node/.npm/imap/0.1.0/package/imap.js:120:56)
at EventEmitter._tickCallback (node.js:55:22)
at node.js:773:9

Cannot access ImapConnection.seq.* methods

I can't seem to access the .seq namespaced methods, since they try to access methods on the parent ImapConnection object, but cannot since they don't have a reference to it.

eg.

imap_connection = require('node-imap');

con = new imap_connection.ImapConnection({
    username: '[email protected]',
    password: 'XXXX',
    host: "imap.gmail.com",
    port: 993,
    secure: true,
    debug: null
});

con.connect(function(){
    con.openBox('INBOX', function(){
        fetch = con.seq.fetch(1, {'request':{'headers':true}},
            function(err){
                console.log('Done');
            }
        );
    });
});

Fails with:

TypeError: Object #<Object> has no method '_fetch'
    at Object.fetch (.../node-imap/imap.js:647:15)
    at Object.<anonymous> (.../imap_seq_test.js:14:19)
    at CleartextStream.<anonymous> (.../node-imap/imap.js:460:42)
    at CleartextStream.emit (events.js:42:17)
    at Array.<anonymous> (.../node-imap/imap.js:254:40)
    at EventEmitter._tickCallback (node.js:108:26)

Unhandled 'error' event

When I try to connect to an non existent IMAP server the connection is refused and the application is killed. Subscribing to the error event as suggested in issue #49 and #12 has no visible effect.

var ImapConnection = require('imap').ImapConnection, util = require('util'),
    imap = new ImapConnection({
      username: '[email protected]',
      password: 'foobar',
      host: 'notexistent.domain',
      port: 993,
      secure: true
    });

imap.on('error', function(err) {
    console.log('Oops!');
});

imap.connect(function(err) {
    if (err)
        console.log('More oops!');
});

This is the error I get.

events.js:66
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: connect ECONNREFUSED
    at errnoException (net.js:781:11)
    at Object.afterConnect [as oncomplete] (net.js:772:19)

Tested with Node 0.8.0 and node-imap 0.3.1 on Ubuntu 12.04.

On search, UID range sends always the last mail

When used with a range which is bigger than the actual maximal UID in the mailbox, the mail with maximal UID is found.

If my last message has UID 100,

SEARCH UID 101:*

fins the message with UID 100.

re-IDLE dosn't sends

I think you need to use setInterval instead of setTimeout

self._state.tmrKeepalive = setInterval(function() {
...
var sendBox = false;
clearInterval(self._state.tmrKeepalive);

Fatal exception with non-existent domain

Try to connect using a non-existent host, eg: "klasjfj.asejfl" using whatever port. This exception will be thrown causing the app to restart:

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: connect ECONNREFUSED
at errnoException (net.js:676:11)
at Object.afterConnect as oncomplete

I temporarily fixed by commenting out the line self.emit('error', err) in the error listener:

  this._state.conn.on('error', function(err) {
    clearTimeout(self._state.tmrConn);
    if (self._state.status === STATES.NOCONNECT)
      loginCb(new Error('Unable to connect. Reason: ' + err));
    //self.emit('error', err);
    debug('Error occurred: ' + err);
  });

Any ideas?

Thanks--

memory issues fetching messages

Using the same structure as the example in the README, but fetching a day of messages from All Mail in my gmail account:

var cmds = [
  function() { imap.connect(cb); },
  function() { imap.openBox('[Google Mail]/All Mail', true, cb); },
  function(result) { box = result;imap.search([ ['SINCE', 'May 20, 2010'], ['BEFORE', 'May 21, 2010' ] ], cb); },
  function(results) { imap.fetch(results, { request: { headers: ['from', 'to', 'subject', 'date'] }, body: false, struct: false }, cb); },
  function(results) { console.log(sys.inspect(results, false, 6)); imap.logout(cb); }
];

CPU pegs around 100% and I get FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory after a couple of minutes. There are about 200 emaills in the date range and the IDs are returned correctly by search.

Is this just too much data for an IMAP call? Or are there major bottlenecks with buffering/parsing that many messages in node?

Testing with node 0.2.6 on a Mac.

breaks with emailjs

Not sure it's bug of emailjs or node-imap but when I requre it ImapConnection.connect() fails with strange exception.

var imap = require('imap');
var email = require('emailjs');

var imapConnection = new imap.ImapConnection({
    username: "[email protected]",
    password: "...",
    host: "imap.gmail.com",
    port: 993,
    secure: true
});

imapConnection.connect(function (){
    console.log('logged in');
    imapConnection.logout(function (){
        console.log('logged out');
    });
});

throws

/home/suor/projects/remailer/node_modules/imap/imap.js:1635
  while ((pos = this.indexOf(search, start)) > -1) {
                     ^
TypeError: Second argument must be a string or a buffer.
    at Buffer.split (/home/suor/projects/remailer/node_modules/imap/imap.js:1635:22)
    at CleartextStream.<anonymous> (/home/suor/projects/remailer/node_modules/imap/imap.js:241:17)
    at CleartextStream.emit (events.js:67:17)
    at CleartextStream._push (tls.js:363:12)
    at SecurePair.cycle (tls.js:688:20)
    at EncryptedStream.write (tls.js:122:13)
    at Socket.ondata (stream.js:38:26)
    at Socket.emit (events.js:67:17)
    at TCP.onread (net.js:347:14)

Commenting out require('emailjs') makes everything work

New 'mail' event & Why auto 'Mark as Read' ?

Hi,

I have 2 questions

  1. Is 'mail' event fired for new mails while already processing a previous 'mail' event ?

  2. How to stop node-imap marking mails as read while fetching ?

Thanks

How to fetch information for level 2 or more folders

Hi,

I am trying to fetch the entire folder structure using IMAP.

Here's a sample structure:

Travel
-1st Level child
-- 2nd level child

Now i can use getBoxes to get the information for Travel. But for "1st level child" what will be the fully qualified box name?

I tried with"Travel/1st Level child", but not returning the structure for "1st Level child".

Can someone please help?

Cannot get delimiter from server with XLIST capability

I have tested the node-imap module with my Cyrus IMAP server with XLIST capability, and it turned out that callback passed to getBoxes() method only got called with only one argument, that is error = null. I tried to debug and found that self.delim is still null after connect. So I tried to emulate what the module does to get the delimiter by sending

AA XLIST "" ""

to my imap server.

The server responded with

AA OK Completed (0.000 secs)

But when I tried with gmail IMAP server, it also returned

* XLIST (\Noselect) "/" "/"

before "OK Completed" message.

I also tested with IMAP server of fastmail.fm (which use Cyrus IMAP server), using XLIST to get delimiter didn't work. However, using LIST worked fine with all servers that I have tested.

Should we use only LIST command to get the delimiter?

Search with UID ranges returns only one result when open-ended.

Perhaps related to #63.

When I search with UID ranges (eg. ["UID","65443:"] I expect to get as a result all emails starting from the given UID and up - but instead it seems I only get the next UID. It seems that the above query is functionally identical to ["UID","65443"].

Gmail INBOX becomes "Posteingang"

Hi,

I'm using your imap library. When we upgraded we experienced a new behavior.
With the old version getBoxes got "INBOX" as "INBOX"
With tne new version we "INBOX" gets translated into "Posteingang"
Posteingang is German and means inbox.

When I try to openBox "Posteingang" there is an error:

[NONEXISTENT] Unknown Mailbox: Posteingang (Failure)

Can you give me a hint how/where to fix this?

Ability to fetch both body and headers

When fetching with request: { headers: false, body: 'full' } headers are also fetched, but are raw-emitted on the .on('data') events.

Would it be possible that the library itself parsed those, and populated headers of the messages?

partial reads not being handled correctly

the on('data'...) callback does not correctly handle the situation when it receives an incomplete response from the server.

i.e.
SEND:
A6196 UID FETCH 3104 (FLAGS INTERNALDATE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (FROM TO SUBJECT DATE)])
RECV:

  • 3095 FETCH (UID 3104 FLAGS () INTERNALDATE "22-Oct-2010 11:55:40 +0100" BODYSTRUCTURE ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 111 1 NIL NIL NIL NIL) BODY[HEADER.FIELDS (FROM TO SUBJECT DATE)] {170})

A6196 O

The 'A6196 O' is supposed to be re-emitted, such that the trailing 'K ...\r\n' get picked up by the next read()
and appended onto the end of :
self._state.curData

I'm not certain if my solution is correct, but i've created a fork with a fix that "works for me"

Mark an email as spam

Hi,
How can I flag a message with the type of a spam? (Mark as Spam/ Mark as not Spam)
The flags are only:" \Answered \Flagged \Deleted \Seen \Draft ."

Best regards
André Ligeiro

Crash on refused connection

programs using node-imap are crashing during imap connection-process if imap server is not available.
node-imap first emits an error (Unable to connect. Reason: Error: ECONNREFUSED, Connection refused) but then an ECONNREFUSED error will kill the programm.

var ImapConnection = require('imap').ImapConnection;

var imap = new ImapConnection({
  username: 'someuser',
  password: 'xxxx',
  host: 'imap.notexistingdomain.com',
  port: 143      
});

imap.connect(function(err) {
  console.log(err);    
});

uncatched connection error

Hello,

When there is a connection error, node imap crashes my application instead of returning an error.

Error: Unable to connect. Reason: Error: getaddrinfo ENOENT
at CleartextStream.errorHandler ((...)/node_modules/imap/imap.js:139:15)
at CleartextStream.EventEmitter.emit (events.js:88:17)
at Socket.onerror (...)/node_modules/imap/imap.js:1702:17)
at Socket.EventEmitter.emit (events.js:115:20)
at Socket.connect.require.lookup.addressType (net.js:699:16)
at process.startup.processNextTick.process._tickCallback (node.js:244:9)

events.js:66
throw arguments[1]; // Unhandled 'error' event
^
Error: getaddrinfo ENOENT
at errnoException (dns.js:31:11)
at Object.onanswer as oncomplete

How can I change this behaviour ?

No timeout when establishing a secure-only conn as non-secure.

Using the gmail example that you have listed on the readme and changing the secure flag to be false, you'll see that it just hangs open:

var ImapConnection = require('./imap').ImapConnection, util = require('util'),
    imap = new ImapConnection({
      username: '[email protected]',
      password: 'mygmailpassword',
      host: 'imap.gmail.com',
      port: 993,
      secure: false
    });

Not sure if this is the best way to fix, but I added a listener for timeout and moved the timeout into the socket:

  this._state.conn.on("timeout", function() {
    self._fnTmrConn(loginCb);
  });  

  this._state.conn.setTimeout(this._options.connTimeout);
  this._state.conn.connect(this._options.port, this._options.host);
  //this._state.tmrConn = setTimeout(this._fnTmrConn.bind(this),
  //                                 this._options.connTimeout, loginCb);
};

Please let me know if you're seeing the same problem.

Thanks

is starttls required my googlemail

Having problems trying to connect to the gmail service (always times out) - is starttls required to connect ? If so, is there a plan to implement this feature ? Thanks!

Delete email messages

Hi,

How can I delete an email?
What I'm doing wrong?
Thks.

fetch = imap.fetch(req.params.id, {request: {headers:true, body:false } });

            fetch.on('message', function(msg)
            {
                msg.on('end', function() {
                    console.log("Flags: " + msg.flags);
                    msg.flags.push("\\Deleted");
                    console.log("Flags: " + msg.flags);
                });         
            });

            fetch.on('end', function()
            {
                imap.logout(cb);
                imap.closeBox(function(err) {
                if (err)
                    console.log(err);});

}

Fetch Regex fails when email headers contain CR

Hi.

reFetch = /^* (\d+) FETCH .+? {(\d+)}\r\n/;

The above regex fails under a rare situation where headers contain CR and the on('data') sends a chunk where the header is incomplete. This is more apparent when Yahoo! emails contain the X-YMailISG header, which contains CR seperated values.

reFetch = /^* (\d+) FETCH [\s\S]+? {(\d+)}\r\n/;

The above regex fixes this issue.

Can't connect/authenticate in 0.3.0

I check an imap connection once a minute, looking for new emails. It's been working fine, but 0.3.0 breaks things somehow:

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Not connected or authenticated
at ImapConnection.openBox (/Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:549:11)
at /Users/jmhnilbog/Workspaces/Bad-Luck/lib/interfaces/EmailInterface.coffee:77:27
at /Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:89:15
at ImapConnection._login (/Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:967:14)
at Object. (/Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:87:16)
at CleartextStream. (/Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:475:42)
at CleartextStream.emit (events.js:67:17)
at Array.0 (/Users/jmhnilbog/Workspaces/Bad-Luck/node_modules/imap/imap.js:258:40)
at EventEmitter._tickCallback (node.js:192:40)

code snippet:

@imap.connect (err)=>
    unless err?
            @logger.error err
            return
        @imap.openBox 'INBOX', false, (err, inbox)=>
            cb = ()=>
                @_checkInbox()

            if err?
                if @logger? then @logger.error "Failed to open Inbox: #{err}"
                @interval = setInterval cb, @checkInterval
                return
                # and so on...

how to use msgupdate?

I'm connected to my Gmail Account and want to receive flag changes from it.

I've implemented a simple eventListener on a new ImapConnection() like this:

imap.on("msgupdate", function (message) {
    console.log('msgupdate: ', message);
});

I expected it to get called when I mark emails as read/unread in my iphone or gmail web client. But it doesn't.

Am I on the right track or is it something very different, which I didn't get, yet? =)

Thx for the great Library, btw!

node-imap crashing out trying to process my inbox

https://gist.github.com/4c55ae8e4e546c7fad6f is a gist of the problem I'm seeing. I don't know which exact message is causing it, and I can certainly add more debugging in for you, but it seems that it's processing something wrong. After adding the stack trace debugging output where it was actually breaking, I followed it up the stack and added:

else if (result[i] === 'BODYSTRUCTURE') {
    console.log(result[i+1]);
    fetchData.structure = parseBodyStructure(result[i+1]);        
}

At line 973 (running v0.2.3 of node-imap.) to get the rest of the output you see here. Without fully understanding imap, it became pretty difficult for me to get much farther. If there's anything else I can provide for you, just ask!

PERMANENTFLAGS issue

PERMANENTFLAGS are not set.
My server returns
'* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft )] Flags permitted.'
Fixed by changing regex to
/.
[PERMANENTFLAGS ((.*))]/i

Problem with concurrent calls to openBox()

I want to list all mailboxes and get message counts for each mailbox. So I called openBox() with readonly flag set to true for each mailbox in one connection. The result was only the last callback got called. After I looked into the code it seems that the state of the connection was messed up somehow.

Is there any other way around this? Currently I have to create separate connection for each mailbox just to get message count.

Thanks.

Bug in escape and unescape functions

Hello,
The escape and unescape functions are missing the global flag to ensure all (not just the first) substrings are replaced.

They should be:

function escape(str){
return str.replace(//g, "\").replace(/"/g, '"');
}

function unescape(str){
return str.replace(/"/g, '"').replace(/\/g, "");
}

crash when message flags change

Test script crashes when I connect to the same mailbox with another client and modify a message (delete or set it as unread):

node-imap/imap.js:344
                  curReq._fetcher.emit('message', msg);
                        ^
TypeError: Cannot read property '_fetcher' of undefined
    at Socket.<anonymous> (node-imap/imap.js:344:25)
    at Socket.emit (events.js:64:17)
    at Socket._onReadable (net.js:671:31)
    at IOWatcher.onReadable [as callback] (net.js:177:10)

Conversation with the server looks like this:

+ idling
* OK Still here
(delete few random messages)
* OK Still here
* 1 FETCH (FLAGS (\Deleted \Seen))
* 2 FETCH (FLAGS (\Deleted \Seen))
* 10 FETCH (FLAGS (\Deleted \Seen))
* 11 FETCH (FLAGS (\Answered \Deleted \Seen))
* 12 FETCH (FLAGS (\Deleted \Seen $MDNSent))

Test program: https://gist.github.com/960404 (also shows "public use for _uidnext")

stack overflow on error with secure: true

I don't follow precisely what the function pipe is aiming to do with intercepting the socket error, but by calling cleartext.socket.emit('error') it recurses infinitely.

var ImapConnection = require('./imap').ImapConnection;

var i = new ImapConnection({
username: 'user',
password: 'password',
host: 'nonexistant',
port: 123,
secure: true
});

i.connect(function() { console.log('connected'); });

Command error. 10 - When fetching Exchange mailbox

Hi,

Im trying to fetch my exchange mailbox with the example-code provided. Im getting the following error:

        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: Error while executing request: Command Error. 10
    at Socket.<anonymous> (/www/labb.ntnet.se/imap/imap.js:446:17)
    at Socket.emit (events.js:67:17)
    at TCP.onread (net.js:347:14)```

The data array looks like this.
```[ 'A8', 'BAD', 'Command Error. 10' ]```

Resetting idle state

ImapConnection.prototype._reset does not reset _state.ext.idle.sentIdle and _state.ext.idle.timeWaited. If a connection is closed by the server while we are idling and we try to reconnect using the same ImapConnection instance, sentIdle left to true causes this bug:

  • Upon successful connection, we're sending a CAPABILITY command
  • since _state.ext.idle.sentIdle is true, the _send function will first send a "DONE"
  • This causes the server to respond with a "BAD invalid tag" and close the connection again

TCP ZeroWindow

Hi, i test node-imap on my mailaccount.

i call imap.fetch with one msg id.
By some messages i get on TCP a ZeroWindow (WindowSize=0).
The message Event of imap.fetch called, but no one of the "data"-Event.
I get no Error and the keep-alive and zerowindow tcp paket repeat endless.
I hope you understand my bad english.
Thank you for help.

PERMANENTFLAGS are not set

Remove the $ sign from RegExp in line 264

else if ((result = /^\[PERMANENTFLAGS \((.*)\)\]$/i.exec(data[2])) !== null) {
should be
else if ((result = /^\[PERMANENTFLAGS \((.*)\)\]/i.exec(data[2])) !== null) {

our mail server returns following:

'[PERMANENTFLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\*)] Flags permitted.'

Because of the Flags permitted the RegExp returns false.

Can't fetch entire email message using body: 'full'

I got :

Error: Invalid body partID format

While trying to do :

imap.fetch(results, { request: { headers: false, body: 'full' } });

I quickly checked in imap.js around line 578 but I didn't see anything about fetching both headers and the body at the same time.

Thanks.

Can't read message headers

I don't seem to get anything when I do an imapConnection.fetch(msgId)

 fetchHeaders.on("message", function(msg) {
    console.log("Message: %s", util.inspect(msg, false, 5));
    console.log(msg.id);
    console.log(msg.structure);
    // ...
}

shows:

Message: {}
undefined
undefined

It's most likely user error but you don't have a mailing list so I'm submitting an issue.

search with UID ranges returns nothing under certain circumstances

Currently it seems that UID range searches (e.g. [ 'UID', '5:'] require that at least the starting index must be a real UID.

This might not be possible due to the IMAP spec, but it would be nice if the range simply caught all emails that fell in that range, even if the starting index does not map to a real email.

Connecting on a Exchange Server question

Hi,

I'm struggling to connect on a exchange server from my company.

I've added all the credentials exactly how they are configured on my outlook and after debugged I've got as far as

Connected to host.
Secure connection made.

and than stops there. Doesnt go through the "Ready" state.

On my outlook my settings are like:

authentication Method: username and password

user name: companydomain\myusername
password : *******

advanced

Exchange:

server: mail.mycompany.com.au : 443
Override default port (unchecked)
Use SSL to connect (checked)
Download headers only (unchecked)

Any advise?

Thanks
Rafael

Fetch with sequence ID

In an ideal world we'd always work with UID but I'm finding I need to do some things some times with the sequence id, can this library be updated to support the UID version and the sequence versions of commands?

eg:

FETCH seq
UID FETCH uid

Adding flags to messages

Hello,

I'm having a strange issue with adding flags to the flags array of each message. I call the method addFlags with the appropriate msg id in hopes to set the unread messages I retrieved from my email as read.

Here is the line of code:

imap.addFlags(msg.id, '\\\\Seen', function(err) { console.log('ERROR ADDING FLAG TO EMAIL') });

However, I keep on getting the error:

=====EMAIL
8245 <--- msg.id
[ '\Flagged', '$Junk' ] <--- msg.flags, i printed them out for reference of the format
[ '\Flagged', '$Junk' ]

/Users/congchen/congchen/prism/node/node_modules/imap/imap.js:605
throw err;
^
Error: The flag "\Seen" is not allowed by the server for this mailbox
at ImapConnection._store (/Users/congchen/congchen/prism/node/node_modules/imap/imap.js:713:15)
at ImapConnection.addFlags (/Users/congchen/congchen/prism/node/node_modules/imap/imap.js:603:10)
at ImapMessage. (/Users/congchen/congchen/prism/node/server.js:557:10)
at ImapMessage.emit (events.js:61:17)
at CleartextStream. (/Users/congchen/congchen/prism/node/node_modules/imap/imap.js:186:23)
at CleartextStream.emit (events.js:64:17)
at CleartextStream. (/Users/congchen/congchen/prism/node/node_modules/imap/imap.js:208:34)
at CleartextStream.emit (events.js:64:17)
at CleartextStream._push (tls.js:297:31)
at SecurePair.cycle (tls.js:577:20)

I have tried "\SEEN", "SEEN","seen","Seen", and whatever variation i could think of. In fact, I also tried adding the flag "\Deleted" or tried to delFlag the "\Flagged" flag with no success.

Any help would be great!

Thanks.

UIDNext of opened box ?

Hi,

How to find UIDNext of opened box ? Is that updated for every new incoming mail ?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.