# -*- coding: utf-8 -*- # This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) # Copyright (C) 2021 OzzieIsaacs # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import os.path from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request from googleapiclient.discovery import build from google.oauth2.credentials import Credentials from datetime import datetime import base64 from flask_babel import gettext as _ from ..constants import CONFIG_DIR from .. import logger log = logger.create() SCOPES = ['openid', 'https://www.googleapis.com/auth/gmail.send', 'https://www.googleapis.com/auth/userinfo.email'] def setup_gmail(token): # If there are no (valid) credentials available, let the user log in. creds = None if "token" in token: creds = Credentials( token=token['token'], refresh_token=token['refresh_token'], token_uri=token['token_uri'], client_id=token['client_id'], client_secret=token['client_secret'], scopes=token['scopes'], ) creds.expiry = datetime.fromisoformat(token['expiry']) if not creds or not creds.valid: # don't forget to dump one more time after the refresh # also, some file-locking routines wouldn't be needless if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: cred_file = os.path.join(CONFIG_DIR, 'gmail.json') if not os.path.exists(cred_file): raise Exception(_("Found no valid gmail.json file with OAuth information")) flow = InstalledAppFlow.from_client_secrets_file( os.path.join(CONFIG_DIR, 'gmail.json'), SCOPES) creds = flow.run_local_server(port=0) user_info = get_user_info(creds) return { 'token': creds.token, 'refresh_token': creds.refresh_token, 'token_uri': creds.token_uri, 'client_id': creds.client_id, 'client_secret': creds.client_secret, 'scopes': creds.scopes, 'expiry': creds.expiry.isoformat(), 'email': user_info } return {} def get_user_info(credentials): user_info_service = build(serviceName='oauth2', version='v2',credentials=credentials) user_info = user_info_service.userinfo().get().execute() return user_info.get('email', "") def send_messsage(token, msg): log.debug("Start sending e-mail via Gmail") creds = Credentials( token=token['token'], refresh_token=token['refresh_token'], token_uri=token['token_uri'], client_id=token['client_id'], client_secret=token['client_secret'], scopes=token['scopes'], ) creds.expiry = datetime.fromisoformat(token['expiry']) if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) service = build('gmail', 'v1', credentials=creds) message_as_bytes = msg.as_bytes() # the message should converted from string to bytes. message_as_base64 = base64.urlsafe_b64encode(message_as_bytes) # encode in base64 (printable letters coding) raw = message_as_base64.decode() # convert to something JSON serializable body = {'raw': raw} (service.users().messages().send(userId='me', body=body).execute()) log.debug("E-mail send successfully via Gmail")