Brad Hards | 4 Jan 12:02 2011
Picon

[openchange]server stuff - thoughts on properties

Hi,

I've been working on getting the server back running for mapistore_v2 branch, 
and one idea that seems quite useful is to treat all the folder information we 
need to add as just a set of named properties.

So if we need a mailbox GUID and mailbox replica GUID, we could just store 
those as properties on the mailbox root folder. The backend operation would 
just be the standard op_getprops. I'm currently working on an implementation 
that does this for mailbox properties.

However I recognise that the properties are a scarce resource (only 16 bit 
space, 15 bits for the direct ids and 15 bits for the named properties). 
However we don't need to use the same space as the wire protocol for this.

That led to thinking about the best way to handle properties (both direct ID 
and named properties). It occurs to me that we could perhaps handle all 
properties using a larger space (perhaps 48 bits for property "number" + 16 
bits for property type) which would include a GUID index (for the property 
namespace) together with either the property number or a name index.

So on receipt of the property tag from the client, we'd map that into a server 
representation. That could make lookup of LID pretty easy, and might be able 
to be shared across the whole server. Each user would still have a mapping for 
their 16 bit property ids.

Thoughts about the treatment of folder characteristics as generic properties?

Thoughts about the best way to manage the properties space?

(Continue reading)

Li Jing | 18 Jan 02:57 2011

[openchange]eventpool file descriptor don't release

Hi,

I use MAPI in my multithreading program. Because I want to monitor many mailbox, so in order to reduce the number of file descriptor and connection.  After each request , call API MAPIUninitialize. When I check by lsof, many eventpool file descriptor leak, even in a single thread environment.  How can I deal with it.

The calling sequence as follows:

MAPIInitialize->MapiLogonEx->OpenMsgStore->...->mapi_object_release->MAPIUninitialize
 
 
--
李京
电话:13466355456
海阔凭鱼跃,天高任鸟飞。


_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel
Brad Hards | 18 Jan 04:07 2011
Picon

Re: [openchange]eventpool file descriptor don't release

On Tuesday, January 18, 2011 12:57:08 pm Li Jing wrote:
> The calling sequence as follows:
> 
> MAPIInitialize->MapiLogonEx->OpenMsgStore->...->mapi_object_release->MAPIUn
> initialize
Can you show a simple compilable example that reproduces the problem?

Brad

