LibGMailClientCXX Code
Status: Alpha
Brought to you by:
owenhealy
-----------------------------
INSTALLATION
-----------------------------
To create the Makefile:
./configure
To compile the library:
$ make
To install the headers and solib:
# make install
To compile it needs headers and objects from libcurl
(http://curl.haxx.se/libcurl/)
And expects to link with -lcurl
-----------------------------
USING THE LIBRARY
-----------------------------
See the online documentation at http://gmailclientcxx.sourceforge.net/
The remainder of this README is copied from there.
==========================
Creating an instance of the client
==========================
GMailClient *client;
ClientData *clientData;
client = new GMailClient();
clientData = client->getClientData();
And when you're done,
delete client;
You should not delete the ClientData object. When the client is deleted the
ClientData is deleted as well. Most interactions are done through
ClientData, except logging in and logging out.
==========================
Logging in and out
==========================
client->login(const std::string &username, const std::string &password);
For example,
string username(argv[1]);
string password(argv[2]);
client->login(username, password);
To logout,
client->logout();
If login is success, GMailClient::login() returns 0. Otherwise it returns a
nonzero value, and the client is not logged in.
==========================
Listing messages
==========================
(see messagetest.cpp)
Most interactions with the server are tricky because of the delay involved:
when you request a resource (such as a list of messages), you can't use it
until the server returns it. Here's how you get a list of messages:
GMailClient *client = new GMailClient();
ClientData *clientData = client->getClientData();
ListView *list = client->openListView(
ListView::SEARCH, // type of query
"ketchup", // query string
0, // messages to skip
NULL, // callback
NULL // user data (passed to callback)
);
// blocks until all data is returned by the server
list->waitFor();
list->lock(); // so only this thread can access it
vector<MessageListEntry*>::iterator msgIter = list->messages.begin();
vector<MessageListEntry*>::iterator msgEnd = list->messages.end();
for (; msgIter != msgEnd; ++msgIter) {
MessageListEntry *message = *msgIter;
cout << "Message from " << message->fromString << endl;
}
list->unlock();
It's important to remember to lock() a ListView before you access it and
unlock() it when you're done, or the library will not work correctly (and
it would be a very tricky problem to debug)
ListView* ClientData::openListView(
ListView::QueryType queryType,
const std::string &query,
int start,
void (*eventCallback)(void*, ListViewEvent*),
void *userData
);
* queryType: can one one of:
o ListView::GENERAL: where the query string can be "inbox", "spam", "all",
"trash", "drafts", "starred", "sent", "chats"
o ListView::SEARCH: where the query string is a query that you would
type into the search field
o ListView::LABEL: where the query string is the name of a label
* queryString: as explained above.
* start: The number of messages to skip
* eventCallback: Called when new data arrives. not called if NULL
* userData: Passed as the first argument to eventCallback
==========================
Retrieving text of messages
==========================
See convotest.cpp
First you need to register a listener with the ClientData so that you can
be notified when the server has complied with the request
void ClientData::addConversationListener(
void (*callback)(void*, const ConversationEvent*),
void *userData // passed to the callback
);
clientData->addConversationListener(
convoListener,
NULL
);
Next you need to find out about the messages, through a ListView:
ListView *list = clientData->openListView(
ListView::GENERAL,
"inbox",
0,
NULL,
NULL
);
list->waitFor();
Now you need to request their contents. In this example we'll pick a random
conversation. The methods you use to fetch conversations are:
Conversation* ClientData::getConversation(const std::string &id);
void ClientData::fetchConversation(Conversation* conversation);
void ClientData::fetchMessage(Message *message);
void ClientData::refetchConversation(Conversation *conversation);
void ClientData::refetchMessage(Message *message);
list->lock();
int size = list->messages.size();
if (size > 0) {
int index = rand() % size;
MessageListEntry *msgListEntry = list->messages[index];
Conversation *conversation;
// this doesn't have data yet - it's just a placeholder
conversation = clientData->getConversation(msgListEntry->hexID);
// this requests the data
clientData->fetchConversation(conversation);
}
list->unlock();
Now when the conversation is ready, we will be notified.
void convoListener(void *data, const ConversationEvent *event) {
// indicates that the data was newly received
if (event->type == ConversationEvent::CONVERSATION_READY) {
Conversation *convo = event->conversation;
convo->lock(); // for synchronization
cout << "Received " << convo->subject << endl;
convo->unlock();
}
}
Possible ConversationEvents are:
* ConversationEvent::CONVERSATION_READY
* ConversationEvent::CONVERSATION_UPDATED
* ConversationEvent::MESSAGE_READY
* ConversationEvent::MESSAGE_UPDATED
==========================
Events
==========================
Events happen whenever the server sends some new data to the client.
Only a few of the many events are implemented so far.
To receive events, you define a listener function, and give it to the
ClientData. When an event occurs, the listener will be called with
information about the event. The information passed to the listener should
be everything that the client needs to know about the event.
#include <libgmailclientcxx/allheaders.hpp>
#include <string>
#include <iostream>
using namespace libgmailclientcxx;
using namespace std;
void eventListener(void*, const Event&);
int main()
{
GMailClient *client;
ClientData *clientData;
client = new GMailClient();
clientData = client->getClientData();
clientData->addListener(eventListener, NULL);
client->login("joe1234567", "93sdjf389");
// hangs. Will return when client logs out
client->block();
return 0;
}
void eventListener(void *data, const Event &event) {
if (event.type == Event::OWN_CHAT_RECEIVED) {
cout << "I said " << event.chatLine->text << endl;
}
}
Events implemented so far are:
* Event::CHAT_RECEIVED
* Event::CHAT_TYPING
* Event::CHAT_ENTERED_TEXT
* Event::CHAT_INACTIVE
* Event::CONTACTS_UPDATED
* Event::OWN_CHAT_RECEIVED
* Event::QUICK_CONTACTS_UPDATED
The Event object has the following fields:
* EventType type; one of the above
* ChatLine *chatLine; the chat line associated with the event
* std::string text; some string associated with the event
googlelinker and googlesocket are good examples of how to use events
==========================
Requests
==========================
The client can send little messages to the server. You access these
through functions in ClientData:
void ClientData::sendChat(const std::string &email, const std::string &text);
void ClientData::chatTyping(const std::string &email);
void ClientData::chatEnteredText(const std::string &email);
void ClientData::chatInactive(const std::string &email);
void ClientData::setStatus(const Status &status);
Clearly there's some room for improvement. If there's a feature you would
particularly like, you can request it
==========================
Contacts
==========================
I don't yet know how the client can request contact information. Right now,
it waits for the server to send it (which it will, most of the time).
Contact information can be accessed through methods in ClientData:
bool ClientData::haveContact(const std::string &email);
bool ClientData::isOnline(const std::string &email);
Contact ClientData::getContact(const std::string &email); // returns a copy
std::string ClientData::getFirstName(const std::string &email);
std::string ClientData::getName(const std::string &email);
// caller MUST delete[] the allocated memory;
size_t ClientData::getAllContacts(Contact **list);
size_t ClientData::getQuickContacts(Contact **list);
The Contact class looks like this:
class Contact {
public:
std::string email;
std::string uniqueString;
bool canChat;
bool hasGMail;
Status status;
std::string name;
std::string firstName;
Contact();
~Contact();
Contact operator=(Contact &other);
};
==========================
Sending Emails
==========================
To send an email, you first put the necessary information into a
MessageToSend object. This class looks like this:
class MessageToSend {
public:
MessageToSend();
~MessageToSend();
MessageToSend operator=(const MessageToSend &other);
std::string to;
std::string cc;
std::string bcc;
std::string subject;
bool isHTML;
std::string body;
bool isEvent;
std::string eventTitle;
std::string where;
std::string startDate;
std::string startTime;
std::string endDate;
std::string endTime;
private:
Sender *sender;
friend class Sender;
};
Then you call ClientData::sendMessage(const MessageToSend *message);
For an example see sendtest.cpp in the example programs