Skip to content

Commit 0add215

Browse files
committed
Avoid double version issue in requirements; update readme
Also streamline `get_title` and reorder notification handling now that pystray (0.19.4+) has notifications on macOS
1 parent 1e28891 commit 0add215

File tree

3 files changed

+14
-22
lines changed

3 files changed

+14
-22
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Email services that support IMAP and/or SMTP access are increasingly requiring t
77

88
### Example use-cases
99
- You need to use an Office 365 email account, but don't get on with Outlook. The email client you like doesn't support OAuth 2.0.
10-
- You currently use Gmail via IMAP/SMTP with your raw account credentials (i.e., your real password). You've received a notification that Google is disabling this access at the end of May 2022, but you don't want to use an [App Password](https://support.google.com/accounts/answer/185833) (or cannot enable this option).
10+
- You used to use Gmail via IMAP/SMTP with your raw account credentials (i.e., your real password), but cannot do this now that Google has disabled this method, and don't want to use an [App Password](https://support.google.com/accounts/answer/185833) (or cannot enable this option).
1111
- You have an account already set up in an email client, and you need to switch it to OAuth 2.0 authentication. You can edit the server details, but the client forces you to delete and re-add the account to enable OAuth 2.0, and you don't want to do this.
1212
- You have made your own script or application that sends or receives email, but it doesn't support OAuth 2.0, and you don't want to have to modify it to implement this.
1313
- You run a server with multiple services that use IMAP/SMTP, and you don't want to have to set up OAuth 2.0 independently for each one.
@@ -32,9 +32,9 @@ After your accounts are fully set-up and authorised, no further proxy interactio
3232
### OAuth 2.0 client credentials
3333
As part of the proxy setup process you need to provide an OAuth 2.0 `client_id` and `client_secret` to allow it to authenticate with email servers on your behalf.
3434

35-
If you have an existing client ID and secret for a desktop app, you can use these directly in the proxy. You can also reuse the client ID and secret from any email client that supports IMAP/SMTP OAuth 2.0 authentication with the email server you would like to connect to.
35+
If you have an existing client ID and secret for a desktop app, you can use these directly in the proxy. If this is not possible, you can also reuse the client ID and secret from any email client that supports IMAP/SMTP OAuth 2.0 authentication with the email server you would like to connect to (such as the various [open](https://github.com/mozilla/releases-comm-central/blob/master/mailnews/base/src/OAuth2Providers.jsm) [source](https://gitlab.gnome.org/GNOME/evolution-data-server/-/blob/master/CMakeLists.txt) [clients](https://gitlab.gnome.org/GNOME/gnome-online-accounts/-/blob/master/meson_options.txt) with OAuth 2.0 support), but please do this with care and restraint as access through reused tokens will be associated with the token owner rather than your own client.
3636

37-
If you do not have access to credentials for an existing client you will need to register your own. The process to do this is different for each provider, but the registration guides for several common ones are linked below. In all cases, when registering, make sure your client is set up to use an OAuth scope that will give it permission to access IMAP/SMTP – see the sample configuration file for examples.
37+
If you do not have access to credentials for an existing client you will need to register your own. The process to do this is different for each provider, but the registration guides for several common ones are linked below. In all cases, when registering, make sure your client is set up to use an OAuth scope that will give it permission to access IMAP/SMTP – see the sample configuration file for examples.
3838

3939
- Office 365: register a new [Microsoft identity application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
4040
- Gmail / Google Workspace: register a [Google API desktop app client](https://developers.google.com/identity/protocols/oauth2/native-app)
@@ -90,7 +90,7 @@ Please feel free to [open an issue](https://github.com/simonrob/email-oauth2-pro
9090

9191

9292
## Advanced / experimental features
93-
The [plugins branch](https://github.com/simonrob/email-oauth2-proxy/tree/plugins) has a semi-experimental new feature that enables the use of separate scripts to modify IMAP/SMTP commands when they are received from the client or server before passing through to the other side of the connection. This allows a wide range of additional capabilities or triggers to be added the proxy. For example, the [IMAPIgnoreSentMessageUpload plugin](https://github.com/simonrob/email-oauth2-proxy/blob/plugins/plugins/IMAPIgnoreSentMessageUpload.py) intercepts any client commands to add emails to the IMAP sent messages mailbox, which resolves message duplication issues for servers that automatically do this when emails are received via SMTP (e.g., Office 365, Gmail, etc). See the documentation and examples in this branch for further details and setup instructions.
93+
The [plugins branch](https://github.com/simonrob/email-oauth2-proxy/tree/plugins) has a semi-experimental new feature that enables the use of separate scripts to modify IMAP/SMTP commands when they are received from the client or server before passing through to the other side of the connection. This allows a wide range of additional capabilities or triggers to be added the proxy. For example, the [IMAPIgnoreSentMessageUpload plugin](https://github.com/simonrob/email-oauth2-proxy/blob/plugins/plugins/IMAPIgnoreSentMessageUpload.py) intercepts any client commands to add emails to the IMAP sent messages mailbox, which resolves message duplication issues for servers that automatically do this when emails are received via SMTP (e.g., Office 365, Gmail, etc). The [SMTPBlackHole plugin](https://github.com/simonrob/email-oauth2-proxy/blob/plugins/plugins/SMTPBlackHole.py) gives the impression emails are being sent but actually silently discards them, which is useful for testing email sending tools. See the documentation and examples in this branch for further details, additional sample plugins and setup instructions.
9494

9595

9696
## Potential improvements (pull requests welcome)

emailproxy.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ def authenticate_connection(self, username, password, command='login'):
730730

731731

732732
class SMTPOAuth2ClientConnection(OAuth2ClientConnection):
733-
"""The client side of the connection - intercept AUTH LOGIN commands and replace with OAuth 2.0"""
733+
"""The client side of the connection - intercept AUTH PLAIN and AUTH LOGIN commands and replace with OAuth 2.0"""
734734

735735
class AUTH(enum.Enum):
736736
PENDING = 1
@@ -1050,7 +1050,7 @@ def process_data(self, byte_data):
10501050

10511051

10521052
class OAuth2Proxy(asyncore.dispatcher):
1053-
"""Listen on SERVER_ADDRESS:SERVER_PORT, creating a ServerConnection + ClientConnection for each new connection"""
1053+
"""Listen on local_address, creating an OAuth2ServerConnection + OAuth2ClientConnection for each new connection"""
10541054

10551055
def __init__(self, proxy_type, local_address, server_address, custom_configuration):
10561056
asyncore.dispatcher.__init__(self)
@@ -1089,7 +1089,7 @@ def handle_accepted(self, connection, address):
10891089
error_text = '%s encountered an SSL error - is the server\'s starttls setting correct? Current ' \
10901090
'value: %s' % (self.info_string(), self.custom_configuration['starttls'])
10911091
Log.error(error_text)
1092-
if sys.platform == 'darwin':
1092+
if sys.platform in ['darwin', 'win32']:
10931093
Log.error('If you encounter this error repeatedly, please check that you have correctly configured '
10941094
'python root certificates; see: https://github.com/simonrob/email-oauth2-proxy/issues/14')
10951095
connection.send(b'%s\r\n' % self.bye_message(error_text).encode('utf-8'))
@@ -1205,14 +1205,6 @@ def handle_close(self):
12051205
Log.error('Abandoning restart of', self.info_string(), 'due to repeated exception:', Log.error_string(e))
12061206

12071207

1208-
class AuthorisationWindow:
1209-
"""Used to dynamically add the missing get_title method to a pywebview window"""
1210-
1211-
# noinspection PyUnresolvedReferences
1212-
def get_title(self):
1213-
return self.title
1214-
1215-
12161208
if sys.platform == 'darwin':
12171209
# noinspection PyUnresolvedReferences,PyMethodMayBeStatic,PyPep8Naming,PyUnusedLocal
12181210
class ProvisionalNavigationBrowserDelegate:
@@ -1546,7 +1538,7 @@ def create_authorisation_window(self, request):
15461538
authorisation_window = webview.create_window(window_title, html=auth_page, on_top=True, text_select=True)
15471539
else:
15481540
authorisation_window = webview.create_window(window_title, request['permission_url'], on_top=True)
1549-
setattr(authorisation_window, 'get_title', AuthorisationWindow.get_title) # add missing get_title method
1541+
setattr(authorisation_window, 'get_title', lambda window: window.title) # add missing get_title method
15501542

15511543
# pywebview 3.6+ moved window events to a separate namespace in a non-backwards-compatible way
15521544
if pkg_resources.parse_version(
@@ -1763,11 +1755,7 @@ def toggle_debug(_, item):
17631755
# noinspection PyUnresolvedReferences
17641756
def notify(self, title, text):
17651757
if self.icon:
1766-
if self.icon.HAS_NOTIFICATION:
1767-
self.icon.remove_notification()
1768-
self.icon.notify('%s: %s' % (title, text))
1769-
1770-
elif sys.platform == 'darwin':
1758+
if sys.platform == 'darwin': # prefer native notifications over the osascript approach
17711759
user_notification = AppKit.NSUserNotification.alloc().init()
17721760
user_notification.setTitle_(title)
17731761
user_notification.setInformativeText_(text)
@@ -1782,6 +1770,10 @@ def notify(self, title, text):
17821770
title = title.replace(*replacement)
17831771
os.system('osascript -e \'display notification "%s" with title "%s"\'' % (text, title))
17841772

1773+
elif self.icon.HAS_NOTIFICATION:
1774+
self.icon.remove_notification()
1775+
self.icon.notify('%s: %s' % (title, text))
1776+
17851777
else:
17861778
Log.info(title, text) # last resort
17871779
else:

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ configobj
22
cryptography
33
pillow
44
pystray
5-
pywebview
5+
pywebview; sys_platform != 'win32' # specify platform to avoid double requirement error with older pip versions
66
timeago
77

88
# used to improve menu bar interaction, provide native notifications, handle system events and output to unified logging

0 commit comments

Comments
 (0)