diff options
Diffstat (limited to 'libmail/mail.H')
| -rw-r--r-- | libmail/mail.H | 1027 | 
1 files changed, 1027 insertions, 0 deletions
| diff --git a/libmail/mail.H b/libmail/mail.H new file mode 100644 index 0000000..281877e --- /dev/null +++ b/libmail/mail.H @@ -0,0 +1,1027 @@ +/* +** Copyright 2003-2008, Double Precision Inc. +** +** See COPYING for distribution information. +*/ +#ifndef libmail_mail_H +#define libmail_mail_H + +#include "libmail_config.h" +#include <time.h> +#include <string> + +#if HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <sys/types.h> +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +#  include <sys/time.h> +# else +#  include <time.h> +# endif +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <sys/poll.h> + +#include <vector> +#include <list> +#include <set> + +#include "namespace.H" +#include "objectmonitor.H" +#include "misc.H" + +#if LIBMAIL_THROW_DEBUG +#define LIBMAIL_THROW(x) do { fprintf(stderr, "Exception at %s(%d)\n", __FILE__, __LINE__); throw x;} while (0) +#else +#define LIBMAIL_THROW(x) throw x + +#define LIBMAIL_THROW_EMPTY + +#endif + +LIBMAIL_START + +class envelope; +class xenvelope; +class mimestruct; +class addMessage; +class searchParams; +class searchCallback; +class smtpInfo; +class snapshot; +class loginInfo; + +// Encapsulate poll() structures + +typedef struct ::pollfd pollfd; + +// i.e. pollfd.fd, pollfd.events, + +static const int pollin=POLLIN; +static const int pollpri=POLLPRI; +static const int pollout=POLLOUT; +static const int pollerr=POLLERR; +static const int pollhup=POLLHUP; + +static const int pollread= POLLIN | POLLHUP | POLLERR; + +static const int pollwrite= POLLOUT | POLLERR; + + +// +// libmail.a uses a mail::callback object to notify the application when +// the requested operation succeeds.  libmail.a's API is completely +// asynchronous.  Most operations cannot be completed immediately.  Instead, +// the application passes a mail::callback object (or one of its subclasses) +// to a function/method call that makes a particular request.  The function +// or a method returns immediately, and the mail::callback's success() or +// fail() method will be called whenever the requested operation completes. +// All processing occurs within mail::account::process(). +// +// It's possible that the requested operation can be completed immediately, +// without blocking for I/O.  In which case the function/method call invokes +// the success() or the fail() method prior to returning. + +class callback { +public: +	callback() {} +	virtual ~callback() {} +	virtual void success(std::string message)=0; +	virtual void fail(std::string message)=0; + +	virtual void reportProgress(size_t bytesCompleted, +				    size_t bytesEstimatedTotal, + +				    size_t messagesCompleted, +				    size_t messagesEstimatedTotal)=0; + +	class disconnect; +	class folder; +	class folderInfo; +	class folderList; +	class message; +}; + +class folder; +class messageInfo; +class loginCallback; + +#define MAILCHECKINTERVAL 10 + +/////////////////////////////////////////////////////////////////////////// +// +// A mail::account object represents a single mail account.  A mail account is +// defined as a collection of related mail folders.  A mail folder may +// contain other mail subfolders, or messages (or both), depending on the +// mail account. +// +// A mail::account object is not instantiated directly, but is instantiated by the +// mail::account::open() function, which instantiated the appropriate subclass +// based on the mail account's URL.  mail::account::open() returns a new mail::account +// object.  As a rule, the mail::account object is not yet fully initialized; the +// application must wait until the success() callback method is invoked. +// +// Mail folders are arranged into a tree-like hierarchy.  The list of folders +// at the topmost hierarchy level is obtained. by the readTopLevelFolders() +// method. + +#define LIBMAIL_SINGLEFOLDER "*LIBMAIL_SINGLEFOLDER" + +#define LIBMAIL_CHEAPSTATUS "*LIBMAIL_CHEAPSTATUS" + +#define LIBMAIL_SERVERTYPE "*LIBMAIL_SERVERTYPE" + +#define LIBMAIL_SERVERDESCR "*LIBMAIL_SERVERDESCR" + +#define LIBMAIL_ACL	"ACL" + +class account : public obj { + +	// All instantiated mail::account objects: + +	static std::list<account *> mailaccount_list; + +	std::list<account *>::iterator my_mailaccount_p; + +	virtual void resumed()=0; + +public: +	static void resume(); +private: +	// Handle any pending I/O for this mail::account object. + +	virtual void handler(std::vector<pollfd> &fds, int &timeout)=0; + +protected: + +	// Disconnect callback object that's passed to the constructor. + +	callback::disconnect &disconnect_callback; + +public: + +	account(callback::disconnect &disconnect_callback); +	// +	// disconnect_callback - a callback object. +	//     disconnect_callback.disconnected() gets called from within +	//     handler() when the connection to the server is terminated. +	//     disconnect_callback.servererror() gets called whenever the +	//     server reports a fatal error which does not result in the +	//     server connection shutting down. + +	virtual ~account(); + +	class openInfo { +	public: +		// +		// Information for creating a new mail::account object: + +		std::string url; +		std::string pwd; + +		std::vector<std::string> certificates; // Raw SSL certificates + +		std::string extraString; // newsrc filename, etc... + +		mail::loginCallback *loginCallbackObj; + +		openInfo(); +		~openInfo(); +	}; + + +	static account *open(openInfo openInfoArg, +			     callback &callback, +			     callback::disconnect &disconnectCallback); +	// +	// Create a new mail::account object. +	// +	// url - mail account URL. +	// pwd - mail account password.  May be an empty string for mail +	//      accounts that do not require passwords (local mail storage). +	// callback - The open() function generally returns immediately. +	//            The app must wait until callback.success() is invoked +	//            indicating that libmail.a succesfully opened account. +	//            callback.fail() is invoked if the login failed (at which +	//            point the mail::account object is automatically destroyed). +	//            A fatal error within the open function itself, +	//            (such as an invalid URL or out of memory) results in +	//            an invocation of callback.fail(), followed by open() +	//            return a NULL pointer. +	// +	// disconnect_callback - +	//            disconnect_callback.disconnected() gets called from +	//            within handler() when the connection to the server is +	//            terminated. disconnect_callback.servererror() gets +	//            called whenever the server reports a fatal error which +	//            does not result in the server connection shutting down. +	// +	//            The disconnect_callback object may not be destroyed until +	//            either callback.fail() calls, or the logout() function +	//            completes (the fail() or the success() method of the +	//            object passed to mail::account::logout() is invoked). + + +	static bool isRemoteUrl(std::string url); +	// Return TRUE if url represents a remote server account +	// (IMAP, POP3, NNTP, or SMTP) + +	static void process(std::vector<pollfd> &fds, int &timeout); + +	// +	// The process function is where ALL libmail.a processing takes +	// place.  All other methods in all mail::account objects merely +	// initiate a request to perform the given task.  The process() +	// function must be called periodically in order to process pending +	// I/O requests. +	// +	// The fds and timeout arguments are intended to be passed directly +	// to the poll(2) function call.  Before calling process() initialize +	// fds to an empty vector.  'timeout' should also be initialized +	// to a fairly large timeout value, which should generally be the +	// timeout before any further application activity takes place. +	// +	// After process() terminates, it should not be invoked again until +	// poll(&fds[0], fds.size(), timeout) indicates that I/O requested +	// by the fd array is available, or until the 'tv' timeout expires. +	// +	// Note that the application should check if fds.size() == 0, which +	// indicates that libmail.a does not expect I/O on any file descriptor, +	// instead the application needs to wait for a simple timer to expire. +	//  +	// If mail::account::process expects further processing to take place +	// earlier than what's indicated by 'timeout', mail::account::process() +	// will reduce the indicated timeout (the timeout will never be made +	// longer, only shorter). + +	static int poll(std::vector<pollfd> &fds, int timeout); + +	virtual void logout(callback &callback)=0; +	// +	// Close the mail account.  The application should wait until +	// either callback.success() or callback.fail() is called (not much +	// of a difference, really, in both cases the mail::account object gets +	// automatically destroyed) + +	virtual void checkNewMail(callback &callback)=0; +	// +	// Explicitly check for any new mail if a folder is currently open. +	// A call to mail::account::checkNewMail() invokes mail::folderCallback's +	// methods to reflect any changes to the currently open folder. +	// mail::folderCallback::newMessages() will be invoked if new messages +	// were added to the folder. mail::folderCallback::messagesRemoved() +	// will be invoked if messages were removed from a folder (perhaps +	// by another application doing updateFolderIndexInfo, and +	// mail::folderCallback::messageChanged() may be invoked to reflect +	// changes to existing messages. + +	virtual bool hasCapability(std::string capability)=0; +	virtual std::string getCapability(std::string capability)=0; +	// +	// Indicate whether this mail::account object supports the indicated +	// capability. + +	virtual class folder *folderFromString(std::string)=0; +	// +	// The opposite of mail::folder::toString().  Creates a new +	// mail::folder object.  The mail::folder object is linked to this +	// mail::account object, and may only be used as argument to this mail::account +	// object's methods. +	// Note that the returned object does not imply that the actual +	// folder exists, only that if it does exist then the new +	// mail::folder object may be used to refer to it. + +	virtual void readTopLevelFolders(callback::folderList +					 &callback1, +					 callback &callback2)=0; +	// Enumerate the topmost mail folders available in this mail account. +	// callback1.success() is invoked to enumerate the folders at the +	// top level of the folder hierarchy. + +	virtual void findFolder(std::string path, +				callback::folderList &callback1, +				callback &callback2)=0; +	// Recreate a folder object. +	// +	// path - the folder's known path -- can be obtained by invoking +	// mail::folder::getPath(). +	// +	// name - the name of this folder, in the application charset. + +	virtual std::string translatePath(std::string path)=0; +	// +	// Take a "human readable" path, and return its server representation. +	// For example: IMAP accounts translate path from the local charset +	// to modified-UTF7. +	// +	// Returns an empty string if the original path was invalid +	// (setting errno accordingly).  A non-empty return does not guarantee +	// an existing folder, merely that the path is valid. + + + +	virtual folder *getSendFolder(const smtpInfo &info, +				      const mail::folder *folder, +				      std::string &errmsg); +	// +	// Create a folder object to be used for sending outgoing +	// mail. +	// +	// info - parameters for sending mail +	// +	// folder - if not NULL, file a CC of the message into this folder +	// +	// errmsg - if this mail account login cannot be used for sending +	// mail, getSendFolder() returns a null ptr, and sets errmsg +	// accordingly. + + +	enum MessageAttributes { +		ARRIVALDATE=1, +		MESSAGESIZE=2, +		ENVELOPE=4, +		MIMESTRUCTURE=8}; + +	virtual void readMessageAttributes(const std::vector<size_t> &messages, +					   MessageAttributes attributes, +					   callback::message +					   &callback)=0; +	// +	// Return metadata about messages in the currently open folder. +	// +	// messages - a list of messages whose metadata should be returned. +	// +	// attributes - which attributes to return.  A logical OR of the +	//     enumerated constant.  Each constant directly translates to a +	//     method in the mail::callback::message object.  If multiple +	//     messages are specified the order of messages for whom the +	//     the attributes are returned is arbitrary.  If multiple attrs +	//     are specified the order in which the attributes are returned is +	//     arbitrary. +	//     With multiple messages and attributes, any order is possible. +	//     It's possible that all attributes for the same message are +	//     returned before the attributes for the next message are +	//     returned; or the attribute for all messages are returned before +	//     returning the next attribute for all messages, etc... +	// +	//              ARRIVALDATE - when the message was added to the +	//              folder (messageArrivalDateCallback). +	// +	//              MESSAGESIZE - approximate message size (may not be +	//              exact, may be just a rough estimate -- +	//              messageSizeCallback). +	// +	//              ENVELOPE - message envelope/thread summary +	//              (messageEnvelopeCallback, maybe +	//               messageReferencesCallback). +	// +	//              MIMESTRUCTURE - message's MIME structure +	//              (messageStructureCallback). +	// + +	virtual void readMessageContent(const std::vector<size_t> &messages, +					bool peek, +					enum mail::readMode readType, +					callback::message +					&callback)=0; + +	// +	// Return the entire header and/or body content of one or more +	// messages. +	// +	// messages - a list of messages whose contents are returned. +	// peek     - if true, do not reset the unread flag, if possible. +	// justHeader - return the contents of the header portion of the +	//              message. +	// justContents - return the contents of the body portion of each +	//              message. +	// mail::callback::message - the messageTextCallback method of +	// this object is invoked for each listed message.  The relative +	// order of messages is arbitrary, but the requested contents of +	// each message are returned in their entirety before returning the +	// contents of the next message. +	// +	// Either justHeader or justContents (or both) must be set.  If +	// only justHeader is set (justContents is not set), header lines are +	// automatically folded. + +	virtual void readMessageContent(size_t messageNum, +					bool peek, +					const class mimestruct &msginfo, +					enum mail::readMode readType, +					callback::message +					&callback)=0; +	// +	// Return the contents of a MIME section of a message. +	// messageNum - the message whose contents are returned. +	// peek - do not reset the unread flag, if possible +	// msgInfo - the MIME section whose contents to be returned. +	// justHeader - return the contents of the header portion of the +	//              message. +	// justContents - return the contents of the body portion of each +	//              message. +	// +	// Either justHeader or justContents (or both) must be set.  If +	// only justHeader is set (justContents is not set), header lines are +	// automatically folded. + +	virtual void readMessageContentDecoded(size_t messageNum, +					       bool peek, +					       const class mimestruct +					       &msginfo, +					       callback::message +					       &callback)=0; +	// +	// Return the decoded contents of a MIME section.  Like +	// readMessageContents, except that base64/quoted-printable content +	// is automatically decoded, and callback.messageTextCallback() +	// gets the raw, decoded, contents. +	// +	// messageNum - the message whose contents are returned. +	// peek - do not reset the unread flag, if possible +	// msgInfo - the MIME section whose contents to be returned. + +	virtual size_t getFolderIndexSize()=0; +	// +	// Return the number of messages in the currently opened folders. +	// The message number arguments to the previous functions should range +	// should range between 0 and one less than the return value from +	// getFolderIndexSize() +	// + +	virtual class messageInfo getFolderIndexInfo(size_t)=0; +	// +	// Return the mail::messageInfo structure for an indicated message. +	// + +	virtual void saveFolderIndexInfo(size_t messageNum, +					 const messageInfo &msgInfo, +					 callback &callback)=0; +	// +	// Reflect updated message flags. +	// +	// messageNum - update flags of this message +	// msgInfo - new message flags. + + +	virtual void updateFolderIndexFlags(const std::vector<size_t> &messages, +					    bool doFlip, +					    bool enableDisable, +					    const messageInfo &flags, +					    callback &callback)=0; +	// +	// Update flags of multiple messages. +	// +	// messages - list of messages whose flags are to be updated. +	// +	// doFlip - flip the state of the indicated flags +	// +	// enableDisable - whether the indicated flags should be set, or +	//          cleared (ignored if doFlip is set) +	// +	// flags - which flags should be changed.  The flags structure is +	// NOT saved for each indicated message, instead the action specified +	// by doFlip/enableDisable is applied to each flag set in the flags +	// object. + +	virtual void updateFolderIndexInfo(callback &)=0; +	// +	// Remove deleted messages. + + +	virtual void removeMessages(const std::vector<size_t> &messages, +				    callback &cb)=0; +	// Remove specified messages + + + +	// Update keywords +	virtual void updateKeywords(const std::vector<size_t> &messages, +				    const std::set<std::string> &keywords, +				    bool setOrChange, +				    // false: set, true: see changeTo +				    bool changeTo, +				    callback &cb); + +	// Variations of the above.  Implemented in the base class. + +	void updateKeywords(const std::vector<size_t> &messages, +			    const std::vector<std::string> &keywords, +			    bool setOrChange, +			    // false: set, true: see changeTo +			    bool changeTo, +			    callback &cb); + +	void updateKeywords(const std::vector<size_t> &messages, +			    const std::list<std::string> &keywords, +			    bool setOrChange, +			    // false: set, true: see changeTo +			    bool changeTo, +			    callback &cb); + +	virtual void getFolderKeywordInfo(size_t, std::set<std::string> &); + +	// +	// Application requests to be notified about folder changes +	// immediately, if possible (IMAP IDLE) +	// + +	virtual void updateNotify(bool enableDisable, callback &callbackArg); + +	// +	// Update the folder according to the flags on each message. +	// Generally, each message with the deleted flag is set gets removed +	// from the folder.  Additionally, updateFolderIndexInfo() usually +	// results in the applicatio notified regarding any changes to the +	// folder's contents, via mail::folderCallback's methods. + +	virtual void copyMessagesTo(const std::vector<size_t> &messages, +				    folder *copyTo, +				    callback &callback)=0; +	// +	// Copy messages to another folder +	// +	// messages - which message to copy +	// copyTo - a folder from the same, or another mail account. + + +	virtual void moveMessagesTo(const std::vector<size_t> &messages, +				    mail::folder *copyTo, +				    mail::callback &callback); +	// +	// Like copyMessagesTo(), except that the messages are moved, not +	// copied (invoking mail::folderCallback::messagesRemoved() +	// appropriate. +	// Subclasses may override.  The generic implementation uses +	// copyMessagesTo(), followed by removeMessages + + +	virtual void searchMessages(const searchParams &searchInfo, +				    searchCallback &callback)=0; +	// +	// Search messages in this folder. +	// +	// searchInfo - specified the search criteria +	// +	// callback - callback object that receives the list of messages +	// that fit the search criteria +}; + +// gcc food + +inline account::MessageAttributes operator| (account::MessageAttributes a, +					     account::MessageAttributes b) +{ +	return (account::MessageAttributes)((int)a | (int)b); +} + +inline account::MessageAttributes operator& (account::MessageAttributes a, +					     account::MessageAttributes b) +{ +	return (account::MessageAttributes)((int)a & (int)b); +} + +inline account::MessageAttributes &operator&= (account::MessageAttributes &a, +					       account::MessageAttributes b) +{ +	return (a=(account::MessageAttributes)((int)a & (int)b)); +} + +inline account::MessageAttributes operator~ (account::MessageAttributes a) +{ +	return (account::MessageAttributes)~(int)a; +} + +// +// A folder object represents a folder in a mail account.  Each mail::folder +// object is linked to the mail::account object that created it. + +class folder : public obj { + +	ptr<mail::account> myServer; + +protected: +	bool isDestroyed(callback &callback) const; +	bool isDestroyed() const; + +	folder(const folder &); // UNDEFINED +	folder &operator=(const folder &o) +	{ +		myServer=o.myServer; +		return *this; +	} + +public: + +	// Applications should not use the constructor directly, but instead +	// should use other methods in the mail::account and mail::folder objects +	// to create instances of mail::folder.  Applications can destroy +	// mail::folder objects at any time where the object is not an +	// argument to an uncompleted request. + +	folder(mail::account *); +	virtual ~folder(); + +	virtual void sameServerAsHelperFunc() const=0; +	// +	// For internal use. +	// + +	virtual std::string getName() const=0; +	// +	// Return the name of the folder, in the application character set. + +	virtual std::string getPath() const=0; +	// +	// Return the folder's path.  Applications should consider paths to +	// be complete opaque strings, for libmail.a's internal use only. +	// The only officially blessed usage for paths is as arguments for +	// mail::account::findFolder, and mail::folder::isParentOf(). + +	virtual bool hasMessages() const=0; +	// +	// Return an indication whether this folder can contain message. + +	virtual bool hasSubFolders() const=0; +	// +	// Return an indication whether this folder can contain subfolders. + +	virtual std::string isNewsgroup() const; +	// +	// Returns a non-empty string if this is a newsgroup, with the +	// string being the newsgroup name. + +	virtual bool isParentOf(std::string path) const=0; +	// True if this folder would be considered a parent folder in the +	// folder hierarchy. +	// +	// path - the path of another folder. + +	virtual void hasMessages(bool)=0; +	virtual void hasSubFolders(bool)=0; +	// +	// For internal use only + +	virtual void readFolderInfo( callback::folderInfo +				     &callback1, +				     callback &callback2) const=0; +	// Return folder metadata, such as the size of this folder + + +	virtual void getParentFolder(callback::folderList &callback1, +				     callback &callback2) const=0; + +	// Return parent folder + +	virtual void readSubFolders( callback::folderList &callback1, +				     callback &callback2) +		const=0; +	// Enumerate any subfolders in this folder + +	virtual mail::addMessage +	*addMessage(callback &callback) const=0; +	// +	// Add a new message to this folder.  Returns a mail::addMessage +	// object. +	// +	// callback - the usual callback object. +	// +	// If addMessage() returns NULL, callback.fail() will be invoked to +	// indicate the reason why.  Otherwise, the new message's metadata +	// should be saved in the mail::addMessage's fields. +	// The message's contents must be passed to saveMessageContents() +	// (multiple times, if necessary), followed by +	// saveMessageContents::go().  If it becomes necessary to abort +	// the process, saveMessageContents::fail() will hold the presses, +	// invoke callback.fail(), and destroy the mail::addMessage object. + + +	virtual void createSubFolder(std::string name, bool isDirectory, +				     callback::folderList +				     &callback1, +				     callback &callback2) const=0; + +	// Create a new subfolder. +	// +	// name - the name of the new subfolder. +	// isDirectory - if true, the subfolder is expected to contain +	// subfolders.  To create a folder that should contain both subfolders +	// and messages do this twice, first with isDirectory set to false, +	// then with isDirectory set to true.  Note that not every mail +	// account supports dual-purpose folders. +	// callback1 - if succesfully, callback1.success() gets invoked with +	// a folder list containing the new folder directory entry. + +	virtual void create(bool isDirectory, +			    callback &callback) const=0; +	// +	// An alternative path to create a new folder is to use +	// mail::account::folderFromString() to create a folder object for a +	// folder that doesn't really exist, then use this method to create +	// the new folder. + +	virtual void destroy(callback &callback, bool destroyDir) +		const=0; +	// +	// The opposite of create() - deletes this folder.  destroyDir should +	// be set to indicate if this folder contains subfolders or messages. +	// For dual-purpose folders, only the folder component represented +	// by destroyDir() gets removed. + +	virtual void renameFolder(const folder *newParent, std::string newName, +				  callback::folderList &callback1, +				  callback &callback2) const=0; +	// Rename this folder. +	// +	// newParent - new parent folder, or NULL if folder should be renamed +	// to the top of the hierarcy tree +	// newName - new folder name, in application charset +	// + + +	virtual folder *clone() const=0; +	// +	// Create another mail::folder object that refers to the same +	// folder. + +	virtual std::string toString() const=0; +	// +	// Convert this folder's identity to a single string.  Applications +	// should consider the string to be a completely opaque string; with +	// its only documented purpose is that passing the string to +	// mail::account::folderFromString() will create a mail::folder object that +	// refers to the same folder that this object refers to. + +	virtual void open(callback &openCallback, +			  snapshot *restoreSnapshot, +			  callback::folder &folderCallback) const=0; +	// +	// Open the messages in this folder.  Any existing open folder is +	// automatically closed.  If the open fails, whether an existing folder +	// remains open is undefined. +	// +	// openCallback - the standard callback method whose methods will be +	// invoked to indicate whether the operation succeeded or not. +	// +	// If not NULL, a pointer to a snapshot object that holds a previously +	// saved folder index snapshot (see callback::folder::saveSnapshot). +	// +	// +	// folderCallback - the object whose methods will be invoked to notify +	// of any changes to the folder's state while it is opened.  This +	// object must not be destroyed, and must continue to exist until +	// either another folder's open request succeeds, or the mail account +	// is closed or disconnected. + + +	// ---------  Access control list support ---------- // + +	virtual void getMyRights(callback &getCallback, std::string &rights) +		const; +	virtual void getRights(callback &getCallback, +			       std::list<std::pair<std::string, std::string> > +			       &rights) +		const; + +	virtual void setRights(callback &setCallback, +			       std::string &errorIdentifier, +			       std::vector<std::string> &errorRights, +			       std::string identifier, +			       std::string rights) +		const; +	virtual void delRights(callback &setCallback, +			       std::string &errorIdentifier, +			       std::vector<std::string> &errorRights, +			       std::string identifier) +		const; + + +	// Helper function for sorting folders. + +	class sort { + +		bool foldersFirst; +	public: +		sort(bool foldersFirstArg); +		~sort(); + +		bool operator()(const folder *a, const folder *b); +	}; +}; + +// +// A mail::callback::disconnect() object is provided for each request to +// open a mail account. +// When the connection to the mail account's server terminates, the object's +// disconnected() method is invoked.  If the connection was abnormally +// terminated, the errmsg string will be empty. +// The servererror() method may be invoked at any time to report a critical +// server error that was not severe enough to force the connection to be +// terminated. + +class callback::disconnect { +public: +	disconnect() {} +	virtual ~disconnect() {} +	virtual void disconnected(const char *errmsg)=0; +	virtual void servererror(const char *errmsg)=0; +}; + +// +// Callbacks for readMessageContent(): +// + +class callback::message : public callback { +public: +	message(); +	virtual ~message(); + +	virtual void messageEnvelopeCallback(size_t messageNumber, +					     const envelope +					     &envelopeArg); + +	virtual void messageReferencesCallback(size_t messageNumber, +					       const std::vector<std::string> +					       &references); + +	virtual void messageArrivalDateCallback(size_t messageNumber, +						time_t datetime); + +	virtual void messageSizeCallback(size_t messageNumber, +					 unsigned long size); + +	virtual void messageStructureCallback(size_t messageNumber, +					      const mimestruct +					      &messageStructure); +	virtual void messageTextCallback(size_t n, std::string text); + +}; + +// +// A callback for readTopLevelFolders/readSubFolders: +// This callback object is also used for creating a new folder.  A +// mail::callback::folderList object is provided when creating a new folder. +// The success() method is invoked with a vector containing exactly one +// mail::folder object, representing the newly-created folder. +// +// NOTE: The mail::folder objects provided to the success() method are valid +// only until the success method() terminates, and are IMMEDIATELY destroyed +// afterwards.  If the callback function needs to preserve a mail::folder +// object (perhaps for the application's main code, later, after it checks +// that this request completed succesfully and needs to do something else to +// the folder) it should use mail::folder::clone() method to create its own +// private copy of the mail::folder object. + +class callback::folderList { +public: +	folderList(); +	virtual ~folderList(); +	virtual void success(const std::vector<const mail::folder *> +			     &folders)=0; +}; + +///////////////////////////////////////////////////////////////////// +// +// Information about a folder + +class callback::folderInfo { +public: +	size_t messageCount; +	size_t unreadCount; + +	bool fastInfo; +	// Initialize to TRUE to only do this if it can be done fast. + +	folderInfo(); +	virtual ~folderInfo(); + +	virtual void success(); +}; + +///////////////////////////////////////////////////////////////////// +// +//  A reference to the following object is saved when a folder is opened +// +//  The object should be subclassed, and virtual methods implemented. +// +//  libmail.a uses the object to notify the application about any changes +//  to the contents of the folder.  The application should expect any of +//  the following methods to be invoked at any time.  However, the methods +//  are usually invoked by mail::account::saveFolderIndexInfo(), +//  mail::account::updateFolderIndexFlags(), mail::account::updateFolderIndexInfo(), +//  and mail::account::checkNewMail().  Additionally, if the 'peek' argument to +//  mail::account::readMessageContents(), and mail::account::readMessageContentsDecoded() is +//  false, mail::folderCallback::messageChanged() will be invoked to indicate +//  that the message's unread flag has been reset. +// +//  However, the application must be prepared to deal with any method being +//  invoked at any time, in the event that the mail account allows the same +//  folder to be opened by multiple applications, and another applications +//  makes changes to the folder. + +class callback::folder { +public: +	folder(); +	virtual ~folder(); + +	virtual void newMessages()=0; +	// +	// New messages have been added to the folder.  The application +	// should use mail::account::getFolderIndexSize() to obtain the current +	// folder size, and compare it with the previously known folder +	// size in order to determine newly-added messages. + +	virtual void messagesRemoved(std::vector< std::pair<size_t, size_t> > +				     &)=0; +	// +	// Messages were removed from the folder.  messagesRemoved() receives +	// a reference to an array of first-last pairs.  Each first-last +	// pair specifies a range of messages removed from the folder index. +	// <3, 5> indicates that messages 3, 4, and 5 were removed, +	// <3, 3> indicates that message #3 was removed. +	// +	// The array is sorted in numerically increasing order. + +	virtual void messageChanged(size_t n)=0; +	// +	// Message metadata has changed.  Use mail::account::getFolderIndexInfo() +	// to obtain the updated set of message flags. + +	virtual void saveSnapshot(std::string snapshotId); +	// Optionally cache the current folder index (getFolderIndexInfo()), +	// as snapshot "snapshotId" + +}; + +// +// libmail.a collects the following metadata about each message, when +// a folder is opened. +// The application is notified via mail::folderCallback::messageChanged() +// about any changes to an existing message's metadata. +// NOTE: this includes changes initiated by the application itself. +// For example, mail::folderCallback::messageChanged() will usually be +// invoked before the mail::account::saveFolderIndexInfo() request completes +// Any changes to the following metadata are +// The folder index. + +class messageInfo { +public: + +	std::string uid; +	// +	// A unique ID is assigned to each message in a folder.  Applications +	// must consider the uid value to be a completely opaque string. +	// The only assumption that applications may make is that no two +	// messages will ever have the same uid in the same folder. +	// Not all mail accounts support the following flags.  Where not, +	// libmail.a will simulate the semantics of the flag while the +	// mail account is opened. + +	bool	draft,		// This is a draft message +		replied,	// This message has been replied to +		marked,	       // This message is marked for further processing +		deleted,  // Marked for deletion (updateFolderIndexInfo() +			  // should end up removing this message + +		unread,	// The contents of this message have not been read. +		recent; // This is the first time the folder has been opened +			// with this message in the folder. + + +#define LIBMAIL_MSGFLAGS \ +	do { \ +	DOFLAG(   FLAG, draft, "\\DRAFT"); \ +	DOFLAG(   FLAG, replied, "\\ANSWERED"); \ +	DOFLAG(   FLAG, marked, "\\FLAGGED"); \ +	DOFLAG(   FLAG, deleted, "\\DELETED"); \ +	DOFLAG(NOTFLAG, unread, "\\SEEN"); \ +	} while (0) + +#define LIBMAIL_SMAPFLAGS \ +	do {\ +		DOFLAG(   FLAG, draft, "DRAFT");\ +		DOFLAG(   FLAG, replied, "REPLIED");\ +		DOFLAG(   FLAG, deleted, "DELETED");\ +		DOFLAG(   FLAG, marked, "MARKED");\ +		DOFLAG(NOTFLAG, unread, "SEEN");\ +	} while (0) + +	messageInfo(); + +	~messageInfo(); + +	operator std::string() const; +	messageInfo(std::string); +}; + +LIBMAIL_END + +#endif | 
