The mailman-client API

0.1

A Node.js client for mailman-core

File: lib/List.js

                'use strict';
                /**
                * @module mailman-client
                * @submodule List
                */
                
                var lodash = require('lodash');
                var ApiRequest = require('./shared/ApiRequest.js');
                var Member = require('./Member.js');
                var Page = require('./Page.js');
                var Settings = require('./Settings.js');
                var ListArchivers = require('./ListArchivers.js');
                var utils = require('./utils');
                
                
                /**
                * List extends ApiRequest to perform operations on the list resource
                * 
                * @constructor
                * @class List
                * @extends ApiRequest
                * @param {Object} options A hash of options for the List instance
                * @param {String} options.endpoint The endpoint URI to request
                * @param {String} [options.username] A username for authenticating API requests
                * @param {String} [options.password] A password for authenticating API requests
                * @param {String} url Location of the list resource on the server
                */
                function List(options,url) {
                    /**
                    * Configuration options such as the endpoint of the API, auth parameters etc.
                    * 
                    * @private
                    * @type Object
                    * @property _options
                    * @default {}
                    */
                    this._options = options || {};
                
                    /**
                    * URL of the list resource 
                    *
                    * @private
                    * @type String
                    * @property _url
                    */
                    this._url = url;
                
                    /**
                    * Supported HTTP methods
                    *
                    * @property _supportedMethods
                    * @type Array
                    * @private
                    * @default ['get','delete']
                    */
                    this._supportedMethods = ['get','post','delete','put'];
                
                    /**
                    * Object containing the resource information, will be null if getInfo() is never called
                    *
                    * @private
                    * @type {Object}
                    * @default null
                    * @property _info
                    */
                    this._info = null;
                
                    /** 
                    * Root template string for the list resource used to compose the _template value
                    * 
                    * @property _rootTemplate
                    * @type String
                    * @private
                    */
                    this._rootTemplate = this._url.split(this._options.endpoint)[1];
                
                    /**
                    * The URI template used to generate the URI to request 
                    *
                    * @private
                    * @type String
                    * @property _template
                    */
                    this._template = this._rootTemplate;
                
                    /**
                    * Keys of the _info object
                    *
                    * @private
                    * @type Array
                    * @property _keys
                    * @default []
                    */
                    this._keys = [];
                
                    /**
                    * Object containing request path variables used to assemble the request URI
                    *
                    * @property _path
                    * @type Object
                    * @private
                    * @default {}
                    */
                    this._path = {};
                }
                
                
                List.prototype = new ApiRequest();
                
                
                /**
                * Fetch the resource by making a HTTP GET request and calls the callback(if any), and provide a 
                * promise to the Domain object itself
                * 
                * @method getInfo
                * @async
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List object itself
                * @return {Promise} Promise to the List object itself
                */
                List.prototype.getInfo = function(callback) {
                    this._template = this._rootTemplate;
                    if ( !this._info ) {
                        var that = this;
                        return that.get().then(function(data) {
                                        that._info = data;
                                        that._keys = Object.keys(data);
                                        that._setAccessors();
                                        return utils.promisify(that,callback);
                                    }).catch(function(e) {
                                        console.error(e);
                                    });
                    } else {
                        return utils.promisify(this,callback);
                    }
                }
                
                
                /**
                * Set the accessors on the object for the resource information i.e _info object
                *
                * @method _setAccessors
                * @private
                */
                List.prototype._setAccessors = function() {
                    /**
                    * The fully qualified list name
                    *
                    * @property fqdn_listname
                    * @type String
                    */
                
                    /**
                    * The mail host of the list
                    *
                    * @property mail_host
                    * @type String
                    */
                
                    /**
                    * The list identifier
                    *
                    * @property list_id
                    * @type String
                    */
                
                    /**
                    * Name of the list
                    *
                    * @property list_name
                    * @type String
                    */
                
                    /**
                    * Display name of the list
                    *
                    * @property display_name
                    * @type String
                    */
                    var that = this;
                    that._keys.forEach(function(key) {
                        Object.defineProperty(that,key, {
                            get : function() {
                                if ( key in that._info )
                                    return that._info[key];
                            },
                            configurable : true
                        });
                    });
                }
                
                
                /**
                * Provides an array of Member instances that are list owners
                *
                * @method getOwners
                * @async
                * @param {Function} [callback] The callback function to be invoked with an array of Member instances
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of Member instances
                * @return {Promise} Promise to an array of Member instances
                */
                List.prototype.getOwners = function(callback) {
                    var that = this;
                    that._template = that._rootTemplate + '/roster/owner';
                    var items = [];
                    return that.get().then(function(resp) {
                                    if ( 'entries' in resp ) {
                                        resp.entries.forEach(function(entry) {
                                            items.push(new Member(that._options,entry.self_link));
                                        });
                                    }
                                    return utils.promisify(items,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides an array of Member instances that are list moderators
                *
                * @method getModerators
                * @async
                * @param {Function} [callback] The callback function to be invoked with an array of Member instances
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of Member instances
                * @return {Promise} Promise to an array of Member instances
                */
                List.prototype.getModerators = function(callback) {
                    var that = this;
                    that._template = that._rootTemplate + '/roster/moderator';
                    var items = [];
                    return that.get().then(function(resp) {
                                    if ( 'entries' in resp ) {
                                        resp.entries.forEach(function(entry) {
                                            items.push(new Member(that._options,entry.self_link));
                                        });
                                    }
                                    return utils.promisify(items,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides an array of Member instances that are list members
                *
                * @method getMembers
                * @async
                * @param {Function} [callback] The callback function to be invoked with an array of Member instances
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of Member instances
                * @return {Promise} Promise to an array of Member instances
                */
                List.prototype.getMembers = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/' + that.fqdn_listname + '/roster/member';
                                    return that.get();
                                }).then(function(resp) {
                                    var items = [];
                                    if ( 'entries' in  resp ) {
                                        resp.entries.forEach(function(entry) {
                                            items.push(new Member(that._options,entry.self_link));
                                        });
                                    }
                                    return utils.promisify(items,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides an array of Member instances that are non-members of the list
                *
                * @method getNonMembers
                * @async
                * @param {Function} [callback] The callback function to be invoked with an array of Member instances
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of Member instances
                * @return {Promise} Promise to an array of Member instances
                */
                List.prototype.getNonMembers = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/members/find';
                                    var data = {
                                        'role' : 'nonmember',
                                        'list_id' : that.list_id
                                    }
                                    return that.post(data);
                                }).then(function(resp) {
                                    var items = [];
                                    if ( 'entries' in resp ) {
                                        items.push(new Member(that._options,entry.self_link));
                                    }
                                    return utils.promisify(items,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides a paging interface to the list members
                *
                * @method getMemberPage
                * @async
                * @param {Number} count Number of items on a page
                * @param {Page} page Number of pages to be requested
                * @param {Function} [callback] The callback function to be invoked with a Page instance
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result A Page instance
                * @return {Promise} Promise to a Page instance
                */
                List.prototype.getMemberPage = function(count,page,callback) {
                    if ( typeof page === 'undefined' )      { page = 1 };
                    if ( typeof count === 'undefined' )     { count = 50 };
                    var that = this;
                    return that.getInfo().then(function() {
                                    var endpoint = '/lists/' + that.fqdn_listname + '/roster/member';
                                    return utils.promisify(
                                        new Page(that._options,endpoint,Member,count,page),
                                        callback
                                        );
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides the list settings, i.e the Settings instance corresponding to the List instance
                *
                * @method getSettings
                * @async
                * @param {Function} [callback] The callback function to be invoked with a Settings instance
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result A Settings instance
                * @return {Promise} Promise to a Settings instance
                */
                List.prototype.getSettings = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    var endpoint = '/lists/' + that.fqdn_listname + '/config';
                                    return utils.promisify(new Settings(that._options,endpoint));
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides an array of objects describing the held messages information
                * 
                * @async
                * @method getHeldMesssages
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of objects describing the held messages
                * @return {Promise} Promise to an array of objects describing the held messages
                */
                List.prototype.getHeldMessages = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/(:fqdn_listname)/held';
                                    that._path.fqdn_listname = that.fqdn_listname;
                                    return that.get();
                                }).then(function(resp) {
                                    var msgEntries = [];
                                    if ( 'entries' in resp ) {
                                        resp.entries.forEach(function(entry) {
                                            msgEntries.push({
                                                hold_date : enrty.hold_date,
                                                msg : entry.msg,
                                                reason : entry.reason,
                                                sender : entry.sender,
                                                request_id : entry.request_id,
                                                subject : entry.subject
                                            });
                                        });
                                    }
                                    return utils.promisify(msgEntries,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Provides an array of objects describing the list subscriptions requests
                * 
                * @async
                * @method getHeldMesssages
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of objects describing the list subscriptions requests
                * @return {Promise} Promise to an array of objects describing the list subscriptions requests
                */
                List.prototype.getSubscriptionRequests = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/(:fqdn_listname)/requests';
                                    that._path.fqdn_listname = that.fqdn_listname;
                                    return that.get();
                                }).then(function(resp) {
                                    var subscriptionRequests = [];
                                    if ( 'entries' in resp ) {
                                        resp.entries.forEach(function(entry) {
                                            subscriptionRequests.push({
                                                email : entry.email,
                                                token : entry.token,
                                                token_owner : entry.token_owner,
                                                list_id : entry.list_id,
                                                request_date : entry.when
                                            });
                                        });
                                    }
                                        return utils.promisify(subscriptionRequests,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Take actions on a subscription request i.e accept|reject|discard|defer it
                *
                * @async
                * @method manageRequest
                * @param {String} token The token identifier for the subscription request
                * @param {String} action Action to take on the list, accept|reject|discard|defer
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of objects describing the list subscriptions requests
                * @return {Promise} Promise to an array of objects describing the list subscriptions requests
                */
                List.prototype.manageRequest = function(token,action,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/' + that.list_id + '/requests/' + token;
                                    var payload = { action : action };
                                    return that.post(payload);
                                }).then(function() {
                                    return utils.promisify(that,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * The ListArchivers instance corresponding to the List instance
                *
                * @async
                * @method getArchivers
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The ListArchivers instance
                * @return {Promise} Promise to the ListArchivers instance
                */
                List.prototype.getArchivers = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    return utils.promisify(
                                        new ListArchivers(that._options,that.list_id),
                                        callback
                                    );
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Assign a role to an address corresponding to a list
                * 
                * @async
                * @method addRole
                * @param {String} role The role to be assigned, owner,moderator etc.
                * @param {String} address The email address
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.addRole = function(role,address,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    var payload = {
                                        list_id : that.list_id,
                                        subscriber : address,
                                        role : role
                                    };
                                    that._template = '/members';
                                    return that.post(payload);
                                }).then(function() {
                                    return utils.promisify(that,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Add a list onwer
                * 
                * @async
                * @method addOwner
                * @param {Function} address The email address of the owner
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.addOwner = function(address,callback) {
                    return this.addRole('owner',address,callback);
                }
                
                
                /**
                * Add a list moderator
                * 
                * @async
                * @method addModerator
                * @param {Function} address The email address of the moderator
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.addModerator = function(address,callback) {
                    return this.addRole('moderator',address,callback);
                }
                
                
                /**
                * Remove an address from a role
                *
                * @async
                * @method removeRole
                * @param {String} role The role from which the address is to be removed
                * @param {String} address The address which is to be removed
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.removeRole = function(role,address,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/(:fqdn_listname)/(:role)/(:address)';
                                    var pathVars = {
                                        fqdn_listname : that.fqdn_listname,
                                        role : role,
                                        address : address
                                    };
                                    lodash.extend(that._path,pathVars);
                                    return that.delete();
                               }).then(function() {
                                    return utils.promisify(that,callback);
                               }).catch(function(e) {
                                    console.error(e);
                               });
                }
                
                
                /**
                * Remove a list moderator
                *
                * @async
                * @method removeModerator
                * @param {String} address The address of the moderator
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.removeModerator = function(address,callback) {
                    return this.removeRole('moderator',address,callback);
                }
                
                
                /**
                * Remove a list owner
                *
                * @async
                * @method removeOnwer
                * @param {String} address The address of the list owner
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.removeOwner = function(address,callback) {
                    return this.removeRole('owner',address,callback);
                }
                
                
                /**
                * Moderate a held message
                * 
                * @async
                * @method moderateMessage
                * @param {String} requestId Identifier describing the held message
                * @param {String} action The action to take on the held message, viz. defer|accept|reject|discard
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.moderateMessage = function(requestId,action,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/(:fqdn_listname)/held/(:requestId)';
                                    var pathVars = {
                                        requestId : requestId,
                                        fqdn_listname : that.fqdn_listname
                                    };
                                    lodash.extend(that._path,pathVars);
                                    return that.post({action : action});
                                }).then(function(resp) {
                                    return utils.promisify(resp,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                // ========== Shortcuts for moderateMessage ================
                
                /**
                * Discard a held message
                * 
                * @async
                * @method discardMessage
                * @param {String} requestId Identifier describing the held message
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.discardMessage = function(requestId,callback) {
                    return this.moderateMessage(requestId,'discard',callback);
                }
                
                
                /**
                * Reject a held message
                * 
                * @async
                * @method rejectMessage
                * @param {String} requestId Identifier describing the held message
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.rejectMessage = function(requestId,callback) {
                    return this.moderateMessage(requestId,'reject',callback);
                }
                
                
                /**
                * Defer a held message
                * 
                * @async
                * @method deferMessage
                * @param {String} requestId Identifier describing the held message
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.deferMessage = function(requestId,callback) {
                    return this.moderateMessage(requestId,'defer',callback);
                }
                
                
                /**
                * Accept a held message
                * 
                * @async
                * @method acceptMessage
                * @param {String} requestId Identifier describing the held message
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.acceptMessage = function(requestId,callback) {
                    return this.moderateMessage(requestId,'accept',callback);
                }
                
                
                /**
                * Moderate a subscription request
                * 
                * @async
                * @method moderateRequest
                * @param {String} requestId Identifier describing the subscription request
                * @param {String} action The action to take on the subscription request, viz. defer|accept|reject|discard
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.moderateRequest = function(requestId,action,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/(:list_id)/requests/(:requestId)';
                                    var pathVars = {
                                        list_id : that.list_id,
                                        requestId : requestId
                                    };
                                    lodash.extend(that._path,pathVars);
                                    return that.post({action : action});
                                }).then(function(resp) {
                                   return utils.promisify(resp,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }       
                
                // ========== Shortcuts for moderateRequest ================
                
                /**
                * Reject a subscription request
                * 
                * @async
                * @method rejectRequest
                * @param {String} requestId Identifier describing the subscription request
                * @param {String} action The action to take on the subscription request
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.rejectRequest = function(requestId,callback) {
                    return this.moderateRequest(requestId,'reject',callback);
                }
                
                /**
                * Accept a subscription request
                * 
                * @async
                * @method acceptRequest
                * @param {String} requestId Identifier describing the subscription request
                * @param {String} action The action to take on the subscription request
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.acceptRequest = function(requestId,callback) {
                    return this.moderateRequest(requestId,'accept',callback);
                }
                
                
                /**
                * Discard a subscription request
                * 
                * @async
                * @method discardRequest
                * @param {String} requestId Identifier describing the subscription request
                * @param {String} action The action to take on the subscription request
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.discardRequest = function(requestId,callback) {
                    return this.moderateRequest(requestId,'discard',callback);
                }
                
                
                /**
                * Defer a subscription request
                * 
                * @async
                * @method deferRequest
                * @param {String} requestId Identifier describing the subscription request
                * @param {String} action The action to take on the subscription request
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The request response
                * @return {Promise} Promise to the request response
                */
                List.prototype.deferRequest = function(requestId,callback) {
                    return this.moderateRequest(requestId,'defer',callback);
                }
                
                
                /**
                * Get a list member by it's email address, it not found throw an Error
                *
                * @async
                * @method getMemberByEmail
                * @param {String} email The email address of the list member
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The Member instance
                * @return {Promise} Promise to the Member instance
                */
                List.prototype.getMemberByEmail = function(email,callback) {
                    var that = this;
                    return new utils.Promise(function(resolve,reject) {
                        that.getMembers().then(function(members) {
                                    var numMembers = members.length;
                                    var loopcount = 0;
                                    members.forEach(function(member) {
                                        member.getInfo().then(function() {
                                            loopcount++;
                                            if ( member.email === email ) {
                                                resolve(member);
                                            }
                                            else if  ( loopcount === numMembers ) {
                                                reject(new Error(email + ' is not a member of ' + that.fqdn_listname));
                                            }
                                        }); // .getInfo()
                                    });  
                            }).catch(function(e) {
                                console.error(e);
                            }); // .getMembers()
                    }).nodeify(callback || utils.noop);
                }
                
                
                /**
                * Subscribe an email address to the list and provide the created Member instance
                *
                * @async
                * @method subscribe
                * @param {String} address The email address to be subscribed to the list
                * @param {String} displayName The display name of the adddress
                * @param {Boolean} preVerified Addeess is pre verified or not
                * @param {Boolean} preConfirmed Address is pre confirmed or not
                * @param {Boolean} preConfirmed Address is pre approved or not
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The Member instance
                * @return {Promise} Promise to the Member instance
                */
                List.prototype.subscribe = function(address,displayName,preVerified,
                                                    preConfirmed,preApproved,callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    preVerified = preVerified || true;
                                    preConfirmed = preConfirmed || true;
                                    preApproved = preApproved || true;
                                    var payload = {
                                        list_id : that.list_id,
                                        subscriber : address,
                                        display_name : displayName
                                    };
                                    if (preVerified) { payload.pre_verified = true; } 
                                    if (preConfirmed) { payload.pre_confirmed = true; }
                                    if (preApproved) { payload.pre_approved = true; }
                                    that._template = '/members';
                                    // get the raw response
                                    return that.post(payload,null,'identity');
                                }).then(function(resp) {
                                    if ( resp.statusCode === 202 )
                                        return utils.promisify(response.body,callback);
                                    else
                                        return utils.promisify(new Member(that._options,resp.req.res.headers.location));
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Unsubscribe an email address from the list, in case the address is not already subscribed expect it to throw
                *
                * @async
                * @method unsubscribe
                * @param {String} email The email address to be unsubscribed 
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.unsubscribe = function(email,callback) {
                    var that = this;
                    return new utils.Promise(function(resolve,reject) {
                        that.getMembers().then(function(members) {
                                var numMembers = members.length;
                                var loopcount = 0;
                                members.forEach(function(member) {
                                    member.getInfo().then(function(memberObj) {
                                            loopcount++;
                                            if ( member.email == email ) {
                                                that._template = member.self_link;
                                                member.unsubscribe().then(function(){
                                                    resolve(that);
                                                });
                                            }
                                            else if ( loopcount === numMembers ) {
                                                reject(new Error(email + ' is not a member address of ' + that.fqdn_listname));
                                            }
                                    }); // .getInfo()
                                }); 
                        }).catch(function(e) {
                            console.error(e);
                        }); // .getMembers()
                    }).nodeify(callback || utils.noop);
                }
                
                
                /**
                * Delete the mailing list 
                *
                * @async
                * @method deleteList
                * @param {Function} [callback] The callback function to be invoked 
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The List instance
                * @return {Promise} Promise to the List instance
                */
                List.prototype.deleteList = function(callback) {
                    var that = this;
                    return that.getInfo().then(function() {
                                    that._template = '/lists/' + that.fqdn_listname;
                                    return that.delete();
                                }).then(function() {
                                    return utils.promisify(that,callback);
                                }).catch(function(e) {
                                    console.error(e);
                                });
                }
                
                
                /**
                * Returns the string representation of the List instance
                *
                * @method toString
                * @return {String} Returns the string representation of the List instance
                */
                List.prototype.toString = function() {
                    return '<List ' + this.fqdn_listname + ' >';
                }
                
                
                module.exports = List;