Using the Multiple Accounts API

By Alec Flett alecf@flett.org

Structure

The account system consists of:

Here's an example of a common setup.
(You'll have to pardon the crude drawing for now)
Account Manager
+- Account 1
|    +- Incoming Server 1 (imap.mywork.com IMAP Server, my work account)
|    +- Identity 1 (Alec Flett <alecf@mywork.com>)
+- Account 2
|    +- Incoming Server 2 (pop.myisp.com POP Server, my ISP account)
|    +- Identity 2 (Alec Flett <alecf@myisp.com>)
+- Account 3
|    +- Incoming Server 3 (news.myisp.com NNTP server, my ISP's server)
|    +- Identity 3 (Alec Flett <alecfNOSPAM@myisp.com>)
+- Account 4
     +- Incoming Server 4 (news.mozilla.org NNTP server, mozilla devel)
     +- Identity 2 (Alec Flett <alecf@myisp.com>)
     +- Identity 3 (Alec Flett <alecfNOSPAM@myisp.com>)
      

This is the internal structure that the mail client maintains, but it is presented to the user in a few different ways.

(You may have noticed that Identities 2 and 3 are shared between a few accounts...more on that later)

Servers

Servers are show in the folder pane, and in any place where the user must browse or choose folders, such as the new folder dialog, search, filters, etc. The view shows a flat, unified view of all the servers. The above example would look like this:
alecf on imap.mywork.com
  +- INBOX
  +- Trash
  +- (etc)
alecf on pop.myisp.com
  +- INBOX
  +- Trash
  +- (etc)
news.myisp.com
  +- comp.os.linux.announce
  +- etc..
news.mozilla.org
  +- netscape.public.mozilla.announce
  +- netscape.public.mozilla.mail-news
    
Relevant API calls:

Identities

Identities are used in the compose window. If identities are shared between accounts, you will only see that identity once in the list.

In the above example, the list of identities would be as follows:

Alec Flett <alecf@mywork.com>)
Alec Flett <alecf@myisp.com>)
Alec Flett <alecfNOSPAM@myisp.com>)
      
Relevant API calls:

Storage

The accounts are stored in the preferences. The accounts, identities, and servers are all linked via keys. Keys are simply internal strings that uniquely identify each account, identity and server. The keys are also used to decide the name of each of the preferences that hold the object's data.

As an example, the above structure would be represented in your preferences like this:

user_pref("mail.accountmanager.accounts", "account1,account2,account3");
user_pref("mail.account.account1.server", "server1");
user_pref("mail.account.account1.identities", "id1");
user_pref("mail.account.account2.server", "server2");
user_pref("mail.account.account2.identities", "id3");
user_pref("mail.account.account3.server", "server3");
user_pref("mail.account.account3.identities", "id3");
user_pref("mail.account.account4.server", "server4");
user_pref("mail.account.account4.identities", "id2,id3");
user_pref("mail.server.server1.hostname", "imap.mywork.com");
user_pref("mail.server.server2.hostname", "pop.myisp.com");
user_pref("mail.server.server3.hostname", "news.myisp.com");
user_pref("mail.server.server4.hostname", "news.mozilla.org");
user_pref("mail.identity.id1.useremail", "alecf@mywork.com");
user_pref("mail.identity.id2.useremail", "alecf@myisp.com");
user_pref("mail.identity.id3.useremail", "alecfNOSPAM@myisp.com");
    

There is a lot of information missing here of course.

The keys used here are the account1, server1, id1, etc. These keys are listed in the value of some of these preferences, such as "mail.accountmanager.accounts", and are used to construct the preference names, such as "mail.account.account1.server". This the way accounts know which server and which identities they contain.


Creating new accounts

It is possible to create and modify accounts through the account manager API. The account manager is responsible for the creation of all accounts, incoming servers, and identities. You should not use CreateInstance() to create any of the relevant objects because the account manager needs to keep track of all of these objects as they are created.

To create accounts using the API, you should do the following:

  1. Create a fresh identity with createIdentity();
  2. Assign values to the various identity properties as necessary.
  3. Create a fresh incoming server with createIncomingServer(). You will need to pass it the server type as a string, from the list above.
  4. Assign values to the various server properties as necessary. The most important properties here are the userName and the hostname.
  5. Create a fresh account with createAccount();
  6. Assign the server to the account with the incomingServer attribute.
  7. Assign the identity to the account with the AddIdentity() method.

