LibGMailClientCXX Tutorial

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 the example)

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();

ListViewStub *view = clientData->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
view->waitFor();

// Get the data. This method is syncrhonized
ListView *list = view->getData();

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;
}

// Now that we are done,
clientData->disposeListView(view);

ClientData::openListView()

ListViewStub* ClientData::openListView(
	ListView::QueryType queryType,
	const std::string &query,
	int start,
	void (*eventCallback)(void*, ListViewEvent*),
	void *userData
);
  • queryType: can one one of:
    • ListView::GENERAL: where the query string can be "inbox", "spam", "all", "trash", "drafts", "starred", "sent", "chats"
    • ListView::SEARCH: where the query string is a query that you would type into the search field
    • 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 the example

First you need to register a listener with the ClientData so that you can be notified when the server has complied with the request. You will call

void ClientData::addConversationListener(                                                     
	void (*callback)(void*, const ConversationEvent*),
	void *userData  // passed to the callback
);

So let's do that:

clientData->addConversationListener(
	convoListener, // This is our callback
	NULL
);

Next you need to find out about the messages, through a ListView:

ListViewStub *view = clientData->openListView(
	ListView::GENERAL,
	"inbox",
	0,
	NULL,
	NULL
);

view->waitFor();
ListView *list = view->getData();

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& getConversation(const std::string &id);
Conversation& getConversation(const MessageListEntry *list);
void fetchConversation(const Conversation &conversation);
void fetchMessage(const Message &message);
void refetchConversation(const Conversation &conversation);
void refetchMessage(const Message &message);

Because getConversation returns a copy of the data, you do not need to worry about synchronization.

So here goes

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);
	
	// this requests the data
	clientData->fetchConversation(conversation);
}

Now when the conversation is ready, we will be notified.

void conversationEvent(void *data, const ConversationEvent *event) {
	cout << "An event!! " << event->type << endl;
	
	if (event->type == ConversationEvent::CONVERSATION_READY) {
		Conversation conversation = clientData->getConversation(
			event->conversationID);
		
		cout << "Received " << convo.subject << endl;
	}
}

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


SourceForge.net Logo Valid XHTML 1.1