[BTW: I got your private email, but your provider won't accept mail that 
doesn't have SPF.]
Li Jing | 18 Jan 06:13 2011

Re: [openchange]eventpool file descriptor don't release

Thanks for your kind reply. The attachment is a simple example show eventpool file descriptor leak, please check, thanks.
Run following command compile this example.
 # gcc -Wall -I /usr/local/samba/include/ exmain.c -L /usr/local/samba/lib/ -lmapi
 # ./a.out
 # lsof -p $(pgrep a.out) 
 
 
>> The calling sequence as follows:
>> 
>> MAPIInitialize->MapiLogonEx->OpenMsgStore->...->mapi_object_release->MAPIUn
>> initialize
>Can you show a simple compilable example that reproduces the problem?
>
>Brad
>
>[BTW: I got your private email, but your provider won't accept mail that 
>doesn't have SPF.]


_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel
Li Jing | 18 Jan 06:20 2011

Re: [openchange]eventpool file descriptor don't release


Thanks for your kind reply. The attachment is a simple example show eventpool file descriptor leak, please check, thanks.
Run following command compile this example.
 # gcc -Wall -I /usr/local/samba/include/ exmain.c -L /usr/local/samba/lib/ -lmapi
 # ./a.out
 # lsof -p $(pgrep a.out) 
 
 
>> The calling sequence as follows:
>> 
>> MAPIInitialize->MapiLogonEx->OpenMsgStore->...->mapi_object_release->MAPIUn
>> initialize
>Can you show a simple compilable example that reproduces the problem?
>
>Brad
>
>[BTW: I got your private email, but your provider won't accept mail that 
>doesn't have SPF.]




#include <unistd.h>
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>

#include <talloc.h>
#include <libmapi/libmapi.h>

// # gcc -Wall -I /usr/local/samba/include/ exmain.c -L /usr/local/samba/lib/ -lmapi
// # ./a.out
// # lsof -p $(pgrep a.out)

#define DEFAULT_PROFDB_LOCATION             "/tmp"
#define DEFAULT_PROFDB_FILE                 "profiles.ldb"
#define DEFAULT_EXCHANGE_VERSION_NUMBER     0


struct exClient {
	char            username[32];      // generated by email
	char            password[32];
	char            serverip[20];
	char            emailaddress[48];  // hesine <at> hesine.exchange.com	
	char            *profname;         // equal to username
	char            *profdb;           // generated by domain
	char            *domain;           // generated by emailaddress
	unsigned int    n_curmailcount;

	struct mapi_context	            *m_mapi_ctx;   // MAPI context
	struct mapi_session             *m_session;    // Login Session	
};

void init_exclient(struct exClient *oclient)
{
	memset (oclient->username, 0, sizeof(oclient->username));
	memset (oclient->password, 0, sizeof(oclient->password));
	memset (oclient->emailaddress, 0, sizeof(oclient->emailaddress));
	memset (oclient->serverip, 0, sizeof(oclient->serverip));

	oclient->profname         = NULL;
	oclient->profdb           = NULL;
	oclient->domain           = NULL;
	oclient->n_curmailcount   = -1;

	oclient->m_mapi_ctx       = NULL;
	oclient->m_session        = NULL;	
}

int gen_exclient(struct exClient* oclient,
	const char* emailaddress, const char* password, const char* serveraddr,
	const char* profdb_location)
{
	strncpy (oclient->emailaddress, emailaddress, sizeof(oclient->emailaddress));
	strncpy (oclient->password, password, sizeof(oclient->password));
	strncpy (oclient->serverip, serveraddr, sizeof(oclient->serverip));

	int length;
	const char* delim = " <at> ";
	char  profbuffer[256] = "\0", email[64] = "\0", *p;
	strncpy (email, emailaddress, sizeof(email));
	if ((p = strtok (email, delim)) != NULL) {
		strncpy (oclient->username, p, sizeof(oclient->username));
	}
	
	oclient->profname = oclient->username;
	if ((oclient->domain= strpbrk (oclient->emailaddress, delim)) != NULL) {
		oclient->domain++;
	}
	else {
		printf("email:%s Invalid mail address !", emailaddress);
		return 1;
	}

	if (profdb_location != NULL) {
		sprintf (profbuffer, "%s/%s.%s", profdb_location, oclient->domain, DEFAULT_PROFDB_FILE);
	}
	else {
		sprintf (profbuffer, "%s/%s.%s", DEFAULT_PROFDB_LOCATION, oclient->domain, DEFAULT_PROFDB_FILE);
	}		
	length = strlen(profbuffer);
	oclient->profdb = malloc (length+1);
	strcpy (oclient->profdb, profbuffer);
	oclient->profdb[length] = 0;

	return 0;
}

void dump_exclient(const struct exClient* oclient)
{
	printf ("\n");
	printf ("username       : %s\n", oclient->username);
	printf ("password       : %s\n", oclient->password);
	printf ("serverip       : %s\n", oclient->serverip);
	printf ("email          : %s\n", oclient->emailaddress);
	printf ("profname       : %s\n", oclient->profname);
	printf ("profdb         : %s\n", oclient->profdb);
	printf ("domain         : %s\n", oclient->domain);
}

static uint32_t callback(struct SRowSet *rowset, void *private)
{
	uint32_t		  i;
	struct SPropValue *lpProp;
	const char		  *label = "username checked matches several usernames, select the first one";

	printf("Warning: %s:", label);
	for (i = 0; i < rowset->cRows; i++) {
		lpProp = get_SPropValue_SRow(&(rowset->aRow[i]), PR_DISPLAY_NAME);
		if (lpProp && lpProp->value.lpszA) {
			printf("\t[%u] %s", i, lpProp->value.lpszA);
		}
	}
	
	return 0;
}

bool profcreate(const struct exClient * oclient, uint32_t flags)
{
	enum MAPISTATUS		retval;
	struct mapi_context	*mapi_ctx;
	struct mapi_session	*session = NULL;
	TALLOC_CTX		*mem_ctx;
	struct mapi_profile	profile;
	const char		*locale;
	uint32_t		cpid;
	uint32_t		lcid;
	char			*cpid_str;
	char			*lcid_str;
	char            workstation[128] = "\0";
	char			exchange_version_str[8];

	mem_ctx = talloc_named(NULL, 0, "profcreate");

	retval = MAPIInitialize(&mapi_ctx, oclient->profdb);
	if (retval != MAPI_E_SUCCESS) {
		printf ("email:%s <profcreate> MAPIInitialize error: 0x%X\n", oclient->emailaddress,retval);
		talloc_free(mem_ctx);
		return false;
	}

	/* Sanity check */
	retval = OpenProfile(mapi_ctx, &profile, oclient->profname, NULL);
	if (retval == MAPI_E_SUCCESS) {
		printf("email:%s <profcreate> profile \"%s\" already exists\n", oclient->emailaddress,oclient->profname);
		MAPIUninitialize(mapi_ctx);
		talloc_free(mem_ctx);
		return true;
	}

	retval = CreateProfile(mapi_ctx, oclient->profname, oclient->username, oclient->password, flags);
	if (retval != MAPI_E_SUCCESS) {
		printf ("email:%s <profcreate> CreateProfile error: 0x%X\n", oclient->emailaddress,retval);
		MAPIUninitialize(mapi_ctx);
		talloc_free(mem_ctx);
		return false;
	}

	gethostname(workstation, sizeof(workstation));
	sprintf (exchange_version_str, "%d", DEFAULT_EXCHANGE_VERSION_NUMBER);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "binding", oclient->serverip);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "domain",  oclient->domain);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "workstation", workstation);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "seal", "false");
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "exchange_version", exchange_version_str);

	locale = mapi_get_system_locale();
	if (locale) {
		cpid = mapi_get_cpid_from_locale(locale);
		lcid = mapi_get_lcid_from_locale(locale);
	}

	if (!locale || !cpid || !lcid) {
		printf("email:%s <profcreate> Invalid Language supplied or unknown system language\nDeleting profile\n",oclient->emailaddress);
		if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) != MAPI_E_SUCCESS) {
			printf("email:%s <profcreate> DeleteProfile error: 0x%X\n", oclient->emailaddress,retval);
		}
		talloc_free(mem_ctx);
		MAPIUninitialize(mapi_ctx);
		return false;
	}

	cpid_str = talloc_asprintf(mem_ctx, "%d", cpid);
	lcid_str = talloc_asprintf(mem_ctx, "0x%.4x", lcid);

	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "codepage", cpid_str);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "language", lcid_str);
	mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "method", lcid_str);

	talloc_free(cpid_str);
	talloc_free(lcid_str);

	retval = MapiLogonProvider(mapi_ctx, &session, oclient->profname, oclient->password, PROVIDER_ID_NSPI);
	if (retval != MAPI_E_SUCCESS) {
		printf("email:%s <profcreate> MapiLogonProvider error: 0x%X\nDeleting profile\n", oclient->emailaddress,retval);
		if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) != MAPI_E_SUCCESS) {
			printf("email:%s <profcreate> DeleteProfile error: 0x%X\n", oclient->emailaddress,retval);
		}
		MAPIUninitialize(mapi_ctx);
		talloc_free(mem_ctx);

		return false;
	}

	retval = ProcessNetworkProfile(session, oclient->username, (mapi_profile_callback_t) callback, NULL);
	if (retval != MAPI_E_SUCCESS && retval != 0x1) {
		printf("email:%s <profcreate> ProcessNetworkProfile error: 0x%X\nDeleting profile\n", oclient->emailaddress,retval);
		if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) != MAPI_E_SUCCESS) {
			printf("email:%s <profcreate> DeleteProfile error: 0x%X\n", oclient->emailaddress,retval);
		}
		MAPIUninitialize(mapi_ctx);
		talloc_free(mem_ctx);
		return false;
	}

	MAPIUninitialize(mapi_ctx);
	talloc_free(mem_ctx);	
	return true;
}

