def test_ewsdatetime(self): tz = EWSTimeZone.timezone('Europe/Copenhagen') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.ms_id, 'Romance Standard Time') self.assertEqual(tz.ms_name, '(UTC+01:00) Brussels, Copenhagen, Madrid, Paris') dt = tz.localize(EWSDateTime(2000, 1, 2, 3, 4, 5)) self.assertIsInstance(dt, EWSDateTime) self.assertIsInstance(dt.tzinfo, EWSTimeZone) self.assertEqual(dt.tzinfo.ms_id, tz.ms_id) self.assertEqual(dt.tzinfo.ms_name, tz.ms_name) self.assertEqual(str(dt), '2000-01-02 03:04:05+01:00') self.assertEqual( repr(dt), "EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=<DstTzInfo 'Europe/Copenhagen' CET+1:00:00 STD>)" ) self.assertIsInstance(dt + timedelta(days=1), EWSDateTime) self.assertIsInstance(dt - timedelta(days=1), EWSDateTime) self.assertIsInstance(dt - EWSDateTime.now(tz=tz), timedelta) self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime) self.assertEqual(dt, EWSDateTime.from_datetime(tz.localize(datetime(2000, 1, 2, 3, 4, 5)))) self.assertEqual(dt.ewsformat(), '2000-01-02T03:04:05') utc_tz = EWSTimeZone.timezone('UTC') self.assertEqual(dt.astimezone(utc_tz).ewsformat(), '2000-01-02T02:04:05Z') # Test summertime dt = tz.localize(EWSDateTime(2000, 8, 2, 3, 4, 5)) self.assertEqual(dt.astimezone(utc_tz).ewsformat(), '2000-08-02T01:04:05Z')
def initEventStorage(): # Open sqlite database, up to now it is used to store calendarNames / Outlook categories and Mattermost groups in which calendar events should be posted. # The calendar events are stored in an Outlook calendar and also in the sqlite database up to now. try: conn = sqlite3.connect(calendarSettings['DatabaseName']) cursor=conn.cursor() except Exception as e: print ("Could not open sqlite database due to following exception:\n {0} \n {1}".format(e.__doc__, e.message)) # Open outlook calendar try: config = Configuration(username=outlookSettings['Username'], password=outlookSettings['Password']) account = Account(primary_smtp_address=outlookSettings['Email'], config=config, autodiscover=True, access_type=DELEGATE) except Exception as e: print ("Could not open Outlook calendar due to following exception:\n {0} \n {1}".format(e.__doc__, e.message)) # Set timezone needed later, note: only Copenhagen is mapped but it is the same timezone as Berlin tz = EWSTimeZone.timezone('Europe/Copenhagen') # Create table which contains subcalendars # calendarName: Name which is refered to add an event, calendarMattermostGroup: group in which events should be published # calendarName is rewritten in an Outlook calendar category to be stored in Outlook calendar try: createCalendarTable = "CREATE TABLE IF NOT EXISTS 'calendarTable' (id INTEGER PRIMARY KEY AUTOINCREMENT, calendarName TEXT, calendarMattermostGroup TEXT)" conn.execute(createCalendarTable) except Exception as e: print ("Could not access / create sqlite calendar due to following exception:\n {0} \n {1}".format(e.__doc__, e.message)) return conn, cursor, tz, account
def setUpClass(cls): # There's no official Exchange server we can test against, and we can't really provide credentials for our # own test server to everyone on the Internet. Travis-CI uses the encrypted settings.yml.enc for testing. # # If you want to test against your own server and account, create your own settings.yml with credentials for # that server. 'settings.yml.sample' is provided as a template. try: with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'settings.yml')) as f: settings = safe_load(f) except FileNotFoundError: print('Skipping %s - no settings.yml file found' % cls.__name__) print('Copy settings.yml.sample to settings.yml and enter values for your test server') raise unittest.SkipTest('Skipping %s - no settings.yml file found' % cls.__name__) cls.verify_ssl = settings.get('verify_ssl', True) if not cls.verify_ssl: # Allow unverified TLS if requested in settings file BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter # Speed up tests a bit. We don't need to wait 10 seconds for every nonexisting server in the discover dance AutodiscoverProtocol.TIMEOUT = 2 # Create an account shared by all tests tz = EWSTimeZone.timezone('Europe/Copenhagen') cls.retry_policy = FaultTolerance(max_wait=600) config = Configuration( server=settings['server'], credentials=Credentials(settings['username'], settings['password']), retry_policy=cls.retry_policy, ) cls.account = Account(primary_smtp_address=settings['account'], access_type=DELEGATE, config=config, locale='da_DK', default_timezone=tz)
def test_from_params(self): tz = EWSTimeZone.timezone('Europe/Copenhagen') start = tz.localize(EWSDateTime(1900, 9, 26, 8, 0, 0)) end = tz.localize(EWSDateTime(2200, 9, 26, 11, 0, 0)) xml = Restriction.from_params(start=start, end=end, categories=['FOO', 'BAR']) result = '''\ <m:Restriction> <t:And> <t:IsGreaterThan> <t:FieldURI FieldURI="calendar:End" /> <t:FieldURIOrConstant> <t:Constant Value="1900-09-26T07:10:00Z" /> </t:FieldURIOrConstant> </t:IsGreaterThan> <t:IsLessThan> <t:FieldURI FieldURI="calendar:Start" /> <t:FieldURIOrConstant> <t:Constant Value="2200-09-26T10:00:00Z" /> </t:FieldURIOrConstant> </t:IsLessThan> <t:Or> <t:Contains ContainmentComparison="Exact" ContainmentMode="Substring"> <t:FieldURI FieldURI="item:Categories" /> <t:Constant Value="FOO" /> </t:Contains> <t:Contains ContainmentComparison="Exact" ContainmentMode="Substring"> <t:FieldURI FieldURI="item:Categories" /> <t:Constant Value="BAR" /> </t:Contains> </t:Or> </t:And> </m:Restriction>''' self.assertEqual(str(xml), ''.join(l.lstrip() for l in result.split('\n')))
def test_task_validation(self): tz = EWSTimeZone.timezone('Europe/Copenhagen') task = Task(due_date=tz.localize(EWSDateTime(2017, 1, 1)), start_date=tz.localize(EWSDateTime(2017, 2, 1))) task.clean() # We reset due date if it's before start date self.assertEqual(task.due_date, tz.localize(EWSDateTime(2017, 2, 1))) self.assertEqual(task.due_date, task.start_date) task = Task(complete_date=tz.localize(EWSDateTime(2099, 1, 1)), status=Task.NOT_STARTED) task.clean() # We reset status if complete_date is set self.assertEqual(task.status, Task.COMPLETED) # We also reset complete date to now() if it's in the future self.assertEqual(task.complete_date.date(), UTC_NOW().date()) task = Task(complete_date=tz.localize(EWSDateTime(2017, 1, 1)), start_date=tz.localize(EWSDateTime(2017, 2, 1))) task.clean() # We also reset complete date to start_date if it's before start_date self.assertEqual(task.complete_date, task.start_date) task = Task(percent_complete=Decimal('50.0'), status=Task.COMPLETED) task.clean() # We reset percent_complete to 100.0 if state is completed self.assertEqual(task.percent_complete, Decimal(100)) task = Task(percent_complete=Decimal('50.0'), status=Task.NOT_STARTED) task.clean() # We reset percent_complete to 0.0 if state is not_started self.assertEqual(task.percent_complete, Decimal(0))
def setUp(self): self.tz = EWSTimeZone.timezone('Europe/Copenhagen') try: with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'settings.yml')) as f: settings = load(f) except FileNotFoundError: print('Copy settings.yml.sample to settings.yml and enter values for your test server') raise self.categories = ['Test'] self.config = Configuration(server=settings['server'], username=settings['username'], password=settings['password']) self.account = Account(primary_smtp_address=settings['account'], access_type=DELEGATE, config=self.config)
def setUp(self): # There's no official Exchange server we can test against, and we can't really provide credentials for our # own test server to anyone on the Internet. You need to create your own settings.yml with credentials for # your own test server. 'settings.yml.sample' is provided as a template. try: with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'settings.yml')) as f: settings = load(f) except FileNotFoundError: print('Copy settings.yml.sample to settings.yml and enter values for your test server') raise self.tz = EWSTimeZone.timezone('Europe/Copenhagen') self.categories = ['Test'] self.config = Configuration(server=settings['server'], username=settings['username'], password=settings['password'], verify_ssl=settings['verify_ssl']) self.account = Account(primary_smtp_address=settings['account'], access_type=DELEGATE, config=self.config) self.maxDiff = None
def initEventStorage(): # Open sqlite database, up to now it is used to store calendarNames / Outlook categories and Mattermost groups in which calendar events should be posted. # The calendar events are stored in an Outlook calendar and also in the sqlite database up to now. try: conn = sqlite3.connect(calendarSettings['DatabaseName']) cursor = conn.cursor() except Exception as e: print( "Could not open sqlite database due to following exception:\n {0} \n {1}" .format(e.__doc__, e.message)) # Open outlook calendar try: config = Configuration(username=outlookSettings['Username'], password=outlookSettings['Password']) account = Account(primary_smtp_address=outlookSettings['Email'], config=config, autodiscover=True, access_type=DELEGATE) except Exception as e: print( "Could not open Outlook calendar due to following exception:\n {0} \n {1}" .format(e.__doc__, e.message)) # Set timezone needed later, note: only Copenhagen is mapped but it is the same timezone as Berlin tz = EWSTimeZone.timezone('Europe/Copenhagen') # Create table which contains subcalendars # calendarName: Name which is refered to add an event, calendarMattermostGroup: group in which events should be published # calendarName is rewritten in an Outlook calendar category to be stored in Outlook calendar try: createCalendarTable = "CREATE TABLE IF NOT EXISTS 'calendarTable' (id INTEGER PRIMARY KEY AUTOINCREMENT, calendarName TEXT, calendarMattermostGroup TEXT)" conn.execute(createCalendarTable) except Exception as e: print( "Could not access / create sqlite calendar due to following exception:\n {0} \n {1}" .format(e.__doc__, e.message)) return conn, cursor, tz, account
def random_val(self, field): if isinstance(field, ExtendedPropertyField): if field.value_cls.property_type == 'StringArray': return [ get_random_string(255) for _ in range(random.randint(1, 4)) ] if field.value_cls.property_type == 'IntegerArray': return [ get_random_int(0, 256) for _ in range(random.randint(1, 4)) ] if field.value_cls.property_type == 'BinaryArray': return [ get_random_string(255).encode() for _ in range(random.randint(1, 4)) ] if field.value_cls.property_type == 'String': return get_random_string(255) if field.value_cls.property_type == 'Integer': return get_random_int(0, 256) if field.value_cls.property_type == 'Binary': # In the test_extended_distinguished_property test, EWS rull return 4 NULL bytes after char 16 if we # send a longer bytes sequence. return get_random_string(16).encode() raise ValueError('Unsupported field %s' % field) if isinstance(field, URIField): return get_random_url() if isinstance(field, EmailAddressField): return get_random_email() if isinstance(field, ChoiceField): return get_random_choice( field.supported_choices(version=self.account.version)) if isinstance(field, CultureField): return get_random_choice([ 'da-DK', 'de-DE', 'en-US', 'es-ES', 'fr-CA', 'nl-NL', 'ru-RU', 'sv-SE' ]) if isinstance(field, BodyField): return get_random_string(400) if isinstance(field, CharListField): return [get_random_string(16) for _ in range(random.randint(1, 4))] if isinstance(field, TextListField): return [ get_random_string(400) for _ in range(random.randint(1, 4)) ] if isinstance(field, CharField): return get_random_string(field.max_length) if isinstance(field, TextField): return get_random_string(400) if isinstance(field, MimeContentField): return get_random_string(400) if isinstance(field, Base64Field): return get_random_bytes(400) if isinstance(field, BooleanField): return get_random_bool() if isinstance(field, DecimalField): return get_random_decimal(field.min or 1, field.max or 99) if isinstance(field, IntegerField): return get_random_int(field.min or 0, field.max or 256) if isinstance(field, DateTimeField): return get_random_datetime(tz=self.account.default_timezone) if isinstance(field, AttachmentField): return [ FileAttachment(name='my_file.txt', content=get_random_bytes(400)) ] if isinstance(field, MailboxListField): # email_address must be a real account on the server(?) # TODO: Mailbox has multiple optional args but vals must match server account, so we can't easily test if get_random_bool(): return [ Mailbox(email_address=self.account.primary_smtp_address) ] else: return [self.account.primary_smtp_address] if isinstance(field, MailboxField): # email_address must be a real account on the server(?) # TODO: Mailbox has multiple optional args but vals must match server account, so we can't easily test if get_random_bool(): return Mailbox(email_address=self.account.primary_smtp_address) else: return self.account.primary_smtp_address if isinstance(field, AttendeesField): # Attendee must refer to a real mailbox on the server(?). We're only sure to have one if get_random_bool(): mbx = Mailbox(email_address=self.account.primary_smtp_address) else: mbx = self.account.primary_smtp_address with_last_response_time = get_random_bool() if with_last_response_time: return [ Attendee(mailbox=mbx, response_type='Accept', last_response_time=get_random_datetime( tz=self.account.default_timezone)) ] else: if get_random_bool(): return [Attendee(mailbox=mbx, response_type='Accept')] else: return [self.account.primary_smtp_address] if isinstance(field, EmailAddressesField): addrs = [] for label in EmailAddress.get_field_by_fieldname( 'label').supported_choices(version=self.account.version): addr = EmailAddress(email=get_random_email()) addr.label = label addrs.append(addr) return addrs if isinstance(field, PhysicalAddressField): addrs = [] for label in PhysicalAddress.get_field_by_fieldname('label')\ .supported_choices(version=self.account.version): addr = PhysicalAddress(street=get_random_string(32), city=get_random_string(32), state=get_random_string(32), country=get_random_string(32), zipcode=get_random_string(8)) addr.label = label addrs.append(addr) return addrs if isinstance(field, PhoneNumberField): pns = [] for label in PhoneNumber.get_field_by_fieldname( 'label').supported_choices(version=self.account.version): pn = PhoneNumber(phone_number=get_random_string(16)) pn.label = label pns.append(pn) return pns if isinstance(field, EWSElementField): if field.value_cls == Recurrence: return Recurrence(pattern=DailyPattern(interval=5), start=get_random_date(), number=7) if isinstance(field, TimeZoneField): while True: try: return EWSTimeZone.timezone( random.choice(pytz.all_timezones)) except UnknownTimeZone: pass if isinstance(field, PermissionSetField): return PermissionSet(permissions=[ Permission(user_id=UserId( primary_smtp_address=self.account.primary_smtp_address), ) ]) raise ValueError('Unknown field %s' % field)
from exchangelib.configuration import Configuration from exchangelib.account import Account from exchangelib.ewsdatetime import EWSDateTime, EWSTimeZone from exchangelib.folders import CalendarItem logging.basicConfig(level=logging.WARNING) try: with open(os.path.join(os.path.dirname(__file__), 'settings.yml')) as f: settings = load(f) except FileNotFoundError: print('Copy settings.yml.sample to settings.yml and enter values for your test server') raise categories = ['perftest'] tz = EWSTimeZone.timezone('Europe/Copenhagen') config = Configuration(server=settings['server'], username=settings['username'], password=settings['password']) print(('Exchange server: %s' % config.protocol.server)) account = Account(config=config, primary_smtp_address=settings['account'], access_type=DELEGATE) cal = account.calendar # Calendar item generator def calitems(): i = 0 start = tz.localize(EWSDateTime(2000, 3, 1, 8, 30, 0)) end = tz.localize(EWSDateTime(2000, 3, 1, 9, 15, 0)) item = CalendarItem( item_id='',
# Disable insecure SSL warnings warnings.filterwarnings("ignore") # Use notify-send for email notifications and zenity for calendar notifications notify = sh.Command('/usr/bin/notify-send') zenity = sh.Command('/usr/bin/zenity') # Get the local timezone timedatectl = sh.Command('/usr/bin/timedatectl') for l in timedatectl(): if 'Timezone' in l: tz_name = l.split()[1] break else: raise ValueError('Timezone not found') tz = EWSTimeZone.timezone(tz_name) sleep = int(sys.argv[1]) # 1st arg to this script is the number of seconds to look back in the inbox now = UTC_NOW() emails_since = now - timedelta(seconds=sleep) cal_items_before = now + timedelta(seconds=sleep * 4) # Longer notice of upcoming appointments than new emails username, _, password = netrc().authenticators('office365') c = Credentials(username, password, is_service_account=False) a = Account(primary_smtp_address=c.username, credentials=c, access_type=DELEGATE, autodiscover=True, verify_ssl=False) for msg in a.calendar.view(start=now, end=cal_items_before)\ .only('start', 'end', 'subject', 'location')\ .order_by('start', 'end'): if msg.start < now: continue minutes_to_appointment = int((msg.start - now).total_seconds() / 60)
from exchangelib.configuration import Configuration from exchangelib.account import Account from exchangelib.ewsdatetime import EWSDateTime, EWSTimeZone from exchangelib.folders import CalendarItem logging.basicConfig(level=logging.WARNING) try: with open(os.path.join(os.path.dirname(__file__), 'settings.yml')) as f: settings = load(f) except FileNotFoundError: print('Copy settings.yml.sample to settings.yml and enter values for your test server') raise categories = ['foobar', 'perftest'] tz = EWSTimeZone.timezone('US/Pacific') t0 = datetime.now() config = Configuration(server=settings['server'], username=settings['username'], password=settings['password'], verify_ssl=False) print(('Exchange server: %s' % config.protocol.server)) account = Account(config=config, primary_smtp_address=settings['account'], access_type=DELEGATE) cal = account.calendar t1 = datetime.now() print(('Time to build ExchangeServer object: %s' % (t1 - t0))) year = 2012 month = 3