Skip to content

Commit

Permalink
Merge pull request #20 from swimlane/3_0_0_overhaul
Browse files Browse the repository at this point in the history
3 0 0 Overhaul
  • Loading branch information
MSAdministrator authored Jul 6, 2021
2 parents e35ad74 + 99ca58a commit 7cbc384
Show file tree
Hide file tree
Showing 116 changed files with 4,821 additions and 1,780 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/pyews.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Testing py-ews

on:
push

jobs:
build:

runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
# install dependencies on Ubuntu
- if: matrix.os == 'ubuntu-latest'
name: Install build dependencies
run: |
sudo apt-get install libxml2-dev libxslt-dev python-dev
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -U -r requirements.txt
pip install -U -r test-requirements.txt
- name: Run Tests
run: |
pip install -U -r requirements.txt
pip install -U -r test-requirements.txt
python -m pytest
189 changes: 90 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,37 @@
* Autodiscover support
* Delegation support
* Impersonation support
* OAUth2 support
* Retrieve all mailboxes that can be searched based on credentials provided
* Search a list of (or single) mailboxes in your Exchange environment using all supported search attributes
* Delete email items from mailboxes in your Exchange environment
* Retrieve mailbox inbox rules for a specific account
* Find additional hidden inbox rules for a specified account
* Plus more supported endpoints

Currently this package supports the following endpoint's:

* [DeleteItem](docs/services/deleteitem.md)
* [GetInboxRules](docs/services/getinboxrules.md)
* [FindHiddenInboxRules](docs/services/findhiddeninboxrules.md)
* [GetSearchableMailboxes](docs/services/getsearchablemailboxes.md)
* [ResolveNames](docs/services/resolvenames.md)
* [SearchMailboxes](docs/services/searchmailboxes.md)
* [AddDelegate](docs/endpoint/adddelegate.md)
* [ConvertId](docs/endpoint/convertid.md)
* [CreateFolder](docs/endpoint/createfolder.md)
* [CreateItem](docs/endpoint/createitem.md)
* [DeleteFolder](docs/endpoint/deletefolder.md)
* [DeleteItem](docs/endpoint/deleteitem.md)
* [ExecuteSearch](docs/endpoint/executesearch.md)
* [ExpandDL](docs/endpoint/expanddl.md)
* [FindFolder](docs/endpoint/findfolder.md)
* [FindItem](docs/endpoint/finditem.md)
* [GetAttachment](docs/endpoint/getattachment.md)
* [GetHiddenInboxRules](docs/endpoint/gethiddeninboxrules.md)
* [GetInboxRules](docs/endpoint/getinboxrules.md)
* [GetItem](docs/endpoint/getitem.md)
* [GetSearchableMailboxes](docs/endpoint/getsearchablemailboxes.md)
* [GetServiceConfiguration](docs/endpoint/getserviceconfiguration.md)
* [GetUserSettings](docs/endpoint/getusersettings.md)
* [ResolveNames](docs/endpoint/resolvenames.md)
* [SearchMailboxes](docs/endpoint/searchmailboxes.md)
* [SyncFolderHierarchy](docs/endpoint/syncfolderhierarchy.md)
* [SyncFolderItems](docs/endpoint/syncfolderitems.md)


## Installation
Expand All @@ -58,129 +75,113 @@ pip install py-ews
pip install py-ews
```

## Usage example
## Creating EWS Object

The first step in using **py-ews** is that you need to create a [UserConfiguration](docs/configuration/userconfiguration.md) object. Think of this as all the connection information for Exchange Web Services. An example of creating a [UserConfiguration](docs/configuration/userconfiguration.md) using Office 365 Autodiscover is:
For convience, `py-ews` offers a simple interface to access all available EWS `endpoints` in the form of methods. Each of these methods have
their own required inputs based on the individual endpoint. No matter which endpoint you use, you must first instantiate the `EWS` class by providing
authentication details.

When instantiating the `EWS` class you will need to provide credentials which will be used for all methods within the EWS class.

```python
from pyews import UserConfiguration
from pyews import EWS