bool proflookup(const struct exClient * oclient)
{
	enum MAPISTATUS     retval;
	struct mapi_context *mapi_ctx;
	struct mapi_profile profile;

	if ((retval = MAPIInitialize(&mapi_ctx, oclient->profdb)) != MAPI_E_SUCCESS) {
		printf("email:%s <proflookup> MAPIInitialize error : 0x%X\n", oclient->emailaddress,retval);
		return false;
	}

	retval  = OpenProfile(mapi_ctx, &profile, oclient->profname, NULL);
	if (retval != MAPI_E_SUCCESS) {
		MAPIUninitialize(mapi_ctx);
		if(retval != MAPI_E_INVALID_PARAMETER) {
			printf("email:%s <proflookup> OpenProfile error : 0x%X\n", oclient->emailaddress,retval);
		}
		else 
			printf("email:%s <proflookup> OpenProfile error : MAPI_E_INVALID_PARAMETER\n",oclient->emailaddress);
		return false;
	}

	MAPIUninitialize(mapi_ctx);
	return true;
}


int loginserver(struct exClient *oclient)
{
	enum MAPISTATUS                 retval;
	bool                            need_profcreate = false;
	
	// Check profile database exists
	if (access(oclient->profdb, F_OK) != 0) {
		need_profcreate = true;
	}
	// Check specific user's profile exists
	if (!proflookup(oclient) != 0) {
		need_profcreate = true;
	}
	// If profile database or specific user's profile not exist, create it
	if (need_profcreate) {
		if (!profcreate(oclient, 0)) {
			printf ("email:%s <loginserver> create profile failed.\n", oclient->emailaddress);
			return -1;
		}
		else {
			printf ("Profile \"%s\" completed and added to database.\n",	oclient->profname);
		}
	}

	// Initialize MAPI
	retval = MAPIInitialize(&(oclient->m_mapi_ctx), oclient->profdb);
	if (retval != MAPI_E_SUCCESS) {
		printf ("email:%s <loginserver> Initialize MAPI failed: 0x%X\n", oclient->emailaddress,retval);
		return -1;
	}

	// Log on EMSMDB and NSPI
	retval = MapiLogonEx(oclient->m_mapi_ctx, &(oclient->m_session), oclient->profname, NULL);
	if (retval != MAPI_E_SUCCESS) {
		MAPIUninitialize(oclient->m_mapi_ctx);
		printf("email:%s <loginserver> Logon EMSMDB and NSPI failed: 0x%X\n", oclient->emailaddress,retval);
		return -1;
	}
	
	return 0;
}


