modest technical documentation
2006
Nokia Corporation
Introduction
modest is a mail user agent
(MUA) targetting small devices, in particular Nokia's
Nokia 770 Internet Tablet. This document
describes the design and implementation of this software.
modest lives at the top of a extensive
stack of software. It is built on top
of tinymail, and uses its libcamel
backend. It strives to the be a simple yet powerful program, geared
towards small devices, for example (but not limited
to) Nokia's 770 internet tablet. An important
goal is to minimize memory usage while still being able to handle
significant amounts of email quickly; much of that is achieved simply by
using tinymail, which uses a number of clever
tricks for that, such as the proxy design pattern for listing email
headers, and not needing memory for headers which are not currently
visible.
modest, in turn, also tries to be efficient,
fast and scalable. That means that the MUA should
support multiple user-interfaces, perhaps making it even possible to
switch between them during runtime.
To summarize the goals for modest:
target devices with limited amounts of memory ('limited' in 2006
terms means less than 64Mb, and of which only part can be used for
e-mail);
target Linux/Unix-like environments with GLib/GTK+-based
support;
support multiple user-interface (UIs) with as much code
sharing as possible between the different UIs.
Like tinymail
and libcamel, modest
is programmed in C, using the GObject-system for
object-oriented (OO) features. For now, it specifically targets \gtk based
UIs (and derivatives like 'Hildon').
Architecture
modest tries to be quite flexible in its
design. However, it's always important not to make things too
generic. Both for reasons of time limitations and keeping the software
understandable and 'modest', it's important to limit the scope.
For modest, the following:
modest is a e-mail program
using the tinymail and camel
libraries;
modest targets gtk and
gconf-based user-interfaces, including the Hildon
environment;
modest main use-case is in
small, mobile device such as the Nokia 770 Internet
Tablet;
However, effort is made also to
make modest usable as a general-purpose
e-mail client on normal desktop computer.
Design
In this part, we'll discuss the design of various parts of
modest. We'll not go into the details of
various APIs in this chapter. Please consult the documentation generated
from the source code (gtk-doc) for that.
Configuration
Configuration is the part of modest
that deals with storing all settings. While the design allows for
alternative implementations, currently
only GConf is supported as a backend.
All dealing with configuration is done with
the ModestConf-class. It is declared
in modest-conf.h, and
the GConf-based implementation in
modest-conf.c. As said, there could be
different implementations --
nothing GConf-specific is visible in the
ModestConf-API.
Account Management
Account Management is the part of modest
that deals with the setting related to sending and receiving of
e-mail. We will follow the libcamel-convention of using the
term store for an e-mail storage/retrieval
server, and a transport for a server that
transports mail to its destination.
In practice, the following types are available:
stores: POP
and IMAP;
transports: sendmail
and SMTP.
Definitions
An account is a named entity
consisting of a store and
a transport. Note: For our mobile use-cases,
the transport cannot be a static entity, but
may depend on the network connection. That is however not part of
Account Management, so not discussed here
A server account is account
describing the connection with a specific server. Server accounts
come in two type:
A transport describes the connection information
(servername, username, password etc.) for a transport
server;
A store describes the connection information for
a store server;
Code
The functions to deal with account and server accounts are
located in ModestAccountMgr, ie. in
modest-account-mgr.[ch]. There function to add
specific values for both, to list the available ones, etc. Please
refer to the source code documentation for details.
Location in configuration database
Accounts can be found
in /apps/modest/accounts,
while server accounts can be found
in /app/modest/server_accounts.
The following image show an
account accountstest with server accounts
mystore
and mytransport.
For each of the stores, there are number of parameters specified:
hostname - the place where the server resides;
username - the username;
password - the password;
proto - the protocal for communication with this server - for
now these are the following valid values (literal strings):
sendmail;
smtp;
pop
imap.
In modest-proto.[ch] there are various
functions to check whether something is a valid protocol, and
whether it is a transport of a store.
Note that server accounts and accounts are relatively independent. While
accounts refer to two server accounts, these server accounts can be
used by other accounts as well.
The reason two keep accounts and server accounts separately, is a bit of
flexibility. In mobile use-cases, quite often it's desirable to use a
network-specific smtp-server. The chosen structure makes it easy to iterate
over all smtp-servers and find the right one.
Account Management and Tinymail
Tinymail needs the information about all configured accounts - and the
mechanism that it uses for that
is TnyAccountStoreIface. We don't want to use
the tinymail-provided TnyAccountStore, but
provide our own implementation
instead: ModestTnyAccountStore. This class
implements the TnyAccountStoreIface-interace in
terms of the aforementioned ModestAccountMgr.
One unexpected function
that ModestTnyAccountStore needs to implement
is tny account_store get_session (to get the
Camel-session). This function must be provided as a public function,
with that exact name.
Finding the right transport
One of the interesting topics in designing a mobile e-mail client is
to deal with transports (in
particular, SMTP). The reason for that is that
the majority of SMTP-servers only allow e-mail
from the same network. That means that for example
smtp.some-isp.com will only accept mail from
(MAIL FROM:)
user@some-isp.com, and refuse mail
from user@some-other-isp.com, unless the
recipient (RCPT TO:) is on the same network.
Coding guidelines
When hacking on modest, please honour these time-tested coding guidelines.
First, please follow the Linux CodingStyle guidelines
(/usr/src/linux/Documentation/CodingStyle).
Here are only some additional notes.
Your editor may help you with this, for example for emacs:
(c-set-style "K&R")
(setq tab-width 8)
(setq indent-tabs-mode t)
(setq c-basic-offset 8)
Or the equivalent in your favourite editor.
Lines must not exceed 100 characters.
Functions should do one thing, and do it well. In general, functions
should not be much longer than 20-30 lines (except for, say, handling
many different cases in a 'switch'-statement). Files should not get to
big either; if there are more than, say, 800 lines, it's a sign that
some refactoring should take place.
Code should compile cleanly
with gcc's -Wall compile option. Of
course this might not always be possible due to problems in dependent
libraries and/or compiler version. Therefore, do not
include -Werror in the standard compile options; but
do use it when building / testing things yourself.
Code should also run cleanly. GTK+/GLib warnings and errors must be
taken very seriously. If you run modest with
the -d-flag, it will abort whenever
there is such a warning. This can be useful when running inside the
debugger.
Global functions (the ones in .h-files) must
be commented using gtk-doc. This way, we
generate nice documentation. After installing
(under /usr/local), we can browse the results
with DevHelp. Just
add /usr/local/share/gtk-doc/html to the
DEVHELP_SEARCH_PATH-environment variable.
Furthermore, please follow 'conventional wisdom' for programming with
GLib/GTK+/GObject. Some things to remember:
g_new, g_malloc and
friends never return NULL. They terminate
the application if it happens (normally). No need to check
for NULL returns;
g_return_if_fail and friends may be
'turned off', ie. they are to be used for error checking,
but not for your programming logic
Object Index
API Reference