mustang-im / mustang

Mustang - New full-featured desktop email, chat and video conference client
https://mustang.im
Other
5 stars 1 forks source link

Protocol: Mail: EWS #56

Closed benbucksch closed 4 days ago

benbucksch commented 3 months ago

Implement EWS protocol for Microsoft Exchange on-premise and Office365.

Authentication via username and password (on prem) or OAuth2 (Office365).

benbucksch commented 3 months ago

Given that Exchange 2013 is

we don't need to support it anymore in Mustang. I.e. Exchange 2016 is the oldest Exchange server that we support. We support Exchange 2016, 2019, 2022 and Office365.

That said, if you would like to add support for Exchange 2013, you're free to do so :-)

NeilRashbrook commented 3 months ago

I've written some proof of concept code which I've pushed as branch ews-poc. It gets as far as listing folders.

Obviously the OAuth2 class needs to go in its own file, but where? I also need a utility class file for stuff such as XML2JSON, EWSError, EWSItemError, and some utility methods that I put on EWSAccount.

To try it out, you'll need to create the account preferences in the developer tools; you'll need values for hostname (e.g. outlook.office365.com) and emailAddress, then username is optional (defaults to emailAddress), password is required for non-Office 365 Exchange but only supported on Office 365 for certain accounts e.g. neil@beoenx.onmicrosoft.com, and userRealname is optional.

If you're using Office 365 with OAuth then you'll get an error Need interactive login, because I support the interactive flag. You'll want to bypass that in some way, e.g. by setting a breakpoint in the debugger and toggling the flag. Note that once you have a refresh token you can go back to noninteractive login.

I added my own code to fetch from arbitrary hosts because I've only just read your comment on the issue #55 regarding fetching

  • needs various places with specific workarounds in the code

Not true; Owl only has some workarounds for Exchange 2010 (SP1), and ExQuilla might even work on Exchange 2007.

benbucksch commented 3 months ago

Owl only has some workarounds for Exchange 2010

Oh, great. We can include Exchange 2013, then. But it remains low priority.

I added my own code to fetch from arbitrary hosts

I'm very curious to see that. More options are better.

Could you please push your code to a branch neil/ews ? Commit whenever you have something working, and definitely at the end of every work day. I will review on a PR level (i.e. all commits of the branch combined).

benbucksch commented 3 months ago

Happy to see that you're working on this and making progress! Congrats.

NeilRashbrook commented 3 months ago

Could you please push your code to a branch neil/ews ?

I did say that I'd pushed to branch ews-poc. I also would have appreciated some guidance as to how to break the code up into individual files.

benbucksch commented 3 months ago

branch ews-poc

Merged to master

how to break the code up into individual files

I've split up the files and commited that change.

NeilRashbrook commented 3 months ago

I've been looking at ky and it's somewhat awkward to use compared to axios.

As such, in branch ews-ky I kept my postHTTP method and just adapted it to use ky instead of axios.

benbucksch commented 3 months ago

Thanks for your detailed report on ky. I'm not set on ky specifically. However, axios has serious problems which prevent it from working on my machine. We can look into other solutions, mid-term. For now, keeping postHTTP is fine.

I renamed OAuth2ErrorEWS to OAuth2ErrorMS

I had the exactly same though, after my commit. Thanks for doing that.

OAuth2ErrorMS was supposed to take data as a parameter (I don't know why I passed it response as neither Owl nor ExQuilla do this) so I fixed that too.

It used that data for the default error message. What do we now get for 404, 401, 403 etc? BTW, on a relatec topic: I see that you pass throwHttpError = false. What happens in case of HTTP errors? I think we'd want them to throw, no?

branch ews-ky

Merged to master

NeilRashbrook commented 3 months ago

The problem is that we can get an OAuth2 error from the interactive login, where we just have the error parameters and no request.

I pass throwHttpError: false because at least in the EWS case (I can't remember what OAuth does, the Microsoft documentation doesn't specify the HTTP status) it will return an error status if something goes wrong but we want to inspect the response to get the error message.

NeilRashbrook commented 3 months ago

I don't know whether it makes a difference, but export http_proxy="" just sets it to the empty string; you may need unset http_proxy instead.

benbucksch commented 1 month ago

Status update:

EMail

Contacts

Calendar