def test_versioned_choice(self): field = ChoiceField('foo', field_uri='bar', choices={ Choice('c1'), Choice('c2', supported_from=EXCHANGE_2010) }) with self.assertRaises(ValueError): field.clean('XXX') # Value must be a valid choice field.clean('c2', version=None) with self.assertRaises(ErrorInvalidServerVersion): field.clean('c2', version=Version(EXCHANGE_2007)) field.clean('c2', version=Version(EXCHANGE_2010)) field.clean('c2', version=Version(EXCHANGE_2013))
def initialize_exchange_client(self, password=None): acc_credentials = Credentials(username=self.email_address, password=password) version = Version(build=Build(config.EXCHANGE_VERSION['major'], config.EXCHANGE_VERSION['minor'])) acc_config = Configuration(service_endpoint=config.EXCHANGE_URL, credentials=acc_credentials, auth_type='basic', version=version, retry_policy=FaultTolerance(max_wait=300)) self.exchange_client = Account(primary_smtp_address=self.email_address, config=acc_config, autodiscover=True, access_type='delegate')
def test_close(self): proc = psutil.Process() ip_addresses = { info[4][0] for info in socket.getaddrinfo('example.com', 80, socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_IP) } self.assertGreater(len(ip_addresses), 0) protocol = Protocol( config=Configuration(service_endpoint='http://example.com', credentials=Credentials('A', 'B'), auth_type=NOAUTH, version=Version(Build(15, 1)), retry_policy=FailFast())) session = protocol.get_session() session.get('http://example.com') self.assertEqual( len({ p.raddr[0] for p in proc.connections() if p.raddr[0] in ip_addresses }), 1) protocol.release_session(session) protocol.close() self.assertEqual( len({ p.raddr[0] for p in proc.connections() if p.raddr[0] in ip_addresses }), 0)
def test_invalid_field(self): test_field = Item.get_field_by_fieldname(fieldname='text_body') self.assertIsInstance(test_field, TextField) self.assertEqual(test_field.name, 'text_body') with self.assertRaises(InvalidField): Item.get_field_by_fieldname(fieldname='xxx') Item.validate_field(field=test_field, version=Version(build=EXCHANGE_2013)) with self.assertRaises(InvalidFieldForVersion) as e: Item.validate_field(field=test_field, version=Version(build=EXCHANGE_2010)) self.assertEqual( e.exception.args[0], "Field 'text_body' is not supported on server version Build=14.0.0.0, API=Exchange2010, Fullname=Microsoft " "Exchange Server 2010 (supported from: 15.0.0.0, deprecated from: None)" )
def test_protocol_instance_caching(self, m): # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials) m.get('https://example.com/EWS/types.xsd', status_code=200) base_p = Protocol(config=Configuration( service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'), auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast() )) for i in range(10): p = Protocol(config=Configuration( service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'), auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast() )) self.assertEqual(base_p, p) self.assertEqual(id(base_p), id(p)) self.assertEqual(hash(base_p), hash(p)) self.assertEqual(id(base_p._session_pool), id(p._session_pool))
def test_hardcode_all(self, m): # Test that we can hardcode everything without having a working server. This is useful if neither tasting or # guessing missing values works. Configuration( server='example.com', credentials=Credentials('foo', 'bar'), auth_type=NTLM, version=Version(build=Build(15, 1, 2, 3), api_version='foo'), )
def test_session(self, m): m.get('https://example.com/EWS/types.xsd', status_code=200) protocol = Protocol(config=Configuration( service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'), auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast() )) session = protocol.create_session() new_session = protocol.renew_session(session) self.assertNotEqual(id(session), id(new_session))
def test_magic(self): config = Configuration( server='example.com', credentials=Credentials('foo', 'bar'), auth_type=NTLM, version=Version(build=Build(15, 1, 2, 3), api_version='foo'), ) # Just test that these work str(config) repr(config)
def authenticate(self, username, password, server, build, account, verifyssl): """ Authenticates to Exchange server """ BaseProtocol.USERAGENT = "Shuffle Automation" if not verifyssl or verifyssl.lower().strip() == "false": BaseProtocol.HTTP_ADAPTER_CLS = RootCAAdapter processed_build = None if type(build) == str: try: processed_build = [int(x) for x in build.split(".")] if len(build) == 0: build = None elif len(build) < 2 or len(build) > 4: return { "account": None, "error": "Build requires at least major and minor version [Eg. 15.1], at most 4 number [Eg. 15.0.1.2345]", } except ValueError: return { "account": None, "error": "Build needs to be a sequence of numbers dot separated, not %s" % build, } try: credentials = Credentials(username, password) if processed_build: version = Version(build=Build(*processed_build)) config = Configuration(server=server, credentials=credentials, version=version) else: config = Configuration(server=server, credentials=credentials) account = Account(account, config=config, autodiscover=False, access_type=DELEGATE) account.root.refresh() except (exchangelib.errors.TransportError, Exception) as error: return { "account": None, "error": "Can't connect to Exchange server: %s" % (error), } return {"account": account, "error": False}
def test_decrease_poolsize(self): protocol = Protocol(config=Configuration( service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'), auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast() )) self.assertEqual(protocol._session_pool.qsize(), Protocol.SESSION_POOLSIZE) protocol.decrease_poolsize() self.assertEqual(protocol._session_pool.qsize(), 3) protocol.decrease_poolsize() self.assertEqual(protocol._session_pool.qsize(), 2) protocol.decrease_poolsize() self.assertEqual(protocol._session_pool.qsize(), 1) with self.assertRaises(SessionPoolMinSizeReached): protocol.decrease_poolsize() self.assertEqual(protocol._session_pool.qsize(), 1)
def test_close(self): # Don't use example.com here - it does not resolve or answer on all ISPs proc = psutil.Process() ip_addresses = { info[4][0] for info in socket.getaddrinfo('httpbin.org', 80, socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_IP) } def conn_count(): return len( [p for p in proc.connections() if p.raddr[0] in ip_addresses]) self.assertGreater(len(ip_addresses), 0) protocol = Protocol( config=Configuration(service_endpoint='http://httpbin.org', credentials=Credentials('A', 'B'), auth_type=NOAUTH, version=Version(Build(15, 1)), retry_policy=FailFast(), max_connections=3)) # Merely getting a session should not create conections session = protocol.get_session() self.assertEqual(conn_count(), 0) # Open one URL - we have 1 connection session.get('http://httpbin.org') self.assertEqual(conn_count(), 1) # Open the same URL - we should still have 1 connection session.get('http://httpbin.org') self.assertEqual(conn_count(), 1) # Open some more connections s2 = protocol.get_session() s2.get('http://httpbin.org') s3 = protocol.get_session() s3.get('http://httpbin.org') self.assertEqual(conn_count(), 3) # Releasing the sessions does not close the connections protocol.release_session(session) protocol.release_session(s2) protocol.release_session(s3) self.assertEqual(conn_count(), 3) # But closing explicitly does protocol.close() self.assertEqual(conn_count(), 0)
def __init__(self, email: Email, config: EWSConfig): self._email = email self._config = config self._gcs_client = storage.Client() credentials = Credentials(config.email_account, config.password) version = Version(build=Build(config.exchange_version["major"], config.exchange_version["minor"])) ews_config = Configuration( service_endpoint=config.exchange_url, credentials=credentials, auth_type="basic", version=version, retry_policy=FaultTolerance(max_wait=300), ) self._account = Account( primary_smtp_address=config.email_account, config=ews_config, autodiscover=False, access_type="delegate", ) # Setup reply-mail client. recipient = "" if self._config.hardcoded_recipients: recipient = self._config.mail_to_mapping.get(self._email.recipient) else: recipient = self._config.mail_to_mapping.get("STANDARD") acc_credentials = Credentials( username=recipient["sender_account"], password=util.get_secret(os.environ["PROJECT_ID"], recipient["sender_account_secret"]), ) acc_config = Configuration( service_endpoint=config.exchange_url, credentials=acc_credentials, auth_type="basic", version=version, retry_policy=FaultTolerance(max_wait=300), ) self._reply_email_account = Account( primary_smtp_address=recipient["sender_account"], config=acc_config, autodiscover=False, access_type="delegate", )
def test_decrease_poolsize(self): # Test increasing and decreasing the pool size max_connections = 3 protocol = Protocol(config=Configuration( service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'), auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast(), max_connections=max_connections)) self.assertEqual(protocol._session_pool.qsize(), 0) self.assertEqual(protocol.session_pool_size, 0) protocol.increase_poolsize() protocol.increase_poolsize() protocol.increase_poolsize() with self.assertRaises(SessionPoolMaxSizeReached): protocol.increase_poolsize() self.assertEqual(protocol._session_pool.qsize(), max_connections) self.assertEqual(protocol.session_pool_size, max_connections) protocol.decrease_poolsize() protocol.decrease_poolsize() with self.assertRaises(SessionPoolMinSizeReached): protocol.decrease_poolsize() self.assertEqual(protocol._session_pool.qsize(), 1)
def smtp_connect(server, email, username, password): creds = Credentials(username = username, password = password) config = Configuration(credentials = creds, server = server) version = Version() return Account(primary_smtp_address=email, config = config, credentials=creds, autodiscover=False, access_type=DELEGATE)
def test_versioned_field(self): field = TextField('foo', field_uri='bar', supported_from=EXCHANGE_2010) with self.assertRaises(ErrorInvalidServerVersion): field.clean('baz', version=Version(EXCHANGE_2007)) field.clean('baz', version=Version(EXCHANGE_2010)) field.clean('baz', version=Version(EXCHANGE_2013))
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Build, Version, Attendee credentials = Credentials(username='******', password='******') version = Version(build=Build(14, 3, 123, 4)) config = Configuration(server='mail.snellemantom.com.au', credentials=credentials, version=version, auth_type=NTLM) my_account = Account(primary_smtp_address='*****@*****.**', credentials=credentials, config=config, access_type=DELEGATE) for item in my_account.calendar.all().order_by('-datetime_received')[:100]: try: if '@snellemantom.com.au' not in item.required_attendees \ or 'boardroom' in item.required_attendees \ or 'meetingroom' in item.required_attendees: attendees = [] Subject = str(item.subject) Start = str(item.start) End = str(item.end) Location = str(item.location) for x in item.required_attendees: attendees.append( str(x.mailbox.name).replace(" | Snelleman Tom", "").replace("'", "")) print(Subject + " - " + Location + " - " + Start + " to " + End +
["*****@*****.**", "*****@*****.**"], "cc_email": HR_CREW + ["*****@*****.**"] }, "CITY MANAGER": { "receiver_name": ["Phindile", "Ashwin"], "receiver_email": [ "*****@*****.**", "*****@*****.**" ], "cc_email": HR_CREW + ["*****@*****.**"] }, } EXCHANGE_VERSION = Version(build=Build(15, 0, 1395, 4000)) def get_data_df(filename, minio_access, minio_secret): with tempfile.NamedTemporaryFile() as temp_data_file: logging.debug("Pulling data from Minio bucket...") result = minio_utils.minio_to_file(temp_data_file.name, BUCKET, minio_access, minio_secret, CLASSIFICATION, minio_filename_override=filename) assert result logging.debug(f"Reading in raw data from '{temp_data_file.name}'...") data_df = pandas.read_csv(temp_data_file)
def get_version(version_str): if version_str not in VERSIONS: raise Exception("%s is unsupported version: %s. Choose one of" % (version_str, "\\".join(VERSIONS.keys()))) return Version(VERSIONS[version_str])
# Loading secrets with open(secrets_filename, "r") as secrets_file: secrets = json.load(secrets_file) # Loading passwords with open(passwords_filename, "r") as passwords_file: passwords = json.load(passwords_file) # Loading email template with open(email_filename, "r") as email_file: email_template = jinja2.Template(email_file.read()) logging.info("Loaded Secrets, Password and Email template file.") # Setting up Exchange Creds version = Version(build=Build(15, 0, 1395, 4000)) credentials = Credentials(username=secrets['proxy']['username'], password=secrets["proxy"]["password"]) config = Configuration(server="webmail.capetown.gov.za", credentials=credentials, version=version, auth_type=NTLM) account = Account(primary_smtp_address="*****@*****.**", config=config, autodiscover=False, access_type=DELEGATE) logging.info("Authenticated with Exchange") with open(logo_filename, 'rb') as fp: city_logo_attachment = FileAttachment(name='city_logo.png', content=fp.read())
def test_default_api_version(self): # Test that a version gets a reasonable api_version value if we don't set one explicitly version = Version(build=Build(15, 1, 2, 3)) self.assertEqual(version.api_version, 'Exchange2016')
def test_from_response(self, m): # Test fallback to suggested api_version value when there is a version mismatch and response version is fishy version = Version.from_soap_header( 'Exchange2007', to_xml(b'''\ <s:Header> <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="V2016_10_10" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/> </s:Header>''')) self.assertEqual(version.api_version, EXCHANGE_2007.api_version()) self.assertEqual(version.api_version, 'Exchange2007') self.assertEqual(version.build, Build(15, 1, 845, 22)) # Test that override the suggested version if the response version is not fishy version = Version.from_soap_header( 'Exchange2013', to_xml(b'''\ <s:Header> <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="HELLO_FROM_EXCHANGELIB" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/> </s:Header>''')) self.assertEqual(version.api_version, 'HELLO_FROM_EXCHANGELIB') # Test that we override the suggested version with the version deduced from the build number if a version is not # present in the response version = Version.from_soap_header( 'Exchange2013', to_xml(b'''\ <s:Header> <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/> </s:Header>''')) self.assertEqual(version.api_version, 'Exchange2016') # Test that we use the version deduced from the build number when a version is not present in the response and # there was no suggested version. version = Version.from_soap_header( None, to_xml(b'''\ <s:Header> <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/> </s:Header>''')) self.assertEqual(version.api_version, 'Exchange2016') # Test various parse failures with self.assertRaises(TransportError): Version.from_soap_header( 'Exchange2013', to_xml(b'''\ <s:Header> <foo/> </s:Header>''')) with self.assertRaises(TransportError): Version.from_soap_header( 'Exchange2013', to_xml(b'''\ <s:Header> <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" Version="V2016_10_10" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/> </s:Header>'''))