Hallo, i wrote simple script to make auto signatures for Univention users for Kopano.
script use part of old kopano script to write data.
All info for signature stored in LDAP (Univention)
Also for greeting record i use univentionUMCProperty field with format “signature=some text”
script should be run on kopano server.
with “overwrite” argument it will overwrite all signatures.
signature.py
#!/usr/bin/env python3
# pylint: disable=E1101
#by Konstatin Frank
import datetime
import collections
import ldap
import html
from MAPI.Util import *
import sys
import time
# Try simplejson if json is not available
try:
import json
except ImportError:
import simplejson as json
LDAP_IP = "192.168.XX.XX"
LDAP_PORT = "7389"
LDAP_USER = "uid=search_ldap,cn=users,dc=domain,dc=local"
LDAP_PASSWORD = "XXXXXXXXXXXXXXx"
LDAP_USERS = "cn=users,dc=domain,dc=local"
TEST_USER = "test"
TEMPLATE_FILE = "signature.html"
#LDAP SEARCH VERIABLES
ATTR_MAIL = "mailPrimaryAddress"
ATTR_USER_DISABLED = "shadowExpire"
ATTR_UID = "uid"
ATTR_TEL = "telephoneNumber"
ATTR_POSITION = "departmentNumber"
ATTR_FULL_NAME = "displayName"
ATTR_IF_KOPANO_ACCOUNT = "kopanoAccount"
#Title can be used for some reasons. for example ppa.
# it will be add at start to user full name. it can be empty
ATTR_TITLE = "title"
# WARNING! I using" univentionUMCProperty" LDAP ATTRIBUTE to write users greetings. univentionUMCProperty
# can has many records in format "value_name=value". For greeting i use value "signature"
ATTR_GREETING = "univentionUMCProperty"
ATTR_GREETING_VALUE = "signature"
# If user has no greeting record script will use default greeting.
DEFAULT_GREETING = "Mit freundlichen Grüßen / Best regards"
PR_EC_WEBACCESS_SETTINGS_JSON = PROP_TAG(PT_STRING8, PR_EC_BASE + 0x72)
def check_input():
overwrite = False
if len(sys.argv) > 1:
if sys.argv[1] == "overwrite":
overwrite = True
return overwrite
def read_settings(username):
data = None
#username = sys.argv[1]
try:
s = OpenECSession(username, '', 'file:///var/run/kopano/server.sock')
st = GetDefaultStore(s)
except MAPIErrorNotFound as e:
print('User {} has no user store ({})'.format(username, e))
return
except MAPIErrorLogonFailed as e:
print('User {} not found (on this server) ({})'.format(username, e))
return
try:
settings = st.OpenProperty(PR_EC_WEBACCESS_SETTINGS_JSON, IID_IStream, 0, 0)
data = settings.Read(33554432)
except Exception as e:
# Return empty config tree
data = '{"settings": {"zarafa": {"v1": {"contexts": {"mail": {}}}}}}'
return data
def write_settings(data, username):
s = OpenECSession(username, '', 'file:///var/run/kopano/server.sock')
st = GetDefaultStore(s)
settings = st.OpenProperty(PR_EC_WEBACCESS_SETTINGS_JSON, IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE)
settings.SetSize(0)
settings.Seek(0, STREAM_SEEK_END)
writesettings = settings.Write(data.encode('utf-8'))
if writesettings:
print('Writing settings for user {}'.format(username))
settings.Commit(0)
else:
print('Writing Default Signature for user {} failed.'.format(username))
def ldap_connection_init():
global connect
try:
connect = ldap.initialize('ldap://{}:{}'.format(LDAP_IP, LDAP_PORT))
connect.set_option(ldap.OPT_REFERRALS, 0)
connect.simple_bind_s(LDAP_USER, LDAP_PASSWORD)
except Exception as error_msg:
return error_msg
return connect
def update(dic, upd):
# input dict and dixct update.
# update dict with new users and sort it
for share, users in upd.items():
if isinstance(users, collections.Mapping):
for key, value in dic.get(share, {}).items():
if key == next(iter(users)):
users[next(iter(users))].extend(value)
users[next(iter(users))] = list(set(users[next(iter(users))]))
#users[next(iter(users))].sort()
dic[share] = update(dic.get(share, {}), users)
else:
dic[share] = users
return dic
def html_decode(string):
string = string.decode('utf-8')
#.encode('ascii', 'xmlcharrefreplace').decode
#decode("windows-1252")
#.decode('utf-8')
#.encode('ascii', 'xmlcharrefreplace').decode('de_DE.utf8')
return string
def get_users():
ldap_querry = connect.search_s(
LDAP_USERS,
ldap.SCOPE_SUBTREE,
'objectClass=organizationalPerson',
[ATTR_UID, ATTR_FULL_NAME , ATTR_USER_DISABLED, ATTR_GREETING, ATTR_TEL, ATTR_POSITION, ATTR_IF_KOPANO_ACCOUNT, ATTR_TITLE, ATTR_MAIL])
output = {}
for key, value in ldap_querry:
shadow_expire = value.get(ATTR_USER_DISABLED, '')
if shadow_expire:
continue
user_mail = value.get(ATTR_MAIL)
#skip if user has no email
if user_mail:
user_mail = str(user_mail[0].decode("utf-8"))
else:
continue
uid = value.get(ATTR_UID, '')
uid = html_decode(uid[0])
#skip for administrator
if uid == 'Administrator':
continue
#if not uid == TEST_USER:
# continue
#skip if user has no kopano enabled.
kopanoAccount = value.get(ATTR_IF_KOPANO_ACCOUNT)
if not kopanoAccount:
continue
kopanoAccount = str(kopanoAccount[0].decode())
if not kopanoAccount == '1':
continue
#skip if user has no full name
user_name = value.get(ATTR_FULL_NAME, '')
if not user_name:
continue
user_name = html_decode(user_name[0])
title = value.get(ATTR_TITLE, '')
if title:
title = html_decode(title[0])
user_name = "{} {}".format(title, user_name)
user_position = value.get(ATTR_POSITION)
if user_position:
user_position = str(user_position[0].decode("utf-8"))
#skip if user has no position
else:
continue
#signature = False
univentionUMCProperty = value.get(ATTR_GREETING)
if univentionUMCProperty:
for i in univentionUMCProperty:
i = str(i. decode("utf-8"))
if i.split("=")[0] == ATTR_GREETING_VALUE:
user_greet = i.split("=")[1]
continue
else:
user_greet=html.unescape(DEFAULT_GREETING)
else:
user_greet=html.unescape(DEFAULT_GREETING)
user_tel = value.get(ATTR_TEL)
if user_tel:
user_tel = str(user_tel[0].decode("utf-8"))
else:
user_tel = '0'
#list
dic = {uid: [user_name, user_tel, user_position, user_greet, user_mail]}
output.update(dic)
return output
def main():
#ldap connection
ldap_connection_init()
#get users info from ldap
users = get_users()
#read signature template
signaturefile = open(TEMPLATE_FILE, 'r')
signaturehtml = signaturefile.read()
#start writing
for uid, value in users.items():
user_signature = signaturehtml.format(name=value[0], tel=value[1], position=value[2], signature=value[3], mail=value[4])
time.sleep(1)
data = read_settings(uid)
signatureid = '1'
signaturename = u'WebApp Default Signature'
signature_content = dict({u'name': signaturename, u'content': user_signature, u'isHTML': True})
if data:
#print(uid, type(data))
if not type(data) == str:
webappsettings = json.loads(data.decode('utf-8'))
else:
webappsettings = json.loads(data)
if not len(webappsettings['settings']['zarafa']['v1']['contexts']['mail']):
print("WebApp settings are empty.")
print("Adding config tree.")
webappsettings['settings']['zarafa']['v1']['contexts']['mail'] = dict({})
if u'signatures' not in list(webappsettings['settings']['zarafa']['v1']['contexts']['mail']):
print("Adding Signature settings to config tree.")
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures'] = dict({})
if u'all' not in list(webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']):
print("Empty Signature settings detected.")
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures'] = dict({'all': dict({})})
overwrite = check_input()
if webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'].get(signatureid) and not overwrite:
print('Default Signature already exists for user {}'.format(uid))
else:
print('Adding Default Signature for user {}'.format(uid))
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['all'][
signatureid] = signature_content
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures']['new_message'] = signatureid
webappsettings['settings']['zarafa']['v1']['contexts']['mail']['signatures'][
'replyforward_message'] = signatureid
write_settings(json.dumps(webappsettings),uid)
if __name__ == '__main__':
main()
and some test signature template file.
signature.html
<body>
<p>
{signature}
</p>
<p>
{name}<br>
{position}
</p>
<p>
Tel.: + 11 1 11 111 111-{tel}<br>
Mail: <a href="mailto:{mail}">{mail}</a><br>
</p>
</body>