Implementation for gmail server with OAuth2 started
This commit is contained in:
parent
0ceb12f74f
commit
8f91437701
18
cps/admin.py
18
cps/admin.py
|
@ -39,7 +39,7 @@ from sqlalchemy.orm.attributes import flag_modified
|
||||||
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
|
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
|
||||||
from sqlalchemy.sql.expression import func, or_
|
from sqlalchemy.sql.expression import func, or_
|
||||||
|
|
||||||
from . import constants, logger, helper, services
|
from . import constants, logger, helper, services, gmail
|
||||||
from .cli import filepicker
|
from .cli import filepicker
|
||||||
from . import db, calibre_db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils
|
from . import db, calibre_db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils
|
||||||
from .helper import check_valid_domain, send_test_mail, reset_password, generate_password_hash
|
from .helper import check_valid_domain, send_test_mail, reset_password, generate_password_hash
|
||||||
|
@ -1319,7 +1319,17 @@ def edit_mailsettings():
|
||||||
@admin_required
|
@admin_required
|
||||||
def update_mailsettings():
|
def update_mailsettings():
|
||||||
to_save = request.form.to_dict()
|
to_save = request.form.to_dict()
|
||||||
|
_config_int(to_save, "mail_server_type")
|
||||||
|
if to_save.get("invalidate_server"):
|
||||||
|
config.mail_gmail_token = {}
|
||||||
|
try:
|
||||||
|
flag_modified(config, "mail_gmail_token")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
elif to_save.get("gmail"):
|
||||||
|
config.mail_gmail_token = gmail.setup_gmail(config)
|
||||||
|
flash(_(u"G-Mail Account Verification Successfull"), category="success")
|
||||||
|
else:
|
||||||
_config_string(to_save, "mail_server")
|
_config_string(to_save, "mail_server")
|
||||||
_config_int(to_save, "mail_port")
|
_config_int(to_save, "mail_port")
|
||||||
_config_int(to_save, "mail_use_ssl")
|
_config_int(to_save, "mail_use_ssl")
|
||||||
|
@ -1338,8 +1348,8 @@ def update_mailsettings():
|
||||||
if current_user.email:
|
if current_user.email:
|
||||||
result = send_test_mail(current_user.email, current_user.name)
|
result = send_test_mail(current_user.email, current_user.name)
|
||||||
if result is None:
|
if result is None:
|
||||||
flash(_(u"Test e-mail queued for sending to %(email)s, please check Tasks for result", email=current_user.email),
|
flash(_(u"Test e-mail queued for sending to %(email)s, please check Tasks for result",
|
||||||
category="info")
|
email=current_user.email), category="info")
|
||||||
else:
|
else:
|
||||||
flash(_(u"There was an error sending the Test e-mail: %(res)s", res=result), category="error")
|
flash(_(u"There was an error sending the Test e-mail: %(res)s", res=result), category="error")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -39,7 +39,7 @@ class _Flask_Settings(_Base):
|
||||||
__tablename__ = 'flask_settings'
|
__tablename__ = 'flask_settings'
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
flask_session_key = Column(BLOB, default="")
|
flask_session_key = Column(BLOB, default=b"")
|
||||||
|
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
self.flask_session_key = key
|
self.flask_session_key = key
|
||||||
|
@ -58,6 +58,8 @@ class _Settings(_Base):
|
||||||
mail_password = Column(String, default='mypassword')
|
mail_password = Column(String, default='mypassword')
|
||||||
mail_from = Column(String, default='automailer <mail@example.com>')
|
mail_from = Column(String, default='automailer <mail@example.com>')
|
||||||
mail_size = Column(Integer, default=25*1024*1024)
|
mail_size = Column(Integer, default=25*1024*1024)
|
||||||
|
mail_server_type = Column(SmallInteger, default=0)
|
||||||
|
mail_gmail_token = Column(JSON, default={})
|
||||||
|
|
||||||
config_calibre_dir = Column(String)
|
config_calibre_dir = Column(String)
|
||||||
config_port = Column(Integer, default=constants.DEFAULT_PORT)
|
config_port = Column(Integer, default=constants.DEFAULT_PORT)
|
||||||
|
@ -246,7 +248,8 @@ class _ConfigSQL(object):
|
||||||
return {k:v for k, v in self.__dict__.items() if k.startswith('mail_')}
|
return {k:v for k, v in self.__dict__.items() if k.startswith('mail_')}
|
||||||
|
|
||||||
def get_mail_server_configured(self):
|
def get_mail_server_configured(self):
|
||||||
return not bool(self.mail_server == constants.DEFAULT_MAIL_SERVER)
|
return bool((self.mail_server != constants.DEFAULT_MAIL_SERVER and self.mail_server_type == 0)
|
||||||
|
or (self.mail_gmail_token != b"" and self.mail_server_type == 1))
|
||||||
|
|
||||||
|
|
||||||
def set_from_dictionary(self, dictionary, field, convertor=None, default=None, encode=None):
|
def set_from_dictionary(self, dictionary, field, convertor=None, default=None, encode=None):
|
||||||
|
@ -364,10 +367,14 @@ def _migrate_table(session, orm_class):
|
||||||
if isinstance(column.default.arg, bool):
|
if isinstance(column.default.arg, bool):
|
||||||
column_default = ("DEFAULT %r" % int(column.default.arg))
|
column_default = ("DEFAULT %r" % int(column.default.arg))
|
||||||
else:
|
else:
|
||||||
column_default = ("DEFAULT %r" % column.default.arg)
|
column_default = ("DEFAULT '%r'" % column.default.arg)
|
||||||
|
if isinstance(column.type, JSON):
|
||||||
|
column_type = "JSON"
|
||||||
|
else:
|
||||||
|
column_type = column.type
|
||||||
alter_table = "ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__,
|
alter_table = "ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__,
|
||||||
column_name,
|
column_name,
|
||||||
column.type,
|
column_type,
|
||||||
column_default)
|
column_default)
|
||||||
log.debug(alter_table)
|
log.debug(alter_table)
|
||||||
session.execute(alter_table)
|
session.execute(alter_table)
|
||||||
|
|
64
cps/gmail.py
Normal file
64
cps/gmail.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
from __future__ import print_function
|
||||||
|
import os.path
|
||||||
|
from googleapiclient.discovery import build
|
||||||
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
|
from google.auth.transport.requests import Request
|
||||||
|
from google.oauth2.credentials import Credentials
|
||||||
|
from .constants import BASE_DIR
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
subject = "Test"
|
||||||
|
msg = "Testnachricht"
|
||||||
|
sender = "matthias1.knopp@googlemail.com"
|
||||||
|
receiver = "matthias.knopp@web.de"
|
||||||
|
|
||||||
|
SCOPES = ['https://www.googleapis.com/auth/gmail.send']
|
||||||
|
|
||||||
|
def setup_gmail(config):
|
||||||
|
token = config.mail_gmail_token
|
||||||
|
# if config.mail_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:
|
||||||
|
flow = InstalledAppFlow.from_client_secrets_file(
|
||||||
|
os.path.join(BASE_DIR, 'gmail.json'), SCOPES)
|
||||||
|
creds = flow.run_local_server(port=0)
|
||||||
|
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
|
||||||
|
# implement your storage logic here, e.g. just good old json.dump() / json.load()
|
||||||
|
|
||||||
|
# service = build('gmail', 'v1', credentials=creds)
|
||||||
|
# message = MIMEText(msg)
|
||||||
|
# message['to'] = receiver
|
||||||
|
# message['from'] = sender
|
||||||
|
# message['subject'] = subject
|
||||||
|
# raw = base64.urlsafe_b64encode(message.as_bytes())
|
||||||
|
# raw = raw.decode()
|
||||||
|
# body = {'raw' : raw}
|
||||||
|
# message = (service.users().messages().send(userId='me', body=body).execute())
|
|
@ -7,6 +7,23 @@
|
||||||
<div class="discover">
|
<div class="discover">
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<form role="form" class="col-md-10 col-lg-6" method="POST">
|
<form role="form" class="col-md-10 col-lg-6" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="mail_server_type">{{_('Choose Server Type')}}</label>
|
||||||
|
<select name="mail_server_type" id="config_email_type" class="form-control" data-control="email-settings">
|
||||||
|
<option value="0" {% if content.mail_server_type == 0 %}selected{% endif %}>{{_('Use Standard E-Mail Account')}}</option>
|
||||||
|
<option value="1" {% if content.mail_server_type == 1 %}selected{% endif %}>{{_('G-Mail Account with OAuth2 Verfification')}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div data-related="email-settings-1">
|
||||||
|
<div class="form-group">
|
||||||
|
{% if content.mail_gmail_token == {} %}
|
||||||
|
<button type="submit" id="gmail_server" name="gmail" value="submit" class="btn btn-default">{{_('Setup Gmail Account as E-Mail Server')}}</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" id="invalidate_server" name="invalidate" value="submit" class="btn btn-danger">{{_('Revoke G-Mail Access')}}</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-related="email-settings-0">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="mail_server">{{_('SMTP Hostname')}}</label>
|
<label for="mail_server">{{_('SMTP Hostname')}}</label>
|
||||||
<input type="text" class="form-control" name="mail_server" id="mail_server" value="{{content.mail_server}}">
|
<input type="text" class="form-control" name="mail_server" id="mail_server" value="{{content.mail_server}}">
|
||||||
|
@ -44,6 +61,7 @@
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" name="submit" value="submit" class="btn btn-default">{{_('Save')}}</button>
|
<button type="submit" name="submit" value="submit" class="btn btn-default">{{_('Save')}}</button>
|
||||||
<button type="submit" name="test" value="test" class="btn btn-default">{{_('Save and Send Test E-mail')}}</button>
|
<button type="submit" name="test" value="test" class="btn btn-default">{{_('Save and Send Test E-mail')}}</button>
|
||||||
|
</div>
|
||||||
<a href="{{ url_for('admin.admin') }}" id="back" class="btn btn-default">{{_('Cancel')}}</a>
|
<a href="{{ url_for('admin.admin') }}" id="back" class="btn btn-default">{{_('Cancel')}}</a>
|
||||||
</form>
|
</form>
|
||||||
{% if g.allow_registration %}
|
{% if g.allow_registration %}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# GDrive Integration
|
# GDrive Integration
|
||||||
google-api-python-client>=1.7.11,<1.13.0
|
google-api-python-client>=1.7.11,<2.1.0
|
||||||
gevent>20.6.0,<21.2.0
|
gevent>20.6.0,<21.2.0
|
||||||
greenlet>=0.4.17,<1.1.0
|
greenlet>=0.4.17,<1.1.0
|
||||||
httplib2>=0.9.2,<0.18.0
|
httplib2>=0.9.2,<0.18.0
|
||||||
oauth2client>=4.0.0,<4.1.4
|
# oauth2client>=4.0.0,<4.1.4
|
||||||
uritemplate>=3.0.0,<3.1.0
|
uritemplate>=3.0.0,<3.1.0
|
||||||
pyasn1-modules>=0.0.8,<0.3.0
|
pyasn1-modules>=0.0.8,<0.3.0
|
||||||
pyasn1>=0.1.9,<0.5.0
|
pyasn1>=0.1.9,<0.5.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user