def _export_folder_subset(self, folder, start_dt=None, end_dt=None): """ Export a time-subset of an exchange folder :param folder: The exchange folder to export :start_dt: The start date to export from, default 1900-01-01 :end_dt: The end date to export to, default 2100-01-01 :return: Number of attachments in folder """ try: logger.info('Export subset: {} to {}'.format(start_dt, end_dt)) attachments = 0 if start_dt is None: start_dt = EWSDate(1900, 1, 1) if end_dt is None: end_dt = EWSDate(2100, 1, 1) items = folder.all() start_dt = UTC.localize( EWSDateTime(start_dt.year, start_dt.month, start_dt.day, 0, 0)) end_dt = UTC.localize( EWSDateTime(end_dt.year, end_dt.month, end_dt.day, 0, 0)) items = items.filter(datetime_received__range=(start_dt, end_dt)) for chunk in chunkify(items, 10): for item in chunk: self.actual_exported_mails += 1 logger.error( str(item.datetime_created) + ':' + str(item.subject)) skip_list = self.export_item_body(item) attachments += self.export_attachments(item, skip_list) self.update_amqp(only_mails=True) except ErrorMimeContentConversionFailed: msg = '{}: ErrorMimeContentConversionFailed, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorInternalServerError: # Possibly happens on p7m files? msg = '{}: ErrorInternalServerError, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorInvalidOperation: msg = '{}: ErrorInvalidOperation, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorTimeoutExpired: attachments = -1 time.sleep(30) logger.warning('{}: ErrorTimeoutExpired'.format(self.export_path)) except ErrorInternalServerTransientError: attachments = -1 time.sleep(30) warning = '{}, {}: ErrorInternalServerTransientError' logger.warning(warning.format(self.export_path, folder)) return attachments
def _export_folder_subset(self, folder, start_dt=None, end_dt=None): """ Export a time-subset of an exchange folder :param folder: The exchange folder to export :start_dt: The start date to export from, default 1900-01-01 :end_dt: The end date to export to, default 2100-01-01 :return: Number of attachments in folder """ try: logger.info('Export subset: {} to {}'.format(start_dt, end_dt)) attachments = 0 if start_dt is None: start_dt = EWSDate(1900, 1, 1) if end_dt is None: end_dt = EWSDate(2100, 1, 1) items = folder.all() start_dt = UTC.localize(EWSDateTime(start_dt.year, start_dt.month, start_dt.day, 0, 0)) end_dt = UTC.localize(EWSDateTime(end_dt.year, end_dt.month, end_dt.day, 0, 0)) items = items.filter(datetime_received__range=(start_dt, end_dt)) for chunk in chunkify(items, 10): for item in chunk: self.actual_exported_mails += 1 logger.error(str(item.datetime_created) + ':' + str(item.subject)) skip_list = self.export_item_body(item) attachments += self.export_attachments(item, skip_list) self.update_amqp(only_mails=True) except ErrorMimeContentConversionFailed: msg = '{}: ErrorMimeContentConversionFailed, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorInternalServerError: # Possibly happens on p7m files? msg = '{}: ErrorInternalServerError, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorInvalidOperation: msg = '{}: ErrorInvalidOperation, giving up sub-folder' msg += ' Attachment value: {}' logger.warning(msg.format(self.export_path, attachments)) except ErrorTimeoutExpired: attachments = -1 time.sleep(30) logger.warning('{}: ErrorTimeoutExpired'.format(self.export_path)) except ErrorInternalServerTransientError: attachments = -1 time.sleep(30) warning = '{}, {}: ErrorInternalServerTransientError' logger.warning(warning.format(self.export_path, folder)) return attachments
def email_scan(self, keyword): ##grab login info from config. It's currently reading my email. Should change to a public Phia email account config = configparser.ConfigParser() config.read('\\\\pgcfpsclrfs\\ClaimDumps\\Bottest\\Python\\config.ini') email_username = config.get('Section', 'email_username') email_password = config.get('Section', 'email_password') email_smtp_address = config.get('Section', 'email_smtp_address') keyword = keyword credentials = Credentials(username=email_username, password=email_password) account = Account(primary_smtp_address=email_smtp_address, credentials=credentials, autodiscover=True, access_type=DELEGATE) ##Grabing date range of this week. end = UTC.localize(EWSDateTime.today() + timedelta(days=1)) lastweek = EWSDateTime.today() - timedelta(days=5) start = UTC.localize(lastweek) ##Adding the file links from the email into a dictionary. dict = {} for item in account.inbox.all().filter( subject='FW: Scheduled Report Available For Book of Business - Subrogation') \ .filter(datetime_received__range=(start, end)): ##print(item.body) soup = BeautifulSoup(item.body, 'lxml') for link in soup.findAll('a'): newlink = (link.get('href')) filtered = soup.find_all(text=re.compile(keyword)) if 'ReportViewer' in newlink and filtered: datetime = (item.datetime_received) newdict = {newlink: datetime} with open( "\\\\pgcfpsclrfs\\ClaimDumps\\Bottest\\Python\\PythonLog.txt", 'w') as f: for key, value in newdict.items(): f.write('%s:%s\n' % (key, value)) dict.update(newdict) return dict
def total_mails(self): """ Return the total amounts of content newet thatn self.start_date for the user. This includes mails and calendar items """ total_count = 0 if self.account: if False: # TODO: should be if self.start_date start_dt = UTC.localize(EWSDateTime(self.start_date.year, self.start_date.month, self.start_date.day, 0, 0)) end_dt = UTC.localize(EWSDateTime(2100, 1, 1, 0, 0)) for folder in self.account.root.walk(): items = folder.all() items = items.filter(datetime_received__range=(start_dt, end_dt)) total_count += items.count() else: for folder in self.account.root.walk(): total_count += folder.total_count return total_count
def test_naive_datetime(self): # Test that we can survive naive datetimes on a datetime field tz = EWSTimeZone.timezone('Europe/Copenhagen') account = namedtuple('Account', ['default_timezone'])(default_timezone=tz) default_value = tz.localize(EWSDateTime(2017, 1, 2, 3, 4)) field = DateTimeField('foo', field_uri='item:DateTimeSent', default=default_value) # TZ-aware datetime string payload = b'''\ <?xml version="1.0" encoding="utf-8"?> <Envelope xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <t:Item> <t:DateTimeSent>2017-06-21T18:40:02Z</t:DateTimeSent> </t:Item> </Envelope>''' elem = to_xml(payload).find('{%s}Item' % TNS) self.assertEqual(field.from_xml(elem=elem, account=account), UTC.localize(EWSDateTime(2017, 6, 21, 18, 40, 2))) # Naive datetime string is localized to tz of the account payload = b'''\ <?xml version="1.0" encoding="utf-8"?> <Envelope xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <t:Item> <t:DateTimeSent>2017-06-21T18:40:02</t:DateTimeSent> </t:Item> </Envelope>''' elem = to_xml(payload).find('{%s}Item' % TNS) self.assertEqual(field.from_xml(elem=elem, account=account), tz.localize(EWSDateTime(2017, 6, 21, 18, 40, 2))) # Garbage string returns None payload = b'''\ <?xml version="1.0" encoding="utf-8"?> <Envelope xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <t:Item> <t:DateTimeSent>THIS_IS_GARBAGE</t:DateTimeSent> </t:Item> </Envelope>''' elem = to_xml(payload).find('{%s}Item' % TNS) self.assertEqual(field.from_xml(elem=elem, account=account), None) # Element not found returns default value payload = b'''\ <?xml version="1.0" encoding="utf-8"?> <Envelope xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <t:Item> </t:Item> </Envelope>''' elem = to_xml(payload).find('{%s}Item' % TNS) self.assertEqual(field.from_xml(elem=elem, account=account), default_value)
def test_oof_settings_validation(self): with self.assertRaises(ValueError): # Needs a start and end OofSettings(state=OofSettings.SCHEDULED, ).clean(version=None) with self.assertRaises(ValueError): # Start must be before end OofSettings( state=OofSettings.SCHEDULED, start=UTC.localize(EWSDateTime(2100, 12, 1)), end=UTC.localize(EWSDateTime(2100, 11, 1)), ).clean(version=None) with self.assertRaises(ValueError): # End must be in the future OofSettings( state=OofSettings.SCHEDULED, start=UTC.localize(EWSDateTime(2000, 11, 1)), end=UTC.localize(EWSDateTime(2000, 12, 1)), ).clean(version=None) with self.assertRaises(ValueError): # Must have an internal and external reply OofSettings( state=OofSettings.SCHEDULED, start=UTC.localize(EWSDateTime(2100, 11, 1)), end=UTC.localize(EWSDateTime(2100, 12, 1)), ).clean(version=None)
def test_ewsdatetime(self): # Test a static timezone tz = EWSTimeZone.timezone('Etc/GMT-5') 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+05:00') self.assertEqual( repr(dt), "EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=<StaticTzInfo 'Etc/GMT-5'>)" ) # Test a DST timezone tz = EWSTimeZone.timezone('Europe/Copenhagen') 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>)" ) # Test from_string with self.assertRaises(NaiveDateTimeNotAllowed): EWSDateTime.from_string('2000-01-02T03:04:05') self.assertEqual(EWSDateTime.from_string('2000-01-02T03:04:05+01:00'), UTC.localize(EWSDateTime(2000, 1, 2, 2, 4, 5))) self.assertEqual(EWSDateTime.from_string('2000-01-02T03:04:05Z'), UTC.localize(EWSDateTime(2000, 1, 2, 3, 4, 5))) self.assertIsInstance( EWSDateTime.from_string('2000-01-02T03:04:05+01:00'), EWSDateTime) self.assertIsInstance(EWSDateTime.from_string('2000-01-02T03:04:05Z'), EWSDateTime) # Test addition, subtraction, summertime etc self.assertIsInstance(dt + datetime.timedelta(days=1), EWSDateTime) self.assertIsInstance(dt - datetime.timedelta(days=1), EWSDateTime) self.assertIsInstance(dt - EWSDateTime.now(tz=tz), datetime.timedelta) self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime) self.assertEqual( dt, EWSDateTime.from_datetime( tz.localize(datetime.datetime(2000, 1, 2, 3, 4, 5)))) self.assertEqual(dt.ewsformat(), '2000-01-02T03:04:05+01:00') 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') # Test normalize, for completeness self.assertEqual( tz.normalize(dt).ewsformat(), '2000-08-02T03:04:05+02:00') self.assertEqual( utc_tz.normalize(dt, is_dst=True).ewsformat(), '2000-08-02T01:04:05Z') # Test in-place add and subtract dt = tz.localize(EWSDateTime(2000, 1, 2, 3, 4, 5)) dt += datetime.timedelta(days=1) self.assertIsInstance(dt, EWSDateTime) self.assertEqual(dt, tz.localize(EWSDateTime(2000, 1, 3, 3, 4, 5))) dt = tz.localize(EWSDateTime(2000, 1, 2, 3, 4, 5)) dt -= datetime.timedelta(days=1) self.assertIsInstance(dt, EWSDateTime) self.assertEqual(dt, tz.localize(EWSDateTime(2000, 1, 1, 3, 4, 5))) # Test ewsformat() failure dt = EWSDateTime(2000, 1, 2, 3, 4, 5) with self.assertRaises(ValueError): dt.ewsformat() # Test wrong tzinfo type with self.assertRaises(ValueError): EWSDateTime(2000, 1, 2, 3, 4, 5, tzinfo=pytz.utc) with self.assertRaises(ValueError): EWSDateTime.from_datetime(EWSDateTime(2000, 1, 2, 3, 4, 5))
# Datetime math works transparently two_hours_later = localized_dt + timedelta(hours=2) two_hours = two_hours_later - localized_dt two_hours_later += timedelta(hours=2) # Dates my_date = EWSDate(2017, 9, 5) today = EWSDate.today() also_today = right_now.date() also_today += timedelta(days=10) # UTC helpers. 'UTC' is the UTC timezone as an EWSTimeZone instance. # 'UTC_NOW' returns a timezone-aware UTC timestamp of current time. from exchangelib import UTC, UTC_NOW right_now_in_utc = UTC.localize(EWSDateTime.now()) right_now_in_utc = UTC_NOW() # Already have a Python datetime object you want to use? Make sure it's localized. Then pass # it to from_datetime(). pytz_tz = pytz.timezone('Europe/Copenhagen') py_dt = pytz_tz.localize(datetime(2017, 12, 11, 10, 9, 8)) ews_now = EWSDateTime.from_datetime(py_dt) ###Creating, updating, deleting, sending, moving, archiving # Here's an example of creating a calendar item in the user's standard calendar. If you want to # access a non-standard calendar, choose a different one from account.folders[Calendar]. # # You can create, update and delete single items: from exchangelib import Account, CalendarItem, Message, Mailbox, FileAttachment, HTMLBody