int fetchmail(struct exClient *oclient)
{
	enum MAPISTATUS                 retval;
	TALLOC_CTX                      *mem_ctx;
	mapi_id_t						id_inbox;
	
	mapi_object_t                   obj_store;	
	mapi_object_t					obj_inbox;
	mapi_object_t					obj_table;
	
	struct SRowSet					rowset;
	struct SPropTagArray			*SPropTagArray;

	uint32_t			            i, ret=0, mailcount=0, newmail=0;
	const uint64_t		            *mid;
	const char	       	            *subject;
	char                            subject_show[10] = "\0";

	mem_ctx = talloc_named(NULL, 0, "fetchmail");

	printf ("email:%s Fetch mail from exchange server, Open Message Store.\n", oclient->emailaddress);
	// Open Message Store
	mapi_object_init(&obj_store);
	retval = OpenMsgStore(oclient->m_session, &obj_store);
	if (retval != MAPI_E_SUCCESS) {
		talloc_free(mem_ctx);
		printf("email:%s <fetchmail> OpenMsgStore error: 0x%X\n", oclient->emailaddress,retval);
		return 1;
	}

	// Find Inbox default folder
	retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
	if (retval != MAPI_E_SUCCESS) {
		mapi_object_release(&obj_store);
		talloc_free(mem_ctx);
		printf("email:%s <fetchmail> GetDefaultFolder error: 0x%X\n", oclient->emailaddress,retval);
		return 1;
	}

	// Open Inbox folder
	mapi_object_init(&obj_inbox);
	retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
	if (retval != MAPI_E_SUCCESS) {
		mapi_object_release(&obj_store);
		talloc_free(mem_ctx);
		printf("email:%s <fetchmail> OpenFolder error: 0x%X\n", oclient->emailaddress,retval);
		return 1;
	}

	// Retrieve Inbox content table
	mapi_object_init(&obj_table);
	retval = GetContentsTable(&obj_inbox, &obj_table, 0, &mailcount);
	if (retval != MAPI_E_SUCCESS) {
		mapi_object_release(&obj_inbox);
		mapi_object_release(&obj_store);		
		talloc_free(mem_ctx);
		printf("email:%s <fetchmail> GetContentsTable error: 0x%X\n", oclient->emailaddress,retval);
		return 1;
	}
	if (mailcount<=oclient->n_curmailcount || oclient->n_curmailcount==-1) {
		ret = 0;
		if (oclient->n_curmailcount == -1) oclient->n_curmailcount = mailcount; // first login
		if (mailcount < oclient->n_curmailcount) {
			oclient->n_curmailcount = mailcount; // update current mail count
			printf ("email:%s Current inbox mail count: %d, DECREASED\n", oclient->emailaddress, mailcount);
		}
		else {
			printf ("email:%s Current inbox mail count: %d, UNCHANGED\n", oclient->emailaddress, mailcount);
		}
		goto end;
	}
	
	newmail = mailcount - oclient->n_curmailcount;
	oclient->n_curmailcount = mailcount;
	printf ("email:%s Current inbox mail count: %d, %d New Mail:\n",oclient->emailaddress, mailcount, newmail);

	// Create the MAPI table view
	SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_MID, PR_SUBJECT);
	retval = SetColumns(&obj_table, SPropTagArray);
	MAPIFreeBuffer(SPropTagArray);
	if (retval != MAPI_E_SUCCESS) {
		ret = 1;
		printf("email:%s <fetchmail> SetColumns error: 0x%X\n", oclient->emailaddress,retval);
		goto end;
	}

	// Iterate through rows 
	while ((retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &rowset)) 
		!= -1 && rowset.cRows) {
		int n = newmail<rowset.cRows ? newmail : rowset.cRows;
		for (i = 0; i < n; i++) {
			mid 	= (const uint64_t *)find_SPropValue_data(&rowset.aRow[i], PR_MID);
			subject = (const char *)find_SPropValue_data(&rowset.aRow[i], PR_SUBJECT);
			if (subject == NULL)
				strcpy(subject_show, "null");
			else 
				strncpy(subject_show, subject, 6);
			if (strlen (subject_show) == 6) {
				strcat (subject_show, "...");
				subject_show[9] = 0;
			}				
			printf("  subject: %s [MID: 0x%016"PRIx64"]\n", subject_show, mid?*mid:0);
		}
	}
	
