Difference between revisions of "Python API Wrapper Tutorial"

[unchecked revision][unchecked revision]
Line 8: Line 8:
  
 
Additionally you need the [ftp://ftp.mailstore.com/spe/python-api-library.zip MailStore API library] which has to be installed in your Python's site-packages directory.  The location of the site-packages directory can be found with the following command
 
Additionally you need the [ftp://ftp.mailstore.com/spe/python-api-library.zip MailStore API library] which has to be installed in your Python's site-packages directory.  The location of the site-packages directory can be found with the following command
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
 
  python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
 
+
</source>
 
= Getting Started =
 
= Getting Started =
  
Line 16: Line 16:
  
 
The library can be imported with
 
The library can be imported with
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  import mailstore
 
  import mailstore
 
+
</source>
 
You are able to instantiate the class directly
 
You are able to instantiate the class directly
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  speClient = mailstore.spe.Client(username="admin", password="admin", host="127.0.0.1", port=8470)
 
  speClient = mailstore.spe.Client(username="admin", password="admin", host="127.0.0.1", port=8470)
 
+
</source>
 
or by using the ''with'' statement (context manager)
 
or by using the ''with'' statement (context manager)
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  with mailstore.spe.Client(password="S3cR3t!", host="spe.domain.eu") as speClient:
 
  with mailstore.spe.Client(password="S3cR3t!", host="spe.domain.eu") as speClient:
 
     do_something()
 
     do_something()
 
+
</source>
 
Default values can be omitted.
 
Default values can be omitted.
  
 
The available log in arguments and default values are
 
The available log in arguments and default values are
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  username = "admin"
 
  username = "admin"
 
  password = "admin"
 
  password = "admin"
Line 40: Line 40:
 
  logLevel = 2
 
  logLevel = 2
 
  fileLogLevel = 0
 
  fileLogLevel = 0
 
+
</source>
 
When autoHandleToken is enabled, you do not have to care about long running processes, you just have to wait for the result. When this value is set to ''False'', then the status token is returned and you have to handle the token manually. More about this later.
 
When autoHandleToken is enabled, you do not have to care about long running processes, you just have to wait for the result. When this value is set to ''False'', then the status token is returned and you have to handle the token manually. More about this later.
  
The ''waitTime'' value specifies the value that is passed to the ''get-status'' call. When you call a long running method like ''VerifyStore()'', this is the maximum amount of milliseconds you have to wait for a status update.
+
The ''waitTime'' value specifies the value that is passed to the ''get-status'' call. When you call a long running method like ''VerifyStore'', this is the maximum amount of milliseconds you have to wait for a status update.
  
 
''logLevel'' and ''fileLogLevel'' have to be in the range ''0'' to ''4''. The loglevels are defined as following
 
''logLevel'' and ''fileLogLevel'' have to be in the range ''0'' to ''4''. The loglevels are defined as following
Line 57: Line 57:
 
== Log out ==
 
== Log out ==
  
When you prefer the first log in method, you have to log out afterwards manually. When using the context manager method, the log out is done automatically when exiting the ''with'' block.
+
When you prefer the first log in method, you have to log out afterwards manually. When using the context manager method, the log out is done automatically when exiting the ''with'' block. The ''logoutHandler'' will close open log files, if necessary.
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  speClient.logoutHandler()
 
  speClient.logoutHandler()
 
+
</source>
 
== Simple calls ==
 
== Simple calls ==
  
 
Simple calls will return immediately
 
Simple calls will return immediately
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  print(speClient.GetEnvironmentInfo())
 
  print(speClient.GetEnvironmentInfo())
 
   
 
   
 
  {'antiXsrfToken': 'dUubPmGWEANyDxGbBvejCu6qSRUlkQYSiunQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': {'userName': 'admin', 'copyright': 'Copyright (c) 2005-2013 MailStore Software GmbH', 'systemProperties': {'totalPhysicalMemory': 2146947072, 'processors': ['Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz'], 'operatingSystem': 'Microsoft Windows Server 2012 Standard'}, 'serverName': 'win2012spe', 'version': '8.5.0.9288', 'licenseeName': 'MailStore Software GmbH', 'licenseeID': 1}, 'statusVersion': 2, 'statusCode': 'succeeded'}
 
  {'antiXsrfToken': 'dUubPmGWEANyDxGbBvejCu6qSRUlkQYSiunQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': {'userName': 'admin', 'copyright': 'Copyright (c) 2005-2013 MailStore Software GmbH', 'systemProperties': {'totalPhysicalMemory': 2146947072, 'processors': ['Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz'], 'operatingSystem': 'Microsoft Windows Server 2012 Standard'}, 'serverName': 'win2012spe', 'version': '8.5.0.9288', 'licenseeName': 'MailStore Software GmbH', 'licenseeID': 1}, 'statusVersion': 2, 'statusCode': 'succeeded'}
 
+
</source>
 
When the ''statusCode'' is ''succeeded'' the information is stored in the ''result'' field. When the process has ended with another status, like ''failed'' or ''cancelled'' the diagnosis information is stored in the ''error'' field.
 
When the ''statusCode'' is ''succeeded'' the information is stored in the ''result'' field. When the process has ended with another status, like ''failed'' or ''cancelled'' the diagnosis information is stored in the ''error'' field.
  
 
When there are no HTTP errors, the returned value is always a python dictionary.
 
When there are no HTTP errors, the returned value is always a python dictionary.
 
print(speClient.GetUserInfo(instanceID="test01",userName="admin")["result"])
 
 
{'userName': 'admin', 'distinguishedName': None, 'privileges': ['admin'], 'pop3UserNames': [], 'authentication': 'integrated', 'fullName': 'admin', 'emailAddresses': []}
 
  
 
== Simple Examples ==
 
== Simple Examples ==
  
 
To get all user's detailed information you could
 
To get all user's detailed information you could
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  with mailstore.spe.Client("gerald", "s3cR3T1!", "speserver"):
 
  with mailstore.spe.Client("gerald", "s3cR3T1!", "speserver"):
 
     instance = "test01"
 
     instance = "test01"
 
     for user in speClient.GetUsers(instance)["result"]:
 
     for user in speClient.GetUsers(instance)["result"]:
 
         print(speClient.GetUserInfo(instance, user["userName"])["result"])
 
         print(speClient.GetUserInfo(instance, user["userName"])["result"])
 
+
</source>
 
== Long Running Calls ==
 
== Long Running Calls ==
  
 
Long running calls like ''VerifyStore'' do not return the result immediately, but a status token instead. Set ''autoHandleToken'' to ''False'' to get the token.
 
Long running calls like ''VerifyStore'' do not return the result immediately, but a status token instead. Set ''autoHandleToken'' to ''False'' to get the token.
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
 
     instID = "test01"
 
     instID = "test01"
Line 96: Line 92:
 
   
 
   
 
  {'antiXsrfToken': '6h8HV67XSak+jpQ/e6X1ehLOrt9cPUGicfHQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': 'sa6431dcd1b3e48c4719cfe8a75612b88a', 'result': None, 'statusVersion': 0, 'statusCode': 'running'}
 
  {'antiXsrfToken': '6h8HV67XSak+jpQ/e6X1ehLOrt9cPUGicfHQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': 'sa6431dcd1b3e48c4719cfe8a75612b88a', 'result': None, 'statusVersion': 0, 'statusCode': 'running'}
 
+
</source>
One could pass the token to the ''HandleToken()'' method, then the behaviour is exactly the same, as when you would have set ''autoHandleToken=True''.
+
One could pass the token to the ''HandleToken'' method, then the behavior is exactly the same, as when you would have set ''autoHandleToken=True''.
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
     instID="test01"
+
     instID = "test01"
     storeID=38
+
     storeID = 38
 
     token = client.VerifyStore(instID, storeID)
 
     token = client.VerifyStore(instID, storeID)
 
     print(client.HandleToken(token))
 
     print(client.HandleToken(token))
 
   
 
   
 
  {'antiXsrfToken': 'KIMJdCpjcuD8O5+xPislG8OysJ0fPgXQcvHQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n  389 messages verified...\r\nFinished. No errors have been found.\r\n', 'statusText': None, 'error': None, 'percentProgress': 100, 'token': 'sa8e56590b28b3c57f076168d5913840df', 'result': None, 'statusVersion': 147, 'statusCode': 'succeeded'}
 
  {'antiXsrfToken': 'KIMJdCpjcuD8O5+xPislG8OysJ0fPgXQcvHQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n  389 messages verified...\r\nFinished. No errors have been found.\r\n', 'statusText': None, 'error': None, 'percentProgress': 100, 'token': 'sa8e56590b28b3c57f076168d5913840df', 'result': None, 'statusVersion': 147, 'statusCode': 'succeeded'}
 
+
</source>
Alternatively one could pass the token to the ''HandleTokenIter()'' method, then every status update is yielded.
+
Alternatively one could pass the token to the ''HandleTokenIter'' method, then every status update is yielded.
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
     instID="test01"
+
     instID = "test01"
     storeID=38
+
     storeID = 38
 
     for status in client.HandleTokenIter(client.VerifyStore(instID, storeID)):
 
     for status in client.HandleTokenIter(client.VerifyStore(instID, storeID)):
 
         print(status)
 
         print(status)
 
   
 
   
 
  {'antiXsrfToken': 'DEF2dWnoNl7hkgsHqApPZmpsUqEgpih6c/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n', 'statusText': None, 'error': None, 'percentProgress': 0, 'token': 'safd22a51408925dd787ef43a5adc3772c', 'result': None, 'statusVersion': 5, 'statusCode': 'running'}
 
  {'antiXsrfToken': 'DEF2dWnoNl7hkgsHqApPZmpsUqEgpih6c/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n', 'statusText': None, 'error': None, 'percentProgress': 0, 'token': 'safd22a51408925dd787ef43a5adc3772c', 'result': None, 'statusVersion': 5, 'statusCode': 'running'}
 
 
  {'antiXsrfToken': 'a3NMb7VdnLaTOOnfyJnZWEutbmlzPXd6c/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 6, 'statusCode': 'running'}
 
  {'antiXsrfToken': 'a3NMb7VdnLaTOOnfyJnZWEutbmlzPXd6c/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 6, 'statusCode': 'running'}
 
  {'antiXsrfToken': 'mi8qpqTdw6hoH+/+o6h65Rx0jiuPR4p6c/HQCGFkbWlu', 'logOutput': '  100 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 7, 'statusCode': 'running'}
 
  {'antiXsrfToken': 'mi8qpqTdw6hoH+/+o6h65Rx0jiuPR4p6c/HQCGFkbWlu', 'logOutput': '  100 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 7, 'statusCode': 'running'}
 
 
  [...]
 
  [...]
 
+
</source>
 
== Cancelling long running calls ==
 
== Cancelling long running calls ==
  
If you want to cancel a long running call, you have to pass the token of that call to the ''CancelAsync()'' method
+
If you want to cancel a long running call, you have to pass the token of that call to the ''CancelAsync'' method
  
import mailstore
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  import time
 
  import time
 
   
 
   
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
 
  with mailstore.spe.Client(autoHandleToken=False) as client:
     instID="test01"
+
     instID = "test01"
     storeID=38
+
     storeID = 38
 
     token = client.VerifyStore(instID, storeID)
 
     token = client.VerifyStore(instID, storeID)
 
     time.sleep(2)
 
     time.sleep(2)
Line 140: Line 134:
 
  {'antiXsrfToken': 'DUs5EO8ZZ9A8S6lUB/uYwIsAFwTufVpCd/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': None, 'statusVersion': None, 'statusCode': None}
 
  {'antiXsrfToken': 'DUs5EO8ZZ9A8S6lUB/uYwIsAFwTufVpCd/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': None, 'statusVersion': None, 'statusCode': None}
 
  {'antiXsrfToken': 'fYO6hoP7eKr1X1SDj++6hhwI9pTwD45Dd/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n3893 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 7, 'token': None, 'result': None, 'statusVersion': 17, 'statusCode': 'cancelled'}
 
  {'antiXsrfToken': 'fYO6hoP7eKr1X1SDj++6hhwI9pTwD45Dd/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n3893 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 7, 'token': None, 'result': None, 'statusVersion': 17, 'statusCode': 'cancelled'}
 
+
</source>
 
== Pretty Printing the output ==
 
== Pretty Printing the output ==
  
 
There is a helper function that formats the returned values in more readable manner.
 
There is a helper function that formats the returned values in more readable manner.
 
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  mailstore.spe.pprint(client.GetUserInfo("test01","admin"))
 
  mailstore.spe.pprint(client.GetUserInfo("test01","admin"))
 
   
 
   
Line 160: Line 154:
 
  emailAddresses statusVersion 2
 
  emailAddresses statusVersion 2
 
  statusCode succeeded
 
  statusCode succeeded
 +
</source>

Revision as of 08:53, 7 February 2014

This document introduces the Python API library which allows you to administer your MailStore Service Provider Edition via Python.

Installation

The API library is tested against Python 3.2 to Python 3.4. It is compatible with the 32bit and the 64bit versions of Python.

You can get your Python binary from the Python download page or you can install it using the package manager of you distribution.

Additionally you need the MailStore API library which has to be installed in your Python's site-packages directory. The location of the site-packages directory can be found with the following command

 python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"

Getting Started

Log in

The library can be imported with

 import mailstore

You are able to instantiate the class directly

 speClient = mailstore.spe.Client(username="admin", password="admin", host="127.0.0.1", port=8470)

or by using the with statement (context manager)

 with mailstore.spe.Client(password="S3cR3t!", host="spe.domain.eu") as speClient:
     do_something()

Default values can be omitted.

The available log in arguments and default values are

 username = "admin"
 password = "admin"
 host = "127.0.0.1"
 port = 8470
 autoHandleToken = True
 waitTime = 2000
 logLevel = 2
 fileLogLevel = 0

When autoHandleToken is enabled, you do not have to care about long running processes, you just have to wait for the result. When this value is set to False, then the status token is returned and you have to handle the token manually. More about this later.

The waitTime value specifies the value that is passed to the get-status call. When you call a long running method like VerifyStore, this is the maximum amount of milliseconds you have to wait for a status update.

logLevel and fileLogLevel have to be in the range 0 to 4. The loglevels are defined as following

0 : "NONE"
1 : "ERROR"
2 : "WARNING"
3 : "INFO" 
4 : "DEBUG"

Log entries will be printed to stdout. The logfile will be created in the user's %temp% directory and starts with the prefix MailStorePyLib.

Log out

When you prefer the first log in method, you have to log out afterwards manually. When using the context manager method, the log out is done automatically when exiting the with block. The logoutHandler will close open log files, if necessary.

 speClient.logoutHandler()

Simple calls

Simple calls will return immediately

 print(speClient.GetEnvironmentInfo())
 
 {'antiXsrfToken': 'dUubPmGWEANyDxGbBvejCu6qSRUlkQYSiunQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': {'userName': 'admin', 'copyright': 'Copyright (c) 2005-2013 MailStore Software GmbH', 'systemProperties': {'totalPhysicalMemory': 2146947072, 'processors': ['Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz'], 'operatingSystem': 'Microsoft Windows Server 2012 Standard'}, 'serverName': 'win2012spe', 'version': '8.5.0.9288', 'licenseeName': 'MailStore Software GmbH', 'licenseeID': 1}, 'statusVersion': 2, 'statusCode': 'succeeded'}

When the statusCode is succeeded the information is stored in the result field. When the process has ended with another status, like failed or cancelled the diagnosis information is stored in the error field.

When there are no HTTP errors, the returned value is always a python dictionary.

Simple Examples

To get all user's detailed information you could

 with mailstore.spe.Client("gerald", "s3cR3T1!", "speserver"):
     instance = "test01"
     for user in speClient.GetUsers(instance)["result"]:
         print(speClient.GetUserInfo(instance, user["userName"])["result"])

Long Running Calls

Long running calls like VerifyStore do not return the result immediately, but a status token instead. Set autoHandleToken to False to get the token.

 with mailstore.spe.Client(autoHandleToken=False) as client:
     instID = "test01"
     storeID = 1
     print(client.VerifyStore(instID, storeID))
 
 {'antiXsrfToken': '6h8HV67XSak+jpQ/e6X1ehLOrt9cPUGicfHQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': 'sa6431dcd1b3e48c4719cfe8a75612b88a', 'result': None, 'statusVersion': 0, 'statusCode': 'running'}

One could pass the token to the HandleToken method, then the behavior is exactly the same, as when you would have set autoHandleToken=True.

 with mailstore.spe.Client(autoHandleToken=False) as client:
     instID = "test01"
     storeID = 38
     token = client.VerifyStore(instID, storeID)
     print(client.HandleToken(token))
 
 {'antiXsrfToken': 'KIMJdCpjcuD8O5+xPislG8OysJ0fPgXQcvHQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n  389 messages verified...\r\nFinished. No errors have been found.\r\n', 'statusText': None, 'error': None, 'percentProgress': 100, 'token': 'sa8e56590b28b3c57f076168d5913840df', 'result': None, 'statusVersion': 147, 'statusCode': 'succeeded'}

Alternatively one could pass the token to the HandleTokenIter method, then every status update is yielded.

 with mailstore.spe.Client(autoHandleToken=False) as client:
     instID = "test01"
     storeID = 38
     for status in client.HandleTokenIter(client.VerifyStore(instID, storeID)):
         print(status)
 
 {'antiXsrfToken': 'DEF2dWnoNl7hkgsHqApPZmpsUqEgpih6c/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n389 messages are about to be verified.\r\nVerifying...\r\n', 'statusText': None, 'error': None, 'percentProgress': 0, 'token': 'safd22a51408925dd787ef43a5adc3772c', 'result': None, 'statusVersion': 5, 'statusCode': 'running'}
 {'antiXsrfToken': 'a3NMb7VdnLaTOOnfyJnZWEutbmlzPXd6c/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 6, 'statusCode': 'running'}
 {'antiXsrfToken': 'mi8qpqTdw6hoH+/+o6h65Rx0jiuPR4p6c/HQCGFkbWlu', 'logOutput': '  100 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 1, 'token': None, 'result': None, 'statusVersion': 7, 'statusCode': 'running'}
 [...]

Cancelling long running calls

If you want to cancel a long running call, you have to pass the token of that call to the CancelAsync method

 import time
 
 with mailstore.spe.Client(autoHandleToken=False) as client:
     instID = "test01"
     storeID = 38
     token = client.VerifyStore(instID, storeID)
     time.sleep(2)
     print(client.CancelAsync(token))
     time.sleep(2)
     print(client.GetStatus(token))
 
 {'antiXsrfToken': 'DUs5EO8ZZ9A8S6lUB/uYwIsAFwTufVpCd/HQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': None, 'result': None, 'statusVersion': None, 'statusCode': None}
 {'antiXsrfToken': 'fYO6hoP7eKr1X1SDj++6hhwI9pTwD45Dd/HQCGFkbWlu', 'logOutput': 'Verifying file group #38...\r\nCreating a list of messages to be verified...\r\n3893 messages are about to be verified.\r\nVerifying...\r\n  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 7, 'token': None, 'result': None, 'statusVersion': 17, 'statusCode': 'cancelled'}

Pretty Printing the output

There is a helper function that formats the returned values in more readable manner.

 mailstore.spe.pprint(client.GetUserInfo("test01","admin"))
 
 antiXsrfToken tfrgvinkGOkjWgSCSV72UZY/1qkfwEGIdfHQCGFkbWlu
 logOutput None
 statusText None
 error None
 percentProgress None
 token None
 result userName admin
 distinguishedName None
 privileges admin
 pop3UserNames authentication integrated
 fullName admin
 emailAddresses statusVersion 2
 statusCode succeeded