#!/usr/share/ucs-test/runner python
# -*- coding: utf-8 -*-
## desc: check mail related modifications of user objects
## exposure: dangerous
## packages: [univention-mail-server]

from __future__ import print_function
from essential.mailclient import MailClient_SSL
import univention.config_registry
import subprocess
import univention.testing.strings as uts
import univention.testing.ucr as ucr_test
import univention.testing.udm as udm_test
import univention.testing.utils as utils


def check_login_lookup(host, mail, password, expected_result):
	"""This function checks if it is possible to login via a mail address
	and a given password, also checks if it is possible to lookup
	the standard set of mailboxes: INBOX, Ham, Spam.
	An exception is thrown if the result of either the login or the lookup
	was not expected.
	"""
	print('check_login_lookup() host={!r} mail={!r} password={!r} expected_result={!r}'.format(
		host, mail, password, expected_result))
	imap = MailClient_SSL(host)
	try:
		imap.log_in(mail, password)
		for mailbox in ['INBOX', 'Ham', 'Spam']:
			imap.check_lookup(mail, {mailbox: expected_result})
		imap.logout()
		if not expected_result:
			utils.fail('Authentication passed, expected to fail.')
	except Exception as ex:
		auth_errors = ['AUTHENTICATIONFAILED', 'LOGIN => socket error', '[UNAVAILABLE] Internal error']
		if any([msg in str(ex) for msg in auth_errors]):
			if expected_result:
				utils.fail('Authentication failed, expected to pass.')
		elif 'Login failed' in str(ex):
			if expected_result:
				utils.fail('Login failed, expected to pass.')
		else:
			raise


def main():
	with udm_test.UCSTestUDM() as udm:
		ucr_tmp = univention.config_registry.ConfigRegistry()
		ucr_tmp.load()
		cmd = ['/etc/init.d/dovecot', 'restart']
		with utils.AutoCallCommand(exit_cmd=cmd, stderr=open('/dev/null', 'w')):
			with ucr_test.UCSTestConfigRegistry() as ucr:
				domain = ucr.get('domainname')
				basedn = ucr.get('ldap/base')
				univention.config_registry.handler_set([
					'mail/dovecot/mailbox/rename=yes',
					'mail/dovecot/mailbox/delete=no',
					'mail/dovecot/auth/cache_size=0'
				])
				subprocess.call(['service', 'dovecot', 'restart'], stderr=open('/dev/null', 'w'))
				host = '%s.%s' % (ucr.get('hostname'), domain)
				password = 'univention'
				account = utils.UCSTestDomainAdminCredentials()
				admin = account.binddn
				passwd = account.bindpw

				# Case 1
				# Create a user with mailHomeServer and mailPrimaryAddress
				# → mailbox should have been created and is accessible
				# Change mailPrimaryAddress
				# → mailbox with NEW name should have been created and is accessible
				# → mailbox with OLD name should NOT be accessible
				print("== case 1 ==")
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailHomeServer': host,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				new_usermail = '%s@%s' % (uts.random_name(), domain)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailPrimaryAddress': new_usermail},
					check_for_drs_replication=True)
				check_login_lookup(host, new_usermail, password, True)
				check_login_lookup(host, usermail, password, False)

				# Case 2
				# Create a user with mailPrimaryAddress and without mailHomeServer
				# → mailbox should NOT have been created
				# Add local FQDN as mailHomeServer
				# → mailbox should have been created and is accessible
				print("== case 2 ==")
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailHomeServer': host},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, True)

				# Case 3
				# Create a user with mailPrimaryAddress and without mailHomeServer
				# → mailbox should NOT have been created
				# Add "foreign" FQDN as mailHomeServer
				# → mailbox should NOT have been created
				print("== case 3 ==")
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailHomeServer': 'mail.example.com'},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, False)

				# Case 4
				# Create a user without mailPrimaryAddress and mailHomeServer==$LOCALFQDN
				# → mailbox should NOT have been created
				# Add mailPrimaryAddress
				# → mailbox should have been created and is accessible
				print("== case 4 ==")
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailHomeServer': host
					}
				)
				check_login_lookup(host, '', password, False)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailPrimaryAddress': usermail},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, True)

				# Case 5
				# Create a user with mailHomeServer and mailPrimaryAddress
				# → mailbox should have been created and is accessible
				# Change mailHomeServer
				# → mailbox should NOT be accessible
				print("== case 5 ==")
				ip = uts.random_ip()
				new_host = uts.random_name()
				udm.create_object(
					'computers/domaincontroller_slave',
					set={
						'ip': ip,
						'name': new_host,
						'dnsEntryZoneForward': 'zoneName=%s,cn=dns,%s %s' % (
							domain, basedn, ip)
					},
					position='cn=computers,%s' % basedn
				)
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailHomeServer': host,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailHomeServer': '%s.%s' % (new_host, domain)},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, False)

				# Case 6
				# Create a user with mailHomeServer and mailPrimaryAddress
				# → mailbox should have been created and is accessible
				# Remove mailHomeServer
				# → mailbox should still be accessible
				print("== case 6 ==")
				ip = uts.random_ip()
				new_host = uts.random_name()
				udm.create_object(
					'computers/domaincontroller_slave',
					set={
						'ip': ip,
						'name': new_host,
						'dnsEntryZoneForward': 'zoneName=%s,cn=dns,%s %s' % (
							domain, basedn, ip)
					},
					position='cn=computers,%s' % basedn
				)
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailHomeServer': host,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailHomeServer': ''},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, True)

				# Case 7
				# Create a user with mailHomeServer and mailPrimaryAddress
				# → mailbox should have been created and is accessible
				# Remove mailPrimaryAddress
				# → mailbox should NOT be accessible
				print("== case 7 ==")
				ip = uts.random_ip()
				new_host = uts.random_name()
				udm.create_object(
					'computers/domaincontroller_slave',
					set={
						'ip': ip,
						'name': new_host,
						'dnsEntryZoneForward': 'zoneName=%s,cn=dns,%s %s' % (
							domain, basedn, ip)
					},
					position='cn=computers,%s' % basedn
				)
				usermail = '%s@%s' % (uts.random_name(), domain)
				userdn, username = udm.create_user(
					set={
						'password': password,
						'mailHomeServer': host,
						'mailPrimaryAddress': usermail
					}
				)
				check_login_lookup(host, usermail, password, True)
				udm.modify_object(
					'users/user',
					dn=userdn,
					binddn=admin,
					bindpwd=passwd,
					set={'mailPrimaryAddress': ''},
					check_for_drs_replication=True)
				check_login_lookup(host, usermail, password, False)


if __name__ == '__main__':
	main()

# vim: set ft=python ts=4 sw=4 noet :