end:
	// Note: release sequence is very important
	mapi_object_release(&obj_table);
	mapi_object_release(&obj_inbox);
	mapi_object_release(&obj_store);
	talloc_free(mem_ctx);

	MAPIUninitialize(oclient->m_mapi_ctx);
	
	return ret;
}

void* simple_thread(void* param)
{

	struct exClient* client = (struct exClient*)param;

	dump_exclient(client);
	while (true) {
		if (loginserver(client) != 0) break;
		if (fetchmail(client) != 0)   break;

		sleep (5);
	}
	return NULL;
}

int main(int argc, char *argv[])
{
	struct exClient oclient;
	init_exclient(&oclient);
	if (gen_exclient (&oclient, "hesine01 <at> hesine.exchange.com", "hesine-01", "172.27.235.199", NULL))
		return 1;
	dump_exclient(&oclient);

	pthread_t      th;
	pthread_attr_t thattr;
	pthread_attr_init(&thattr);
	pthread_create(&th, &thattr, simple_thread, &oclient);

	pthread_join (th, NULL);	

	return 0;
}

_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel
Emilio Campos | 20 Jan 14:28 2011
Picon

[openchange]how works exchange connectors and routes

Hi, I was reading on the web, but I can`t see, I would like ask about openchange and other exchange server communications.

We have a big organization with exchange 5.5, We would like use openchange with exchange servers, exchange server 5.5 configures a lot of connectors and routes with weight between servers, I would like to know how send openchange mails to other exchange servers?

can Openchange works with x400, x500 protocol communication or can use smtp connection?

Thanks!

--
Load balancer distribution - Open Source Project
http://zenloadbalancer.sourceforge.net
Distribution list (subscribe): zenloadbalancer-support <at> lists.sourceforge.net

_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel
Brad Hards | 20 Jan 18:12 2011
Picon

Re: [openchange]how works exchange connectors and routes

On Thu, 20 Jan 2011 05:28:38 am Emilio Campos wrote:
> Hi, I was reading on the web, but I can`t see, I would like ask about
> openchange and other exchange server communications.
This is partly dependent on the backend server implementation. So if you're 
using the SoGo backend, this might be better asked of the SoGo server people.

