Update Gmail access with OAuth 2

This commit is contained in:
Grégory Soutadé 2022-11-20 19:58:12 +01:00
parent b1feb004e8
commit 5690307c63
2 changed files with 86 additions and 20 deletions

76
examples/gmail.py Normal file
View File

@ -0,0 +1,76 @@
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Setup : https://developers.google.com/gmail/api/quickstart/python
# Need to have credentials.json were you call main script
#
# File imported from https://github.com/googleworkspace/python-samples/blob/main/gmail/quickstart/quickstart.py
#
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
creds = None
def _initCreds():
global creds
if creds: return
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('./token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
def getUnreadMails():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
_initCreds()
service = build('gmail', 'v1', credentials=creds)
nbUnreadMessages = 0
pageToken = ''
while True:
results = service.users().messages().list(userId='me', labelIds=['UNREAD'],\
includeSpamTrash=False, pageToken=pageToken)\
.execute()
nbUnreadMessages += len(results.get('messages', []))
pageToken = results.get('nextPageToken', '')
if not pageToken: break
return nbUnreadMessages

View File

@ -23,11 +23,11 @@ import time
import requests import requests
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
import xml.dom.minidom import xml.dom.minidom
import getpass
from threading import Thread from threading import Thread
from signal import signal, SIGINT from signal import signal, SIGINT
import sys import sys
from genericmonitor import * from genericmonitor import *
from gmail import getUnreadMails
PURPLE_CONV_UPDATE_UNSEEN = 4 PURPLE_CONV_UPDATE_UNSEEN = 4
PURPLE_MESSAGE_SEND = 0 PURPLE_MESSAGE_SEND = 0
@ -59,31 +59,23 @@ class PidginConversation:
class EventThread(Thread,GenericMonitor): class EventThread(Thread,GenericMonitor):
SLEEP_TIME = 30 SLEEP_TIME = 30
MAIL_ADDRESS='XXX@gmail.com'
def stop(self): def stop(self):
self._stopLoop = True self._stopLoop = True
self.stopMainLoop() self.stopMainLoop()
def _getMail(self): def _getMail(self):
address = "https://mail.google.com/mail/feed/atom"
auth = HTTPBasicAuth(self.MAIL_ADDRESS, self._mail_password)
req = requests.get(address, auth=auth)
text = '' text = ''
style = '' style = ''
if req.status_code == requests.codes.ok: try:
dom = xml.dom.minidom.parseString(req.text) nb_messages = getUnreadMails()
try: if nb_messages == 1:
nb_messages = int(dom.getElementsByTagName('fullcount')[0].firstChild.nodeValue) text = '1 msg'
if nb_messages == 1: elif nb_messages > 1:
text = '1 msg' text = '%d msgs' % (nb_messages)
elif nb_messages > 1: style = 'color:white'
text = '%d msgs' % (nb_messages) except Exception as e:
style = 'color:white' text = str(e)
except Exception as e:
text = str(e)
else:
text = 'Mail error %d' % (req.status_code)
self.mailWidget.setText(text) self.mailWidget.setText(text)
self.mailWidget.setStyle(style) self.mailWidget.setStyle(style)
@ -103,8 +95,6 @@ class EventThread(Thread,GenericMonitor):
self.add_signal_receiver(self.pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface') self.add_signal_receiver(self.pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface')
self.add_signal_receiver(self.pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface') self.add_signal_receiver(self.pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface')
self._mail_password = getpass.getpass('Enter password for address %s: ' % (self.MAIL_ADDRESS))
self.mailWidget = GenericMonitorTextWidget('') self.mailWidget = GenericMonitorTextWidget('')
mailItem = GenericMonitorItem('mail', [self.mailWidget]) mailItem = GenericMonitorItem('mail', [self.mailWidget])
self.mailGroup = GenericMonitorGroup('Mail', [mailItem]) self.mailGroup = GenericMonitorGroup('Mail', [mailItem])