Difference between revisions of "Python API Wrapper Tutorial"

[unchecked revision][unchecked revision]
Line 1: Line 1:
 
__NOTOC__
 
__NOTOC__
 +
<p class=msnote>'''Important notice:''' The Python API wrapper for the MailStore Service Provider Edition Management API provided on this website, represents an example implementation of an API client. This wrapper should help system administrators and developers to quickly understand how the Management API of MailStore SEP works and how to use it in own scripts. Please understand that beyond this documentation no further support for the Python API wrapper is provided.</p>
  
This document introduces the Python API library which allows you to administer your MailStore Service Provider Edition via Python.
+
This document explains the installation and usage of the Python API wrapper for the MailStore SPE Management API. In order to prevent loss of data, service interruption or other problems, it is highly recommended to use a non-productive test environment for this tutorial as well as for script development in general. The 30-day-trial version of MailStore Server is perfectly suited for this.
  
 
== Installation ==
 
== 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.  
+
The API wrapper library is tested against Python 3.2 to Python 3.4 and is compatible with 32bit and 64bit versions of Python.  
  
You can get your Python binary from the [http://www.python.org/download/ Python download page] or you can install it using the package manager of you distribution.
+
Python binaries for various operating systems can be downloaded from the [http://www.python.org/download/ Python download page] or installed using the package manager of most Linux distributions.
 +
 
 +
Additionally the [ftp://ftp.mailstore.com/pub/Scripts/Python/v9/python-api-wrapper.zip Python API wrapper library] has to be installed in the ''mailstore'' subdirectory of Python's site-packages directory. The location of the site-packages directory can be found by executing the following command:
  
Additionally you need the [ftp://ftp.mailstore.com/pub/Scripts/Python/Python-MailStore-API-Wrapper.zip MailStore API library] which has to be installed in your Python's site-packages ''mailstore'' 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">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
+
python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
 
</source>
 
</source>
  
== Log in ==
+
== Instantiating the API Client ==
The library can be imported with
+
Before the API wrapper library can be used, it must first be imported with:
 +
 
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
  import mailstore
 
  import mailstore
 
</source>
 
</source>
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)
 
</source>
 
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:
 
    do_something()
 
</source>
 
Default values can be omitted.
 
  
The available log in arguments and default values are
+
Now the ''mailstore.spe.Client'' class can be instantiated as follows:
 +
 
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
username = "admin"
+
serverClient = mailstore.spe.Client(username="admin", password="admin", host="127.0.0.1", port=8463)
password = "admin"
 
host = "127.0.0.1"
 
port = 8470
 
autoHandleToken = True
 
waitTime = 2000
 
logLevel = 2
 
fileLogLevel = 0
 
 
</source>
 
</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.
 
  
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.
+
Default values can be omitted. The default admin credentials (username and password set to ''admin'') are only usable when connecting from the MailStore Server computer itself to ''localhost''. Find a listing of all default values in the following table:
  
''logLevel'' and ''fileLogLevel'' have to be in the range ''0'' to ''4''. The loglevels are defined as following
+
{| class="wikitable"
0 : "NONE"
+
! width="150px" | Parameter
1 : "ERROR"
+
! width="100px" | Default Value
2 : "WARNING"
+
! Description
3 : "INFO"
+
|-
4 : "DEBUG"
+
| <tt>username</tt>
 +
| admin
 +
| Username used for connecting to the API.
 +
|-
 +
| <tt>password</tt>
 +
| admin
 +
| Password used for connecting to the API.
 +
|-
 +
| <tt>host</tt>
 +
| 127.0.0.1
 +
| Hostname or IP address of MailStore SPE Management Server.
 +
|-
 +
| <tt>port</tt>
 +
| 8463
 +
| TCP port on which the Management Server is listening for API requests.
 +
|-
 +
| <tt>autoHandleToken</tt>
 +
| True
 +
| If set to ''True'', the caller does not need to handle tokens of long running tasks, but instead has to wait for the result. When set to ''False'' and the ''statusCode'' is ''running'', a status token is returned and must be handled appropriately by the caller of the method. Further details about token handling is described the corresponding section [[#Automatic Token Handling|Automatic Token Handling]] of this document.
 +
|-
 +
| <tt>waitTime</tt>
 +
| 1000
 +
| Specifies the number of milliseconds the API should wait for a final result. Otherwise the process is treated as ''running'', in which case token handling as defined by the status of ''autoHandleToken'' becomes necessary.
 +
|-
 +
| <tt>callbackStatus</tt>
 +
| None
 +
| Name of callback function to which interim statuses of long running tasks should be passed. This allows keeping track of the tasks' progress even if  ''autoHandleToken'' is enabled. This can be quite useful in order to notify users about the progress without having to deal with the token logic as a whole.
 +
|-
 +
| <tt>logLevel</tt>
 +
| 2
 +
| Has to be in the range ''0'' to ''4'', where 0 (''NONE'') has the lowest verbosity and 4 (''DEBUG'') the highest. The loglevels are defined in the following order (low to high verbosity) ''NONE'', ''ERROR'', ''WARNING'', ''INFO'' and ''DEBUG''. Log entries will always be printed to ''stdout''.
 +
|}
  
Log entries will be printed to ''stdout''.
+
== Invoking API Method ==
The logfile will be created in the user's %temp% directory and starts with the prefix ''MailStorePyLib''. ''logLevel'' and ''fileLogLevel'' do not have to match.
+
After the API client has been successfully instantiated, API methods can easily be invoked. When the method call was successful, the ''statusCode'' is ''succeeded'' and the result is stored in the dictionary ''result'' as shown in the following example:
  
== 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.
 
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
speClient.logoutHandler()
+
print(speClient.GetEnvironmentInfo()["result"])
</source>
 
= Simple calls =
 
 
 
Simple calls will return immediately
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
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'}
+
{'userName': 'admin', 'systemProperties': {'operatingSystem': 'Microsoft Windows Server 2012 R2 Standard', 'totalPhysicalMemory': 2146942976, 'processors': ['Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz']}, 'licenseeID': 10435, 'version': '9.0.3.9873', 'licenseeName': 'MailStore Software GmbH', 'copyright': 'Copyright (c) 2005-2014 MailStore Software GmbH', 'serverName': 'win-2012-r2-x64'}
 
</source>
 
</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 there are no HTTP errors, the returned value is always a python dictionary.
+
If ''autoHandleToken'' was set to ''False'' and the ''statusCode'' returns ''running'', manual token handling is required as described in the [[#Auto Handle Token|Automatic Token Handling]] section.
  
== Simple examples ==
+
For any other ''statusCode'' value than ''succeeded'' and ''running'' the occurrence of an error has to be assumed, in which further information such as the error message and error details are available in the dictionary ''error'' as shown below:
  
To get all user's detailed information you could
 
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
with mailstore.spe.Client():
+
userInfo = spieClient.GetUserInfo("example", "john.doe")
    instance = "test01"
+
 
    for user in speClient.GetUsers(instance)["result"]:
+
if userInfo["statusCode"] == 'succeeded':
        print(speClient.GetUserInfo(instance, user["userName"])["result"])
+
    print(userInfo["result"]["emailAddresses"])
 +
else:
 +
    print(userInfo["error"]["message"])
 
</source>
 
</source>
  
A list with all assigned email address can be retrieved with
+
=== Examples ===
 +
Create a list of all email addresses assigned to MailStore users.
 +
 
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
with mailstore.spe.Client() as client:
+
instanceID = "example"
    instID = "test01"
+
emailAddresses = list()
    emailaddresses = list()
+
for user in speClient.GetUsers(instanceID)["result"]:
    for user in client.GetUsers(instID)["result"]:
+
emailAddresses += speClient.GetUserInfo(instanceID, user["userName"])["result"]["emailAddresses"]
        info = client.GetUserInfo(instID, user["userName"])["result"]
+
print(emailAddresses)
        emailaddresses += info['emailAddresses']
 
    print(emailaddresses)
 
 
</source>
 
</source>
  
== Long running calls ==
+
== Long Running Tasks ==
Long running calls like ''VerifyStore'' are running asynchronous on the instance. When ''autoHandleToken'' is set to ''True'' (default), the library polls the status in the background automatically and will return the final result when the process has ended. Set ''autoHandleToken'' to ''False'' to get the token. In this case you have to handle the token by yourself. There are helper methods available.
+
The execution of certain API methods like ''VerifyStore'' may take several minutes or even hours until it finishes. There are different options available to deal with these long running tasks:
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
 
with mailstore.spe.Client(autoHandleToken=False) as client:
+
# [[#Automatic Token Handling|Automatic Token Handling]]
    instID = "test01"
+
# [[#Automatic Token Handling with Callback Function|Automatic Token Handling with Callback Function]]
    storeID = 1
+
# [[#Manual Token Handling|Manual Token Handling]]
    print(client.VerifyStore(instID, storeID))
+
 
+
Generally it is recommended to expect that every method call can become a long running task, as this depends on the ''waitTime'' value, the called method but also the overall load on the server. Thus it is not advisable to globally turn of automatic token handling when instantiating the API client.
{'antiXsrfToken': '6h8HV67XSak+jpQ/e6X1ehLOrt9cPUGicfHQCGFkbWlu', 'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': None, 'token': 'sa6431dcd1b3e48c4719cfe8a75612b88a', 'result': None, 'statusVersion': 0, 'statusCode': 'running'}
+
 
</source>
+
If desired, automatic token handling can be enabled or disabled for each invoked method by adding ''autoHandleToken=True'' to the method's argument list.
 +
 
 +
Once a method has been invoked with manual token handling or a callback function, it can be cancelled by using the ''CancelAsync'' method as described in [[#Cancelling Long Running Tasks|Cancelling Long Running Tasks]].
 +
 
 +
=== Automatic Token Handling ===
 +
When ''autoHandleToken'' is set to ''True'' (default), the wrapper polls the status of long running tasks automatically in the background and will return the final result when the process has ended.
  
You are able to update the status manually by passing the token to the ''GetStatus'' method. The call has finished, when the ''statusCode'' has changed from ''running'' to something else.
+
==== Code ====
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
with mailstore.spe.Client(autoHandleToken=False) as client:
+
import mailstore
    instID = "test01"
 
    storeID = 1
 
    token = client.VerifyStore(instID, storeID))
 
    time.sleep(5)
 
    print(client.GetStatus(token))
 
  
{'antiXsrfToken': '+MKktayBhloqEsqk3xNTssdwTHRxL5+UaPTQCGFkbWlu', 'logOutput': '  100 messages verified...\r\n  200 messages verified...\r\n  300 messages verified...\r\n  400 messages verified...\r\n  500 messages verified...\r\n  600 messages verified...\r\n  700 messages verified...\r\n', 'statusText': None, 'error': None, 'percentProgress': 17, 'token': 'sa92c717e75db26fa57fc09c5e95f7096d', 'result': None, 'statusVersion': 29, 'statusCode': 'running'}
+
speClient = mailstore.spe.Client(autoHandleToken=True)
</source>
+
instanceID = "example"
One could pass the token to the ''HandleToken'' method, then the behavior is exactly the same, as when you would have set ''autoHandleToken=True''.
+
storeID = 1
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
print(speClient.VerifyStore(instanceID, storeID))
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'}
 
</source>
 
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:
 
    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'}
 
[...]
 
 
</source>
 
</source>
  
You are able to set the token handling behavior globally and locally. When you instantiate the client with ''autoHandleToken=True'' you still are able to call every long running method with ''autoHandleToken=False'' and vice versa. Methods that do not return a token, do not accecpt the ''autoHandleToken'' parameter.
+
==== Output ====
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
<source lang="text" smart-tabs="true" toolbar="false" gutter="false">
with mailstore.spe.Client(autoHandleToken=True) as client:
+
{'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': 100, 'token': 'd242d822a59bd4db308eef8b85af7d2a', 'result': None, 'statusVersion': 71, 'statusCode': 'succeeded'}
    instID = "test01"
 
    client.MaintainFileSystemDatabases(instID, autoHandleToken=False)
 
 
</source>
 
</source>
  
== Cancelling long running calls ==
+
=== Automatic Token Handling with Callback Function ===
If you want to cancel a long running call, you have to pass the token of that call to the ''CancelAsync'' method
+
If a caller wants to keep track of the progress of a long running task (i.e. to inform the user about the progress), although automatic token handling was enabled, he could pass the name of a function as ''callbackStatus'' argument to the instance of the API client.
  
 +
==== Code ====
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
import time
+
import mailstore
 
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'}
 
</source>
 
  
== Pretty Printing the output ==
+
def showProgress(progress):
There is a helper function that formats the returned values in more readable manner.
+
  print(progress["logOutput"], end="", flush=True)
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
mailstore.pprint(client.GetUserInfo("test01","admin"))
 
  
antiXsrfToken lVKkLrjBXeg7KcjdZ/n6050bpfdAILI9F/3QCGFkbWlu
+
speClient = mailstore.spe.Client(autoHandleToken=True, callbackStatus=showProgress)
result
+
instanceID = "example"
    userName    admin
+
storeID = 2
    privileges
+
print(speClient.VerifyStore(instanceID, storeID))
      admin
 
    authentication    integrated
 
    fullName    admin
 
statusVersion 2
 
statusCode succeeded
 
 
</source>
 
</source>
  
== The CallMethod method ==
+
==== Output ====
The signature of the CallMethod method is
+
<source lang="text" smart-tabs="true" toolbar="false" gutter="false">
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
Verifying file group #3...
CallMethod(self, methodname, arguments = {}, autoHandleToken = None)
+
Creating a list of messages to be verified...
 +
1249 messages are about to be verified.
 +
Verifying...
 +
  100 messages verified...
 +
  200 messages verified...
 +
  300 messages verified...
 +
  400 messages verified...
 +
  500 messages verified...
 +
  600 messages verified...
 +
  700 messages verified...
 +
  800 messages verified...
 +
  900 messages verified...
 +
  1000 messages verified...
 +
  1100 messages verified...
 +
  1200 messages verified...
 +
  1249 messages verified.
 +
Finished. No errors have been found.
 +
{'error': None, 'result': None, 'logOutput': '  1000 messages verified...\r\n  1100 messages verified...\r\n  1200 messages verified...\r\n  1249 messages verified.\r\nFinished. No errors have been found.\r\n', 'token': 'c56f032d9db263133c1a413f79744b84', 'statusVersion': 71, 'statusText': None, 'percentProgress': 100, 'statusCode': 'succeeded'}
 
</source>
 
</source>
  
This is the most low-level method available. You are able to send "raw" commands to this method.
+
=== Manual Token Handling ===
 +
If ''autoHandleToken'' is set to ''False'' the caller must handle long running tasks and the corresponding tokens all by itself. To poll for status updates, the ''GetStatus'' method must be called periodically passing the last returned result as parameter. ''GetStatus'' will extract the status token itself, poll for the latest update and return the received data to the caller again. The main call has finished when the ''statusCode'' changes to something different than ''running''. Calling ''GetStatus'' without passing a status token will result in an exception.
  
== Function overview ==
+
==== Code ====
All the methods listed in [[Management_API_-_Function_Reference|Function Reference]] are implemented.
+
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 +
import mailstore
 +
import time
  
=== Replacement methods ===
+
serverClient = mailstore.server.Client(autoHandleToken=False)
Some original methods do require a ''config'' or ''properties'' object as parameter.
+
storeID = 3
This API library also wraps some of these methods so you can use regular named parameters.
+
status = speClient.VerifyStore(instanceID, storeID)
  
E.g. the method ''CreateSystemAdministrator'' has the signature
+
while True:
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
    if status["statusCode"] != "running":
CreateSystemAdministrator(self, config, password)
+
        break
 +
    print(status["logOutput"], end="", flush=True)
 +
    status = speClient.GetStatus(status)
 +
    time.sleep(1)
 
</source>
 
</source>
  
The replacement method has the signature
+
==== Output ====
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
<source lang="text" smart-tabs="true" toolbar="false" gutter="false">
CreateSystemAdministrator2(self, userName, fullName=None, password=None)
+
Verifying file group #3...
 +
Creating a list of messages to be verified...
 +
1249 messages are about to be verified.
 +
Verifying...
 +
  100 messages verified...
 +
  200 messages verified...
 +
  300 messages verified...
 +
  400 messages verified...
 +
  500 messages verified...
 +
  600 messages verified...
 +
  700 messages verified...
 +
  800 messages verified...
 +
  900 messages verified...
 +
  1000 messages verified...
 +
  1100 messages verified...
 +
  1200 messages verified...
 +
  1249 messages verified.
 +
Finished. No errors have been found.
 
</source>
 
</source>
  
the config object is created as follows and then passed to ''CreateSystemAdministrator'' along with the ''password'' parameter.
+
=== Cancelling Long Running Tasks ===
 +
Tasks invoked by using the callback method or manual token handling, can be canceled at any time by using the ''CancelAsync'' method. Please notice that the API does not acknowledge the success of the cancellation request. Instead the caller must continue to monitor the ''statusCode'' of the canceled method.
 +
 
 +
==== Code ====
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
 
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
config = json.dumps({"userName": userName, "fullName": fullName})
+
import mailstore
 +
import time
 +
 
 +
serverClient = mailstore.spe.Client(autoHandleToken=False)
 +
instanceID = "example"
 +
storeID = 3
 +
status = speClient.VerifyStore(instanceID, storeID)
 +
 
 +
while True:
 +
    if status["statusCode"] != "running":
 +
        break
 +
    print(status["logOutput"], end="", flush=True)
 +
    status = speClient.GetStatus(status)
 +
    time.sleep(1)
 +
    speClient.CancelAsync(status)
 
</source>
 
</source>
  
The available replacement methods are
+
==== Output ====
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
<source lang="text" smart-tabs="true" toolbar="false" gutter="false">
SetComplianceConfiguration2(self, instanceID, globalRetentionTimeYears=None, adminEmailPreviewEnabled=None, legalHoldEnabled=None, logSuccessfulUserActivities = None)
+
Verifying file group #3...
SetIndexConfiguration2(self, instanceID, extensions)
+
Creating a list of messages to be verified...
SetStoreAutoCreateConfiguration2(self, instanceID, enabled=True, interval="none", sizeThreshold=None, numberOfMessagesThreshold=500000, baseDirectory=None)
+
1249 messages are about to be verified.
CreateClientAccessServer2(self, serverName, port, thumbprint)
+
Verifying...
CreateInstance2(self, instanceID, instanceHost, startMode, baseDirectory, alias=None, displayName=None, debugLogEnabled="false", vssWriterEnabled="false")
+
  100 messages verified...
SetInstanceConfiguration2(self, instanceID, alias=None, displayName=None, instanceHost=None, startMode=None, baseDirectory=None, debugLogEnabled=None, vssWriterEnabled=None)
+
  200 messages verified...
CreateInstanceHost2(self, serverName, port, thumbprint, baseDirectory)
+
  300 messages verified...
CreateSystemAdministrator2(self, userName, fullName=None, password=None)
+
  400 messages verified...
UpdateClientAccessServerConfiguration2(self, serverName, port, thumbprint)
+
  500 messages verified...
UpdateInstanceHostConfiguration2(self, serverName, port, thumbprint, baseDirectory)
+
  600 messages verified...
UpdateSystemAdministratorConfiguration2(self, userName, fullName=None)
+
  700 messages verified...
 +
  800 messages verified...
 +
  900 messages verified...
 +
  1000 messages verified...
 +
  1100 messages verified...
 
</source>
 
</source>
  
No replacement methods are currently available for the following methods
+
== Methods Overview ==
<source lang="python" smart-tabs="true" toolbar="false" gutter="false">
+
All methods listed in the [[Management API - Function Reference|function reference]] are implemented in the Python API library. Use
CreateProfile(self, instanceID, properties, raw="true")
+
 
RunTemporaryProfile(self, instanceID, properties, raw="true", autoHandleToken=None)
+
  pydoc3 mailstore.spe
SetDirectoryServicesConfiguration(self, instanceID, config)
 
</source>
 
  
=== Additional methods ===
+
to access the build in documentation, which also includes an overview of all methods and their parameters.
There are additional methods available. Please see the source code for further details.
 

Revision as of 09:31, 3 September 2014

Important notice: The Python API wrapper for the MailStore Service Provider Edition Management API provided on this website, represents an example implementation of an API client. This wrapper should help system administrators and developers to quickly understand how the Management API of MailStore SEP works and how to use it in own scripts. Please understand that beyond this documentation no further support for the Python API wrapper is provided.

This document explains the installation and usage of the Python API wrapper for the MailStore SPE Management API. In order to prevent loss of data, service interruption or other problems, it is highly recommended to use a non-productive test environment for this tutorial as well as for script development in general. The 30-day-trial version of MailStore Server is perfectly suited for this.

Installation

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

Python binaries for various operating systems can be downloaded from the Python download page or installed using the package manager of most Linux distributions.

Additionally the Python API wrapper library has to be installed in the mailstore subdirectory of Python's site-packages directory. The location of the site-packages directory can be found by executing the following command:

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

Instantiating the API Client

Before the API wrapper library can be used, it must first be imported with:

 import mailstore

Now the mailstore.spe.Client class can be instantiated as follows:

serverClient = mailstore.spe.Client(username="admin", password="admin", host="127.0.0.1", port=8463)

Default values can be omitted. The default admin credentials (username and password set to admin) are only usable when connecting from the MailStore Server computer itself to localhost. Find a listing of all default values in the following table:

Parameter Default Value Description
username admin Username used for connecting to the API.
password admin Password used for connecting to the API.
host 127.0.0.1 Hostname or IP address of MailStore SPE Management Server.
port 8463 TCP port on which the Management Server is listening for API requests.
autoHandleToken True If set to True, the caller does not need to handle tokens of long running tasks, but instead has to wait for the result. When set to False and the statusCode is running, a status token is returned and must be handled appropriately by the caller of the method. Further details about token handling is described the corresponding section Automatic Token Handling of this document.
waitTime 1000 Specifies the number of milliseconds the API should wait for a final result. Otherwise the process is treated as running, in which case token handling as defined by the status of autoHandleToken becomes necessary.
callbackStatus None Name of callback function to which interim statuses of long running tasks should be passed. This allows keeping track of the tasks' progress even if autoHandleToken is enabled. This can be quite useful in order to notify users about the progress without having to deal with the token logic as a whole.
logLevel 2 Has to be in the range 0 to 4, where 0 (NONE) has the lowest verbosity and 4 (DEBUG) the highest. The loglevels are defined in the following order (low to high verbosity) NONE, ERROR, WARNING, INFO and DEBUG. Log entries will always be printed to stdout.

Invoking API Method

After the API client has been successfully instantiated, API methods can easily be invoked. When the method call was successful, the statusCode is succeeded and the result is stored in the dictionary result as shown in the following example:

print(speClient.GetEnvironmentInfo()["result"])
 
{'userName': 'admin', 'systemProperties': {'operatingSystem': 'Microsoft Windows Server 2012 R2 Standard', 'totalPhysicalMemory': 2146942976, 'processors': ['Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz']}, 'licenseeID': 10435, 'version': '9.0.3.9873', 'licenseeName': 'MailStore Software GmbH', 'copyright': 'Copyright (c) 2005-2014 MailStore Software GmbH', 'serverName': 'win-2012-r2-x64'}

If autoHandleToken was set to False and the statusCode returns running, manual token handling is required as described in the Automatic Token Handling section.

For any other statusCode value than succeeded and running the occurrence of an error has to be assumed, in which further information such as the error message and error details are available in the dictionary error as shown below:

userInfo = spieClient.GetUserInfo("example", "john.doe")

if userInfo["statusCode"] == 'succeeded':
    print(userInfo["result"]["emailAddresses"])
else:
    print(userInfo["error"]["message"])

Examples

Create a list of all email addresses assigned to MailStore users.

instanceID = "example"
emailAddresses = list()
for user in speClient.GetUsers(instanceID)["result"]:
	emailAddresses += speClient.GetUserInfo(instanceID, user["userName"])["result"]["emailAddresses"]
print(emailAddresses)

Long Running Tasks

The execution of certain API methods like VerifyStore may take several minutes or even hours until it finishes. There are different options available to deal with these long running tasks:

  1. Automatic Token Handling
  2. Automatic Token Handling with Callback Function
  3. Manual Token Handling

Generally it is recommended to expect that every method call can become a long running task, as this depends on the waitTime value, the called method but also the overall load on the server. Thus it is not advisable to globally turn of automatic token handling when instantiating the API client.

If desired, automatic token handling can be enabled or disabled for each invoked method by adding autoHandleToken=True to the method's argument list.

Once a method has been invoked with manual token handling or a callback function, it can be cancelled by using the CancelAsync method as described in Cancelling Long Running Tasks.

Automatic Token Handling

When autoHandleToken is set to True (default), the wrapper polls the status of long running tasks automatically in the background and will return the final result when the process has ended.

Code

import mailstore

speClient = mailstore.spe.Client(autoHandleToken=True)
instanceID = "example"
storeID = 1
print(speClient.VerifyStore(instanceID, storeID))

Output

{'logOutput': None, 'statusText': None, 'error': None, 'percentProgress': 100, 'token': 'd242d822a59bd4db308eef8b85af7d2a', 'result': None, 'statusVersion': 71, 'statusCode': 'succeeded'}

Automatic Token Handling with Callback Function

If a caller wants to keep track of the progress of a long running task (i.e. to inform the user about the progress), although automatic token handling was enabled, he could pass the name of a function as callbackStatus argument to the instance of the API client.

Code

import mailstore

def showProgress(progress):
   print(progress["logOutput"], end="", flush=True)

speClient = mailstore.spe.Client(autoHandleToken=True, callbackStatus=showProgress)
instanceID = "example"
storeID = 2
print(speClient.VerifyStore(instanceID, storeID))

Output

Verifying file group #3...
Creating a list of messages to be verified...
1249 messages are about to be verified.
Verifying...
  100 messages verified...
  200 messages verified...
  300 messages verified...
  400 messages verified...
  500 messages verified...
  600 messages verified...
  700 messages verified...
  800 messages verified...
  900 messages verified...
  1000 messages verified...
  1100 messages verified...
  1200 messages verified...
  1249 messages verified.
Finished. No errors have been found.
{'error': None, 'result': None, 'logOutput': '  1000 messages verified...\r\n  1100 messages verified...\r\n  1200 messages verified...\r\n  1249 messages verified.\r\nFinished. No errors have been found.\r\n', 'token': 'c56f032d9db263133c1a413f79744b84', 'statusVersion': 71, 'statusText': None, 'percentProgress': 100, 'statusCode': 'succeeded'}

Manual Token Handling

If autoHandleToken is set to False the caller must handle long running tasks and the corresponding tokens all by itself. To poll for status updates, the GetStatus method must be called periodically passing the last returned result as parameter. GetStatus will extract the status token itself, poll for the latest update and return the received data to the caller again. The main call has finished when the statusCode changes to something different than running. Calling GetStatus without passing a status token will result in an exception.

Code

import mailstore
import time

serverClient = mailstore.server.Client(autoHandleToken=False)
storeID = 3
status = speClient.VerifyStore(instanceID, storeID)

while True:
    if status["statusCode"] != "running":
        break
    print(status["logOutput"], end="", flush=True)
    status = speClient.GetStatus(status)
    time.sleep(1)

Output

Verifying file group #3...
Creating a list of messages to be verified...
1249 messages are about to be verified.
Verifying...
  100 messages verified...
  200 messages verified...
  300 messages verified...
  400 messages verified...
  500 messages verified...
  600 messages verified...
  700 messages verified...
  800 messages verified...
  900 messages verified...
  1000 messages verified...
  1100 messages verified...
  1200 messages verified...
  1249 messages verified.
Finished. No errors have been found.

Cancelling Long Running Tasks

Tasks invoked by using the callback method or manual token handling, can be canceled at any time by using the CancelAsync method. Please notice that the API does not acknowledge the success of the cancellation request. Instead the caller must continue to monitor the statusCode of the canceled method.

Code

import mailstore
import time

serverClient = mailstore.spe.Client(autoHandleToken=False)
instanceID = "example"
storeID = 3
status = speClient.VerifyStore(instanceID, storeID)

while True:
    if status["statusCode"] != "running":
        break
    print(status["logOutput"], end="", flush=True)
    status = speClient.GetStatus(status)
    time.sleep(1)
    speClient.CancelAsync(status)

Output

Verifying file group #3...
Creating a list of messages to be verified...
1249 messages are about to be verified.
Verifying...
  100 messages verified...
  200 messages verified...
  300 messages verified...
  400 messages verified...
  500 messages verified...
  600 messages verified...
  700 messages verified...
  800 messages verified...
  900 messages verified...
  1000 messages verified...
  1100 messages verified...

Methods Overview

All methods listed in the function reference are implemented in the Python API library. Use

 pydoc3 mailstore.spe

to access the build in documentation, which also includes an overview of all methods and their parameters.