def addAgendaSubmit(self): fromDate = self.ui_addAgenda.agndFromDateInput.date() fromTime = self.ui_addAgenda.agndFromTimeInput.time() toDate = self.ui_addAgenda.agndToDateInput.date() toTime = self.ui_addAgenda.agndToTimeInput.time() fromDatetime = QDateTime(fromDate, fromTime, timeSpec=Qt.LocalTime) toDatetime = QDateTime(toDate, toTime, timeSpec=Qt.LocalTime) localTimeZone = EWSTimeZone.localzone() fromEWSDatetime = EWSDateTime.from_datetime( fromDatetime.toPyDateTime()) toEWSDatetime = EWSDateTime.from_datetime(toDatetime.toPyDateTime()) fromDT = fromEWSDatetime.astimezone(tz=localTimeZone) toDT = toEWSDatetime.astimezone(tz=localTimeZone) location = self.ui_addAgenda.agndPosInput.text() subject = self.ui_addAgenda.agndSubjectInput.text() detail = self.ui_addAgenda.agndDetailInput.toPlainText() reminderEnable = self.ui_addAgenda.agndAlarmEnableCheck.isChecked() reminder = self.ui_addAgenda.agndAlarmInput.value() self.timerRoutine.exchAccount.login() self.timerRoutine.exchAccount.addAgenda(fromDT, toDT, location, subject, detail, reminderEnable, reminder) self.addAgendaDialog.close() self.listDialog.show() self.timerRoutine.unrdAutoUpdateTimerStart() self.timerRoutine.timer2.start()
def get_exchange_events(server: str, domain: Optional[str], username: str, password: str, range_start: datetime, range_end: datetime) -> List[CalendarEvent]: """Connect to exchange calendar server and get events within range.""" # load exchange module if necessary from exchangelib import Credentials, Configuration, Account, DELEGATE from exchangelib import EWSDateTime, EWSTimeZone # setup access full_username = r'{}\{}'.format(domain, username) if domain else username account = Account(primary_smtp_address=username, config=Configuration(server=server, credentials=Credentials( full_username, password)), autodiscover=False, access_type=DELEGATE) # collect event information within given time range events: List[CalendarEvent] = [] localzone = EWSTimeZone.localzone() local_start = localzone.localize(EWSDateTime.from_datetime(range_start)) local_end = localzone.localize(EWSDateTime.from_datetime(range_end)) for item in account.calendar.filter( ##pylint: disable=no-member start__range=(local_start, local_end)).order_by('start'): events.append( CalendarEvent(title=item.subject, start=item.start, end=item.end, duration=(item.end - item.start).seconds / 3600, categories=item.categories)) return events
def main(): exchAcc = ExchAccount('eas.outlook.com','******@outlook.com','********') exchAcc.login() localTimeZone = EWSTimeZone.localzone() nowDateTime = EWSDateTime.now(tz=localTimeZone) # print(EWSDateTime.now(tz=localTimeZone)) items = exchAcc.account.calendar.view(start=nowDateTime - timedelta(days=1),end=nowDateTime + timedelta(days=6)) for item in items: startTime = item.start.astimezone(tz=localTimeZone) endTime = item.end.astimezone(tz=localTimeZone) print(item.reminder_minutes_before_start)
def test_ewstimezone(self): # Test autogenerated translations tz = EWSTimeZone('Europe/Copenhagen') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.key, 'Europe/Copenhagen') self.assertEqual(tz.ms_id, 'Romance Standard Time') # self.assertEqual(EWSTimeZone('Europe/Copenhagen').ms_name, '') # EWS works fine without the ms_name # Test localzone() tz = EWSTimeZone.localzone() self.assertIsInstance(tz, EWSTimeZone) # Test common helpers tz = EWSTimeZone('UTC') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.key, 'UTC') self.assertEqual(tz.ms_id, 'UTC') tz = EWSTimeZone('GMT') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.key, 'GMT') self.assertEqual(tz.ms_id, 'UTC') # Test mapper contents. Latest map from unicode.org has 394 entries self.assertGreater(len(EWSTimeZone.IANA_TO_MS_MAP), 300) for k, v in EWSTimeZone.IANA_TO_MS_MAP.items(): self.assertIsInstance(k, str) self.assertIsInstance(v, tuple) self.assertEqual(len(v), 2) self.assertIsInstance(v[0], str) # Test timezone unknown by ZoneInfo with self.assertRaises(UnknownTimeZone) as e: EWSTimeZone('UNKNOWN') self.assertEqual(e.exception.args[0], 'No time zone found with key UNKNOWN') # Test timezone known by IANA but with no Winzone mapping with self.assertRaises(UnknownTimeZone) as e: del EWSTimeZone.IANA_TO_MS_MAP['Africa/Tripoli'] EWSTimeZone('Africa/Tripoli') self.assertEqual( e.exception.args[0], 'No Windows timezone name found for timezone "Africa/Tripoli"') # Test __eq__ with non-EWSTimeZone compare self.assertFalse(EWSTimeZone('GMT') == zoneinfo.ZoneInfo('UTC')) # Test from_ms_id() with non-standard MS ID self.assertEqual(EWSTimeZone('Europe/Copenhagen'), EWSTimeZone.from_ms_id('Europe/Copenhagen'))
def Update(self): localTimeZone = EWSTimeZone.localzone() nowDateTime = EWSDateTime.now(tz=localTimeZone) # print(EWSDateTime.now(tz=localTimeZone)) items = self.account.calendar.view( start=nowDateTime - timedelta(days=1), end=nowDateTime + timedelta(days=6), ) retStr = [] unseenStr = [] unseenMails = self.account.inbox.filter(is_read=False) unseenStr.append(('{}'.format(unseenMails.count()))) retStr.append(unseenStr) for item in items: itemStr = [] startTime = item.start.astimezone(tz=localTimeZone) endTime = item.end.astimezone(tz=localTimeZone) dataOffset = startTime - nowDateTime dateOffNum = dataOffset.days+ dataOffset.seconds/(24.0*60.0*60.0) dateOffStr = ('%3.2f' % (dateOffNum))+'天后' if(dateOffNum>0) else ('%3.2f' % (abs(dateOffNum)))+'天前' if startTime.date()== nowDateTime.date(): dateOffStr=('今天') when = '{},{}-{}'.format(dateOffStr,startTime.strftime('%m/%d %H:%M'),endTime.strftime('%H:%M')) subject = (re.sub('(?s)([^<]*)(<.*>)(.*)', '\\1\\3', '{}'.format(item.subject))).replace('None','') detail = (re.sub('(?s)([^<]*)(<.*>)(.*)', '\\1\\3', ':{}'.format(item.body))).replace(':None','') reminderTime = startTime - timedelta(minutes=item.reminder_minutes_before_start) if(nowDateTime.strftime("%m/%d %H:%M") == reminderTime.strftime("%m/%d %H:%M")): remindNow = True else: remindNow = False reminder = ('{} min'.format(item.reminder_minutes_before_start if item.reminder_is_set else 'No remind')) location = ('@{}#{}'.format(item.location,reminder)).replace('None','') itemStr.append(when) itemStr.append('{}{}'.format(subject,detail)) itemStr.append(location) itemStr.append(remindNow) retStr.append(itemStr) return retStr
def test_ewstimezone(self): # Test autogenerated translations tz = EWSTimeZone.timezone('Europe/Copenhagen') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.zone, 'Europe/Copenhagen') self.assertEqual(tz.ms_id, 'Romance Standard Time') # self.assertEqual(EWSTimeZone.timezone('Europe/Copenhagen').ms_name, '') # EWS works fine without the ms_name # Test localzone() tz = EWSTimeZone.localzone() self.assertIsInstance(tz, EWSTimeZone) # Test common helpers tz = EWSTimeZone.timezone('UTC') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.zone, 'UTC') self.assertEqual(tz.ms_id, 'UTC') tz = EWSTimeZone.timezone('GMT') self.assertIsInstance(tz, EWSTimeZone) self.assertEqual(tz.zone, 'GMT') self.assertEqual(tz.ms_id, 'UTC') # Test mapper contents. Latest map from unicode.org has 394 entries self.assertGreater(len(EWSTimeZone.PYTZ_TO_MS_MAP), 300) for k, v in EWSTimeZone.PYTZ_TO_MS_MAP.items(): self.assertIsInstance(k, str) self.assertIsInstance(v, tuple) self.assertEqual(len(v), 2) self.assertIsInstance(v[0], str) # Test timezone unknown by pytz with self.assertRaises(UnknownTimeZone): EWSTimeZone.timezone('UNKNOWN') # Test timezone known by pytz but with no Winzone mapping tz = pytz.timezone('Africa/Tripoli') # This hack smashes the pytz timezone cache. Don't reuse the original timezone name for other tests tz.zone = 'UNKNOWN' with self.assertRaises(UnknownTimeZone): EWSTimeZone.from_pytz(tz) # Test __eq__ with non-EWSTimeZone compare self.assertFalse(EWSTimeZone.timezone('GMT') == pytz.utc) # Test from_ms_id() with non-standard MS ID self.assertEqual(EWSTimeZone.timezone('Europe/Copenhagen'), EWSTimeZone.from_ms_id('Europe/Copenhagen'))
def __init__(self): # Set Timezone to local Timezone self._tz = EWSTimeZone.localzone() # set start and end time of Calendarentry self.init_time() # Logger logging.basicConfig(level=logging.WARNING, handlers=[PrettyXmlHandler()]) # Config Parser config = configparser.ConfigParser() config.read('config.txt') try: LoginData = config["Credentials"] except KeyError as error: print('The key ' + str(error) + ' were not found in the config file') exit() _Login = { "user": LoginData['user'], "password": LoginData['password'], "Primary_SMTP_Adress": LoginData['Primary SMTP Adress'] } # Credentials and account self._credentials = Credentials(username=_Login["user"], password=_Login["password"]) # Autodiscover fails w/o mail_config. See issue #337 on github exchangelib self._mailConfig = Configuration(server='outlook.office365.com', credentials=self._credentials) self._account = Account( default_timezone=self._tz, primary_smtp_address=_Login["Primary_SMTP_Adress"], config=self._mailConfig, credentials=self._credentials, autodiscover=False, access_type=DELEGATE) # Init Database self._db = exchange_database.exchange_database()
def delete_malicious_email(recipient_email, attachment_name): # once the recipients are found we parse their mailboxes and delete the malicious email # Args: # recipient_email (str) : malware recipient email address # attachment_name (str) : the attachment file name to identify the malicious email # Returns: # True is it parses the mailboxes, False if an error occurs # TODO: # ban the infected recipient machine with either IP or FortiClient using item.is_read account = Account(primary_smtp_address=recipient_email, config=config, autodiscover=False, access_type=IMPERSONATION) tz = EWSTimeZone.localzone() right_now = tz.localize(EWSDateTime.now()) xmin_ago = right_now - timedelta(minutes=300) try: for item in account.inbox.filter(datetime_received__gt=xmin_ago): for attachment in item.attachments: if isinstance(attachment, FileAttachment): if attachment.name == attachment_name: # Either delete the infected email, or move it to trash #item.delete() item.move_to_trash() #send an alert to the recipient m = Message( account=account, subject='FortiSIEM: You have received a Virus ' + attachment_name, body= 'The maliicous email has been deleted from your inbox, please contact your administrator for further incident response', to_recipients=[ Mailbox(email_address=recipient_email) ], ) m.send() return True except: return False
def find_malicious_email(sender_email, file_name): # identify the attributes of the email with was sent with the malicious attachment # Args: # sender_email (str) : the sender email address # file_name (str) : the attachment file name to identify the malicious email # Returns: # two lists, sibjects of the infected emails, recipients of the infected email # TODO: # Could be imroved by getting the email sent_time and use it as a filter in xmin_ago instead of the current 300 seconds recipient_emails = [] emails_subjects = [] account = Account(primary_smtp_address=sender_email, config=config, autodiscover=False, access_type=IMPERSONATION) tz = EWSTimeZone.localzone() right_now = tz.localize(EWSDateTime.now()) xmin_ago = right_now - timedelta(minutes=300) for item in account.sent.filter(datetime_sent__gt=xmin_ago): #for item in account.sent.all().order_by('-datetime_received')[:10]: for attachment in item.attachments: if isinstance(attachment, FileAttachment): if attachment.name == file_name: emails_subjects.append(item.subject) # logging.debug('Subject: '+item.subject+' '+attachment.name) if item.to_recipients is not None: for index, val in enumerate(item.to_recipients): if val.email_address not in recipient_emails: recipient_emails.append(val.email_address) if item.cc_recipients is not None: for index, val in enumerate(item.cc_recipients): if val.email_address not in recipient_emails: recipient_emails.append(val.email_address) if item.bcc_recipients is not None: for index, val in enumerate(item.bcc_recipients): if val.email_address not in recipient_emails: recipient_emails.append(val.email_address) logging.debug(emails_subjects) logging.debug(recipient_emails) return emails_subjects, recipient_emails
def wait_for_message( self, criterion: str = "", timeout: float = 5.0, interval: float = 1.0, contains: bool = False, save_dir: str = None, ) -> Any: """Wait for email matching `criterion` to arrive into INBOX. :param criterion: wait for message matching criterion :param timeout: total time in seconds to wait for email, defaults to 5.0 :param interval: time in seconds for new check, defaults to 1.0 :param contains: if matching should be done using `contains` matching and not `equals` matching, default `False` is means `equals` matching :param save_dir: set to path where attachments should be saved, default None (attachments are not saved) :return: list of messages """ self.logger.info("Wait for messages") end_time = time.time() + float(timeout) filter_dict = self._get_filter_key_value(criterion, contains) items = None tz = EWSTimeZone.localzone() right_now = tz.localize(EWSDateTime.now()) # pylint: disable=E1101 while time.time() < end_time: items = self.account.inbox.filter( # pylint: disable=E1101 **filter_dict, datetime_received__gte=right_now) if items.count() > 0: break time.sleep(interval) messages = [] for item in items: attachments = [] if save_dir and len(item.attachments) > 0: attachments = self._save_attachments(item, save_dir) messages.append(self._get_email_details(item, attachments)) if len(messages) == 0: self.logger.info("Did not receive any matching items") return messages
def wait_for_message( self, criterion: str = "", timeout: float = 5.0, interval: float = 1.0, contains: bool = False, ) -> Any: """Wait for email matching `criterion` to arrive into INBOX. :param criterion: wait for message matching criterion :param timeout: total time in seconds to wait for email, defaults to 5.0 :param interval: time in seconds for new check, defaults to 1.0 :param contains: if matching should be done using `contains` matching and not `equals` matching, default `False` is means `equals` matching :return: list of messages """ self.logger.info("Wait for messages") end_time = time.time() + float(timeout) filter_dict = self._get_filter_key_value(criterion, contains) items = None tz = EWSTimeZone.localzone() right_now = tz.localize(EWSDateTime.now()) # pylint: disable=E1101 while time.time() < end_time: items = self.account.inbox.filter( # pylint: disable=E1101 **filter_dict, datetime_received__gte=right_now) if items.count() > 0: break time.sleep(interval) messages = [] for item in items: messages.append({ "subject": item.subject, "sender": item.sender, "datetime_received": item.datetime_received, "body": item.body, }) if len(messages) == 0: self.logger.info("Did not receive any matching items") return messages
def get_calendar_events(self): start = self.account.default_timezone.localize(EWSDateTime.now()) end = start + datetime.timedelta(days=30) events = [] unfolded_items = self.account.calendar.view(start=start, end=end) tz = EWSTimeZone.localzone() for item in unfolded_items: if "Canceled:" in item.subject: continue events.append({ "start": str(item.start.astimezone(tz).isoformat()), "end": str(item.end.astimezone(tz).isoformat()), "required_attendees": str(item.required_attendees), "optional_attendees": str(item.optional_attendees), "location": str(item.location), "message": str(item.text_body), "subject": str(item.subject), }) logging.info('Added "{}" event'.format(item.subject)) return events
def backup_messages(account: Account, until: datetime.date, clean_up=False): base_dir = 'account' inbox_dir = os.path.join(base_dir, 'inbox') sent_dir = os.path.join(base_dir, 'sent') os.makedirs(base_dir, exist_ok=True) os.makedirs(inbox_dir, exist_ok=True) os.makedirs(sent_dir, exist_ok=True) tz = EWSTimeZone.localzone() start_date = tz.localize(EWSDateTime(2000, 1, 1)) end_date = tz.localize(EWSDateTime(until.year, until.month, until.day)) qs = account.inbox \ .filter(datetime_received__range=(start_date, end_date)) \ .order_by('datetime_received') \ .only('mime_content', 'sender', 'subject', 'datetime_received') r1 = process_messages(qs, base_dir=inbox_dir, do_delete=clean_up, do_backup=True) qs = account.sent.all() \ .filter(datetime_received__range=(start_date, end_date)) \ .order_by('datetime_received') \ .only('mime_content', 'sender', 'subject', 'datetime_received') r2 = process_messages(qs, base_dir=sent_dir, do_delete=clean_up, do_backup=True) counter = collections.Counter() for d in [r1, r2]: counter.update(d) return dict(counter)
from exchangelib import DELEGATE, Credentials, Account, EWSTimeZone, UTC_NOW import sh if '--insecure' in sys.argv: # Disable TLS when Office365 can't get their certificate act together from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter # Disable insecure TLS 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 tz = EWSTimeZone.localzone() 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) a = Account(primary_smtp_address=c.username, credentials=c, access_type=DELEGATE, autodiscover=True) 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 import DELEGATE, Credentials, Account, EWSTimeZone import sh if '--insecure' in sys.argv: # Disable TLS when Office365 can't get their certificate act together from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter # Disable insecure TLS 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 tz = EWSTimeZone.localzone() sleep = int( sys.argv[1] ) # 1st arg to this script is the number of seconds to look back in the inbox now = datetime.now(tz=tz) 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) a = Account(primary_smtp_address=c.username, credentials=c, access_type=DELEGATE, autodiscover=True)
def validate_emails(self, filtered_emails): #print("Total Mails: "+str(len(filtered_emails))) try: tz = EWSTimeZone.localzone() missed_mails = [] customers = self.config.get("customers") not_responded_mail = dict() #Read older mail first print("Validing emails...") i = 0 j = 0 for item in filtered_emails.reverse(): #print(mail.sender) i = i + 1 print("Total mails:" + str(i)) if not isinstance(item, Message): print("========>") continue try: if item == None: print("Email missing....") elif item.sender == None: print("Email sender missing....") #print(mail) else: j = j + 1 print("Valid mails> " + str(j)) subject = str(item.subject).lower().replace('re: ', '') sender_address = item.sender.email_address from_name = item.sender.name datetime_received = item.datetime_received # Convert to local datetime datetime_received = datetime_received + timedelta( hours=5.50) sender_address = sender_address.lower() #print(str(datetime_received)) customers_matched = False for cus in customers: cus_email = cus.get("email") if sender_address.find(cus_email.lower()) != -1: customers_matched = True customer_alise = cus.get("alise") if customers_matched == True: # Last mail from customer m = { "from": sender_address, "alise": customer_alise, "subject": subject } datetime_received = m.update( {"datetime": str(datetime_received)}) m.update({"name": from_name}) not_responded_mail.update({subject: m}) else: # Last mail from HPE not_responded_mail.pop(subject, "None") except Exception: #pass; print("===== Processing Error ====") #logger.exception("processing email failed:") # Removing subject key from dict for nrm in not_responded_mail: missed_mails.append(not_responded_mail.get(nrm)) return missed_mails except Exception: print("Some Error...") pass
#!/usr/bin/env python3 # v1 Artem (c) # https://github.com/ecederstrand/exchangelib # https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/mailitem-object-outlook#properties import os, unicodedata, re, time, logging from exchangelib import Credentials, Account, Configuration, DELEGATE, ItemAttachment, Message, EWSTimeZone, EWSDateTime from datetime import datetime user = '******' password = '******' #for those who likes searching github for passwords ews_server = 'outlook.office365.com' remove_mails = True #this trigger is used for testing. False == do not remove mails tz = EWSTimeZone.localzone() # set local timezone # check OS and set path accordingly. Needed only for easy development if os.path.exists('C:/Windows'): MAIL_DIR = 'C:/Temp/phish/mails/' LOG_DIR = 'C:/Temp/phish/' DATA_DIR = 'C:/Temp/phish/' remove_mails = False #during tests do not remove phishing mails else: MAIL_DIR = '/media/nas01/Controls/PhishMe reports/mails/' LOG_DIR = '/media/nas01/Controls/PhishMe reports/' DATA_DIR = '/media/nas01/Controls/PhishMe reports/' logging.basicConfig(filename=LOG_DIR + 'phishme.log', level=logging.INFO)
break else: if "max_timeout" in command.keys(): __max_timeout__ = command["max_timeout"] print("Starting extraction of data from {}".format( command["email"])) conn = connect(**command) root = osjoin(command["path_output"], "data") try: makedirs(root, mode=0o777) except FileExistsError: pass if 'timezone' in command.keys(): local_time = EWSTimeZone.localzone() if command['timezone'].lower() == 'local' \ else EWSTimeZone.timezone(command['timezone'].lower()) else: local_time = EWSTimeZone() for f in conn.root.walk(): handle_folder(f, root) print("Time taken:" + str(datetime.now() - start_time)) exit(0) print("Time taken:" + str(datetime.now() - start_time)) exit(-1) else: print(usage) print("Time taken:" + str(datetime.now() - start_time)) exit(-1)