Some sample code: (where accountManager is the account manager.

var identity = accountManager.createIdentity();
identity.email="fred@myisp.com";

var server = accountManager.createIncomingServer("pop3");
server.userName = "fred";
server.hostname = "pop.myisp.com";

var account = accountManager.createAccount();
account.incomingServer = server;
account.AddIdentity(identity);

That's it! Now you have a working account, identity, and server.

It is possible, through some tricks with server and identity keys, to share servers and identities between accounts. You can do this by referring to the same identity or server key in the preferences, or with clever calls to the account manager. (Left as an exercise for the reader.)This will work but it is not supported. The UI will act slighty strange when you share information between accounts. The current plans prevent sharing of information between accounts using the UI.

Relevant API calls:

SMTP Servers

SMTP Servers are kept separately from all the other account management stuff. A user's SMTP servers are not actually dependant on any of the account settings. The only thing that determines which SMTP server a user should use is their physical connection to the internet. For instance, if a user is connected to the internet through MyISP, Inc. then he or she must use MyISP's SMTP server, no matter what identity they will be sending mail with.

The SMTP server list is accessable through the SMTP Service. You can add (and eventually delete) servers and have a default server.

SMTP servers are stored in your preferences in a manner resembling the accounts:

user_pref("mail.smtpservers", "server1,server2");
user_pref("mail.smtpserver.server1.hostname", "smtp.myisp.com");
user_pref("mail.smtpserver.server2.hostname", "smtp.mywork.com");
    

You can add new SMTP servers using the SMTP service.

var server = smtpService.createSmtpServer();
server.hostname = "smtp.myisp.com";
    

The default SMTP server is the first server in the list in your preferences. Currently, you can set the default SMTP server to something else by setting the defaultServer property on the smtpService, but that will not be saved to disk. Eventually there will be the concept of a session default server, and a permenant default server.

Relevant API calls:

Appendix A: Listing of all properties

(When brendan's idldoc comes along, I'll just link to that)

All preferences are strings, unless otherwise noted.

Account Manager

Pref: mail.accountmanager.accounts

Account

Preference: mail.account.account.server
IDL: nsIMsgAccount.incomingServer
The incoming server associated with this account. The preference is the preference "key" used, such as "server1".


Preference: mail.account.account.identities
IDL: nsIMsgAccount.identities
The list of identites associated with this account. The preference is a comma-seperated list of preference "keys" such as "identity1,identity2".

Incoming Servers

Preference: mail.server.server.type
: String id of the server type: pop3, nntp, imap, or local
Preference: mail.server.server.hostname - hostname of the server
Preference: mail.server.server.username - user login name
Preference: mail.server.server.password - user login password
Preference: mail.server.server.check_new_mail - boolean, should we check for new mail on a regular basis?
Preference: mail.server.server.check_time - integer, number of minutes between checks for new mail
Preference: mail.server.server.remember_password - boolean, should we remember the password?
Preference: mail.server.server.download_on_biff. - boolean, Should we download new messags on biff (true) or just alert user that there is new mail (false)
Preference: mail.server.server.directory - local platform-specific path to store messages and folder indexes
Preference: mail.server.server.name - User-visible name of server
The following are specific to IMAP:
Preference: mail.server.server.admin_url - administration URL for server
Preference: mail.server.server.using_subscription - boolean, should we use subscriptions? (i.e. use LSUB instead of LIST)
Preference: mail.server.server.cleanup_inbox_on_exit - boolean, should we purge the inbox when we quit?
Preference: mail.server.server.dual_use_folders - boolean - can folders contain both folders and messages?
Preference: mail.server.server.empty_trash_on_exit
boolean, (should not be imap-specific) - should we empty this server's trash when we quit?
Preference: mail.server.server.offline_download - boolean, is this server marked for offline download?
Preference: mail.server.server.override_namespaces - boolean, should we override namespaces on this server?
Preference: mail.server.server.max_cached_connections - integer, max number of connections left open to the server
Preference: mail.server.server.empty_trash_threshhold
integer, (should not be imap-specific) max k of wasted diskspace before we purge a folder
Preference: mail.server.server.delete_model - integer, delete model (move to trash, IMAP delete, purge immediately, not sure of values)
Preference: mail.server.server.timeout - integer, number of minutes a connection is idle before we drop it
Preference: mail.server.server.capability - list of capabilities of this server
Preference: mail.server.server.namespace.public - the server's namespace for public folders
Preference: mail.server.server.namespace.personal - the server's namespace for personal folders
Preference: mail.server.server.namespace.other_users - the server's namespace for other user's folders

The following are specific to POP:

Preference: mail.server.server.leave_on_server - boolean, should we leave messages on the server after we have downloaded them?
Preference: mail.server.server.delete_mail_left_on_server - boolean, when we delete a message locally, should we delete that message on the server?

The following are specific to news:

Preference: mail.server.server.newsrc.file - platform specific file path to newsrc file

Identities

Preference: mail.identity.identity.fullName - the user's full name, i.e. John Smith
Preference: mail.identity.identity.useremail - the user's e-mail address, i.e. jsmith@isp.com
Preference: mail.identity.identity.reply_to - reply to address during message composition, should only be used if different than useremail. (ReplyTo: header in mail messages)
Preference: mail.identity.identity.organization - User's organization (Organization: header in mail messages)
Preference: mail.identity.identity.compose_html - boolean, should we compose messages in HTML (true) or Plain Text (false)?
Preference: mail.identity.identity.attach_vcard - boolean, should we attach the vCard?
Preference: mail.identity.identity.attach_signature - boolean, should we attach the signature?
Preference: mail.identity.identity.fcc - boolean, should we keep a copy of messages in our sent folder?
Preference: mail.identity.identity.fcc_folder - URI of folder to put sent messages in
Preference: mail.identity.identity.bcc_self - boolean, should we blind carbon copy (BCC) this identity with each e-mail sent with this identity?
Preference: mail.identity.identity.bcc_other - boolean, should we BCC other e-mail addresses with each mail sent with this identity?
Preference: mail.identity.identity.bcc_other_list - comma-seperated list of other addresses to BCC
Preference: mail.identity.identity.draft_folder - URI of folder to use for drafts
Preference: mail.identity.identity.stationary_folder - URI of folder to use for stationary (called Templates in 4.x)
Preference: mail.identity.identity.spam_folder - URI of folder to use for SPAM (I think this is cut)