userconfig = UserConfiguration(
ews = EWS(
'[email protected]',
'Password1234'
)
```


If you would like to use an alternative [Autodiscover](docs/configuration/autodiscover.md) endpoint (or any alternative endpoint) then please provide one using the `endpoint` named parameter:
If you would like to use an alternative EWS URL then provide one using the `ews_url` parameter when instantiating the EWS class.

```python
from pyews import UserConfiguration
from pyews import EWS

userconfig = UserConfiguration(
ews = EWS(
'[email protected]',
'Password1234',
endpoint='https://outlook.office365.com/autodiscover/autodiscover.svc'
ews_url='https://outlook.office365.com/autodiscover/autodiscover.svc'
)
```

For more information about creating a [UserConfiguration](docs/configuration/userconfiguration.md) object, please see the full documentation.

Now that you have a [UserConfiguration](docs/configuration/userconfiguration.md) object, we can now use any of the available service endpoints. This example will demonstrate how you can identify which mailboxes you have access to by using the [GetSearchableMailboxes](docs/services/getsearchablemailboxes.md) EWS endpoint.
If you would like to specify a specific version of Exchange to use, you can provide that using the `exchange_version` parameter. By default `pyews` will attempt all Exchange versions as well as multiple static and generated EWS URLs.

Once you have identified a list of mailbox reference ids, then you can begin searching all of those mailboxes by using the [SearchMailboxes](docs/services/searchmailboxes.md) EWS endpoint.
Finally, if you would like to `impersonate_as` a specific user you must provide their primary SMTP address when instantiating the `EWS` class object:

The returned results will then be deleted (moved to Deleted Items folder) from Exchange using the [DeleteItem](docs/services/deleteitem.md) EWS endpoint.

```python
from pyews import UserConfiguration
from pyews import GetSearchableMailboxes
from pyews import SearchMailboxes
from pyews import DeleteItem
from pyews import EWS

userconfig = UserConfiguration(
ews = EWS(
'[email protected]',
'Password1234'
'Password1234',
impersonate_as='[email protected]'
)

# get searchable mailboxes based on your accounts permissions
referenceid_list = []
for mailbox in GetSearchableMailboxes(userconfig).run():
referenceid_list.append(mailbox['reference_id'])

# let's search all the referenceid_list items
messages_found = []
for search in SearchMailboxes(userconfig).run('subject:account', referenceid_list):
messages_found.append(search['id'])
# we can print the results first if we want
print(search['subject'])
print(search['id'])
print(search['sender'])
print(search['to_recipients'])
print(search['created_time'])
print(search['received_time'])
#etc.

# if we wanted to now delete a specific message then we would call the DeleteItem
# class like this but we can also pass in the entire messages_found list
deleted_message_response = DeleteItem(userconfig).run(messages_found[2])

print(deleted_message_response)
```

The following is an example of the output returned when calling the above code:

```text
YOUR ACCOUNT IS ABOUT TO EXPIRE! UPGRADE NOW!!!
AAMkAGZjOTlkOWExLTM2MDEtNGI3MS0..............
Josh Rickard
Research
2019-02-28T18:28:36Z
2019-02-28T18:28:36Z
Upgrade Your Account!
AAMkADAyNTZhNmMyLWNmZTctNDIyZC0..............
Josh Rickard
Josh Rickard
2019-01-24T18:41:11Z
2019-01-24T18:41:11Z
New or modified user account information
AAMkAGZjOTlkOWExLTM2MDEtNGI3MS04..............
Microsoft Online Services Team
Research
2019-01-24T18:38:06Z
2019-01-24T18:38:06Z
[{'MessageText': 'Succesfull'}]
```


**For more examples and usage, please refer to the individual class documentation**

* [Services](docs/services/root.md)
* [Configuration](docs/configuration/root.md)
### Exchange Search Multi-Threading

You can also specify `multi_threading=True` and when you search mailboxes we will use multi-threading to perform the search.

## Using Provided Methods

Once you have instantiated the EWS class with your credentials, you will have access to pre-exposed methods for each endpoint. These methods are:

* get_service_configuration
* get_searchable_mailboxes
* get_user_settings
* resolve_names
* execute_ews_search
* execute_outlook_search
* get_inbox_rules
* get_hidden_inbox_rules
* get_item
* get_attachment
* sync_folder_hierarchy
* sync_folder_items
* create_item
* delete_item
* search_and_delete_message
* get_domain_settings
* find_items
* search_mailboxes_using_find_item
* create_search_folder
* find_search_folder
* delete_search_folder

## Access Classes Directly

In some cases you may want to skip using the `EWS` interface class and build your own wrapper around `py-ews`. To do this, you must first import the `Authentication` class and provide
credential and other details before invoking a desired `endpoint`. Below is an example of this:

## Development setup
```python
from pyews import Authentication, GetSearchableMailboxes

I have provided a [Dockerfile](https://github.com/swimlane/pyews/blob/master/Dockerfile) with all the dependencies and it is currently calling [test.py](https://github.com/swimlane/pyews/blob/master/Dockerfilebin\pyews_test.py). If you want to test new features, I recommend that you use this [Dockerfile](https://github.com/swimlane/pyews/blob/master/Dockerfile). You can call the following to build a new container, but keep the dependencies unless they have changed in your requirements.txt or any other changes to the [Dockerfile](https://github.com/swimlane/pyews/blob/master/Dockerfile).
Authentication(
'[email protected]',
'Password1234'
)

```
docker build --force-rm -t pyews .
reference_id_list = []
for mailbox in GetSearchableMailboxes().run():
reference_id_list.append(mailbox.get('reference_id'))
print(mailbox)
```

To run the container, use the following:
As you can see, you must instantiate the `Authentication` class first before calling an endpoint. By the way, you can import all `endpoints` directly without using the `EWS` interface.

```
docker run pyews
```

I am new to Unit Testing, but I am working on that as time permits. If you would like to help, I wouldn't be sad about it. :)
**For more examples and usage, please refer to the individual class documentation**

* [Endpoint](docs/endpoint/root.md)

## Release History

* 1.0.0
* Initial release of py-ews and it is still considered a work in progress
* 2.0.0
* Revamped logic and overhauled all endpoints and classes
* 3.0.0
* Refactored completely - this can be considered a new version


## Meta
Expand All @@ -196,13 +197,3 @@ Distributed under the MIT license. See ``LICENSE`` for more information.
3. Commit your changes (`git commit -am 'Add some fooBar'`)
4. Push to the branch (`git push origin feature/fooBar`)
5. Create a new Pull Request

```eval_rst
.. toctree::
:maxdepth: 2
:caption: Contents:
services/root
configuration/root
utils/root
```
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXBUILD = python3 -m sphinx
SOURCEDIR = .
BUILDDIR = _build

Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
#html_static_path = ['_static']

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
Expand Down
15 changes: 0 additions & 15 deletions docs/configuration/autodiscover.md

This file was deleted.

11 changes: 0 additions & 11 deletions docs/configuration/credentials.md

This file was deleted.

10 changes: 0 additions & 10 deletions docs/configuration/root.md

This file was deleted.

11 changes: 0 additions & 11 deletions docs/configuration/userconfiguration.md

This file was deleted.

11 changes: 11 additions & 0 deletions docs/core/authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Authentication

The Authentication class is used to configure all communications with Exchange. Additionally, this class contains settings which are used when generating and making SOAP requests.

This class defines the authenication credentials, ews_url(s) to attempt, exchange versions, impersonation details, and more.

```eval_rst
.. autoclass:: pyews.core.authentication.Authentication
:members:
:undoc-members:
```
9 changes: 9 additions & 0 deletions docs/core/core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Core

The Core class is inherited by all other classes within `py-ews`. This class controls logging as well as parsing of EWS SOAP request responses.

```eval_rst
.. autoclass:: pyews.core.core.Core
:members:
:undoc-members:
```
9 changes: 9 additions & 0 deletions docs/core/endpoints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Endpoints

This documentation provides details about the set and generated API endpoints used within the `pyews` package.

```eval_rst
.. autoclass:: pyews.core.endpoints.Endpoints
:members:
:undoc-members:
```
Loading

0 comments on commit 7cbc384

Please sign in to comment.