> We have a big organization with exchange 5.5, We would like use openchange
> with exchange servers, exchange server 5.5 configures a lot of connectors
> and routes with weight between servers, I would like to know how send
> openchange mails to other exchange servers?
SMTP is the standard for transfer for all kinds of mail. You can manage 
routing at the TCP/IP level and at the DNS level (using MX records). 

> can Openchange works with x400, x500 protocol communication or can use smtp
> connection?
I don't know of any backend that does X.400/X.500 at the moment, but (given 
development effort) it should be possible. 

Brad
Emilio Campos | 20 Jan 18:24 2011
Picon

Re: [openchange]how works exchange connectors and routes

Brad Thank you!

The last question.
I just reading on the web, but I can`t read much more about openchange and your operative, In my company we are thinking about migrate from exchange to openchange, we like the operative of client outlook with calendar, notes, mails but we do not like  microsoft support, I would like to know If are there any application, scripts or other methods for migrate exchange accounts from exchange servers to new accounts on openchage servers?

Regards!

2011/1/20 Brad Hards <bradh <at> frogmouth.net>
On Thu, 20 Jan 2011 05:28:38 am Emilio Campos wrote:
> Hi, I was reading on the web, but I can`t see, I would like ask about
> openchange and other exchange server communications.
This is partly dependent on the backend server implementation. So if you're
using the SoGo backend, this might be better asked of the SoGo server people.

> We have a big organization with exchange 5.5, We would like use openchange
> with exchange servers, exchange server 5.5 configures a lot of connectors
> and routes with weight between servers, I would like to know how send
> openchange mails to other exchange servers?
SMTP is the standard for transfer for all kinds of mail. You can manage
routing at the TCP/IP level and at the DNS level (using MX records).

> can Openchange works with x400, x500 protocol communication or can use smtp
> connection?
I don't know of any backend that does X.400/X.500 at the moment, but (given
development effort) it should be possible.

Brad
_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel



--
Load balancer distribution - Open Source Project
http://zenloadbalancer.sourceforge.net
Distribution list (subscribe): zenloadbalancer-support <at> lists.sourceforge.net

_______________________________________________
devel mailing list
devel <at> lists.openchange.org
http://mailman.openchange.org/listinfo/devel
Brad Hards | 20 Jan 18:29 2011
Picon

Re: [openchange]how works exchange connectors and routes

On Thu, 20 Jan 2011 09:24:37 am Emilio Campos wrote:
> I would like to know
> If are there any application, scripts or other methods for migrate
> exchange accounts from exchange servers to new accounts on openchage
> servers?
Not at this stage. We can do some transfers, but not bulk-move an entire 
server. We do (or course) plan to do this type of thing in the longer term, 
but such tools do not currently exist.

I would caution you that openchange server isn't ready for production at this 
stage. The current releases are developer preview / technology preview only, 
and there are significant known issues.

Brad

Gmane