This commit is contained in:
Son NK 2020-08-28 12:27:51 +02:00
parent a3f3c252e3
commit 62ddaaf7b4
23 changed files with 127 additions and 56 deletions

View File

@ -23,8 +23,7 @@ from app.models import (
def try_auto_create(address: str) -> Optional[Alias]: def try_auto_create(address: str) -> Optional[Alias]:
"""Try to auto-create the alias using directory or catch-all domain """Try to auto-create the alias using directory or catch-all domain"""
"""
alias = try_auto_create_catch_all_domain(address) alias = try_auto_create_catch_all_domain(address)
if not alias: if not alias:
alias = try_auto_create_directory(address) alias = try_auto_create_directory(address)
@ -77,7 +76,8 @@ def try_auto_create_directory(address: str) -> Optional[Alias]:
db.session.flush() db.session.flush()
for i in range(1, len(mailboxes)): for i in range(1, len(mailboxes)):
AliasMailbox.create( AliasMailbox.create(
alias_id=alias.id, mailbox_id=mailboxes[i].id, alias_id=alias.id,
mailbox_id=mailboxes[i].id,
) )
db.session.commit() db.session.commit()
@ -127,7 +127,8 @@ def try_auto_create_catch_all_domain(address: str) -> Optional[Alias]:
db.session.flush() db.session.flush()
for i in range(1, len(mailboxes)): for i in range(1, len(mailboxes)):
AliasMailbox.create( AliasMailbox.create(
alias_id=alias.id, mailbox_id=mailboxes[i].id, alias_id=alias.id,
mailbox_id=mailboxes[i].id,
) )
db.session.commit() db.session.commit()
return alias return alias

View File

@ -195,7 +195,8 @@ def get_alias_infos_with_pagination_v3(
func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"), func.sum(case([(EmailLog.is_reply, 1)], else_=0)).label("nb_reply"),
func.sum( func.sum(
case( case(
[(and_(EmailLog.is_reply == False, EmailLog.blocked), 1)], else_=0, [(and_(EmailLog.is_reply == False, EmailLog.blocked), 1)],
else_=0,
) )
).label("nb_blocked"), ).label("nb_blocked"),
func.sum( func.sum(
@ -203,7 +204,8 @@ def get_alias_infos_with_pagination_v3(
[ [
( (
and_( and_(
EmailLog.is_reply == False, EmailLog.blocked == False, EmailLog.is_reply == False,
EmailLog.blocked == False,
), ),
1, 1,
) )

View File

@ -310,7 +310,8 @@ def verify_receipt(receipt_data, user, password) -> Optional[AppleSubscription]:
# try sandbox_url # try sandbox_url
LOG.warning("Use the sandbox url instead") LOG.warning("Use the sandbox url instead")
r = requests.post( r = requests.post(
_SANDBOX_URL, json={"receipt-data": receipt_data, "password": password}, _SANDBOX_URL,
json={"receipt-data": receipt_data, "password": password},
) )
data = r.json() data = r.json()
@ -466,7 +467,8 @@ def verify_receipt(receipt_data, user, password) -> Optional[AppleSubscription]:
if data["status"] != 0: if data["status"] != 0:
LOG.warning( LOG.warning(
"verifyReceipt status !=0, probably invalid receipt. User %s", user, "verifyReceipt status !=0, probably invalid receipt. User %s",
user,
) )
return None return None

View File

@ -288,7 +288,8 @@ def new_custom_alias_v3():
for i in range(1, len(mailboxes)): for i in range(1, len(mailboxes)):
AliasMailbox.create( AliasMailbox.create(
alias_id=alias.id, mailbox_id=mailboxes[i].id, alias_id=alias.id,
mailbox_id=mailboxes[i].id,
) )
db.session.commit() db.session.commit()

View File

@ -54,7 +54,9 @@ def register():
# 'hostname': '127.0.0.1'} # 'hostname': '127.0.0.1'}
if not hcaptcha_res["success"]: if not hcaptcha_res["success"]:
LOG.warning( LOG.warning(
"User put wrong captcha %s %s", form.email.data, hcaptcha_res, "User put wrong captcha %s %s",
form.email.data,
hcaptcha_res,
) )
flash("Wrong Captcha", "error") flash("Wrong Captcha", "error")
return render_template( return render_template(

View File

@ -87,7 +87,10 @@ def alias_contact_manager(alias_id):
except Exception: except Exception:
flash(f"{contact_addr} is invalid", "error") flash(f"{contact_addr} is invalid", "error")
return redirect( return redirect(
url_for("dashboard.alias_contact_manager", alias_id=alias_id,) url_for(
"dashboard.alias_contact_manager",
alias_id=alias_id,
)
) )
contact_email = contact_email.lower() contact_email = contact_email.lower()

View File

@ -143,7 +143,8 @@ def custom_alias():
for i in range(1, len(mailboxes)): for i in range(1, len(mailboxes)):
AliasMailbox.create( AliasMailbox.create(
alias_id=alias.id, mailbox_id=mailboxes[i].id, alias_id=alias.id,
mailbox_id=mailboxes[i].id,
) )
db.session.commit() db.session.commit()

View File

@ -111,7 +111,8 @@ def domain_detail_dns(custom_domain_id):
custom_domain.dmarc_verified = False custom_domain.dmarc_verified = False
db.session.commit() db.session.commit()
flash( flash(
f"DMARC: The TXT record is not correctly set", "warning", f"DMARC: The TXT record is not correctly set",
"warning",
) )
dmarc_ok = False dmarc_ok = False
dmarc_errors = txt_records dmarc_errors = txt_records
@ -207,7 +208,8 @@ def domain_detail_trash(custom_domain_id):
DomainDeletedAlias.delete(deleted_alias.id) DomainDeletedAlias.delete(deleted_alias.id)
db.session.commit() db.session.commit()
flash( flash(
f"{deleted_alias.email} can now be re-created", "success", f"{deleted_alias.email} can now be re-created",
"success",
) )
return redirect( return redirect(

View File

@ -102,7 +102,10 @@ def index():
flash("Unknown error, sorry for the inconvenience", "error") flash("Unknown error, sorry for the inconvenience", "error")
return redirect( return redirect(
url_for( url_for(
"dashboard.index", query=query, sort=sort, filter=alias_filter, "dashboard.index",
query=query,
sort=sort,
filter=alias_filter,
) )
) )

View File

@ -13,9 +13,13 @@ def refused_email_route():
if highlight_id: if highlight_id:
highlight_id = int(highlight_id) highlight_id = int(highlight_id)
email_logs: [EmailLog] = EmailLog.query.filter( email_logs: [EmailLog] = (
EmailLog.query.filter(
EmailLog.user_id == current_user.id, EmailLog.refused_email_id != None EmailLog.user_id == current_user.id, EmailLog.refused_email_id != None
).order_by(EmailLog.id.desc()).all() )
.order_by(EmailLog.id.desc())
.all()
)
# make sure the highlighted email_log is the first email_log # make sure the highlighted email_log is the first email_log
highlight_index = None highlight_index = None

View File

@ -396,8 +396,7 @@ def get_mx_domain_list(domain) -> [str]:
def personal_email_already_used(email: str) -> bool: def personal_email_already_used(email: str) -> bool:
"""test if an email can be used as user email """test if an email can be used as user email"""
"""
if User.get_by(email=email): if User.get_by(email=email):
return True return True

View File

@ -17,14 +17,19 @@ def greylisting_needed_for_alias(alias: Alias) -> bool:
nb_activity = ( nb_activity = (
db.session.query(EmailLog) db.session.query(EmailLog)
.join(Contact, EmailLog.contact_id == Contact.id) .join(Contact, EmailLog.contact_id == Contact.id)
.filter(Contact.alias_id == alias.id, EmailLog.created_at > min_time,) .filter(
Contact.alias_id == alias.id,
EmailLog.created_at > min_time,
)
.group_by(EmailLog.id) .group_by(EmailLog.id)
.count() .count()
) )
if nb_activity > MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS: if nb_activity > MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS:
LOG.d( LOG.d(
"Too much forward on alias %s. Nb Activity %s", alias, nb_activity, "Too much forward on alias %s. Nb Activity %s",
alias,
nb_activity,
) )
return True return True
@ -39,7 +44,10 @@ def greylisting_needed_for_mailbox(alias: Alias) -> bool:
db.session.query(EmailLog) db.session.query(EmailLog)
.join(Contact, EmailLog.contact_id == Contact.id) .join(Contact, EmailLog.contact_id == Contact.id)
.join(Alias, Contact.alias_id == Alias.id) .join(Alias, Contact.alias_id == Alias.id)
.filter(Alias.mailbox_id == alias.mailbox_id, EmailLog.created_at > min_time,) .filter(
Alias.mailbox_id == alias.mailbox_id,
EmailLog.created_at > min_time,
)
.group_by(EmailLog.id) .group_by(EmailLog.id)
.count() .count()
) )

View File

@ -608,7 +608,9 @@ class MfaBrowser(db.Model, ModelMixin):
found = True found = True
return MfaBrowser.create( return MfaBrowser.create(
user_id=user.id, token=token, expires=arrow.now().shift(days=30), user_id=user.id,
token=token,
expires=arrow.now().shift(days=30),
) )
@classmethod @classmethod

View File

@ -34,7 +34,9 @@ def upload_from_bytesio(key: str, bs: BytesIO, content_type="string"):
else: else:
_session.resource("s3").Bucket(BUCKET).put_object( _session.resource("s3").Bucket(BUCKET).put_object(
Key=key, Body=bs, ContentType=content_type, Key=key,
Body=bs,
ContentType=content_type,
) )

View File

@ -151,8 +151,7 @@ class Stats:
def stats_before(moment: Arrow) -> Stats: def stats_before(moment: Arrow) -> Stats:
"""return the stats before a specific moment, ignoring all stats come from users in IGNORED_EMAILS """return the stats before a specific moment, ignoring all stats come from users in IGNORED_EMAILS"""
"""
# nb user # nb user
q = User.query q = User.query
for ie in IGNORED_EMAILS: for ie in IGNORED_EMAILS:
@ -175,7 +174,9 @@ def stats_before(moment: Arrow) -> Stats:
q = ( q = (
db.session.query(EmailLog) db.session.query(EmailLog)
.join(User, EmailLog.user_id == User.id) .join(User, EmailLog.user_id == User.id)
.filter(EmailLog.created_at < moment,) .filter(
EmailLog.created_at < moment,
)
) )
for ie in IGNORED_EMAILS: for ie in IGNORED_EMAILS:
q = q.filter(~User.email.contains(ie)) q = q.filter(~User.email.contains(ie))

View File

@ -156,13 +156,18 @@ def get_or_create_contact(
if contact: if contact:
if contact.name != contact_name: if contact.name != contact_name:
LOG.d( LOG.d(
"Update contact %s name %s to %s", contact, contact.name, contact_name, "Update contact %s name %s to %s",
contact,
contact.name,
contact_name,
) )
contact.name = contact_name contact.name = contact_name
db.session.commit() db.session.commit()
else: else:
LOG.debug( LOG.debug(
"create contact for alias %s and contact %s", alias, contact_from_header, "create contact for alias %s and contact %s",
alias,
contact_from_header,
) )
reply_email = generate_reply_email() reply_email = generate_reply_email()
@ -346,7 +351,8 @@ def prepare_pgp_message(orig_msg: Message, pgp_fingerprint: str):
# Delete unnecessary headers in orig_msg except to save space # Delete unnecessary headers in orig_msg except to save space
delete_all_headers_except( delete_all_headers_except(
orig_msg, _MIME_HEADERS, orig_msg,
_MIME_HEADERS,
) )
first = MIMEApplication( first = MIMEApplication(
@ -590,7 +596,10 @@ async def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (boo
# the "reply email" # the "reply email"
if mail_from == "<>": if mail_from == "<>":
LOG.warning( LOG.warning(
"Bounce when sending to alias %s from %s, user %s", alias, contact, user, "Bounce when sending to alias %s from %s, user %s",
alias,
contact,
user,
) )
handle_bounce(contact, alias, msg, user) handle_bounce(contact, alias, msg, user)
@ -1326,7 +1335,9 @@ class MailHandler:
return ret return ret
except Exception: except Exception:
LOG.exception( LOG.exception(
"email handling fail %s -> %s", envelope.mail_from, envelope.rcpt_tos, "email handling fail %s -> %s",
envelope.mail_from,
envelope.rcpt_tos,
) )
return "421 SL Retry later" return "421 SL Retry later"

View File

@ -75,8 +75,7 @@ def callback():
@app.route("/profile", methods=["GET"]) @app.route("/profile", methods=["GET"])
def profile(): def profile():
"""Fetching a protected resource using an OAuth 2 token. """Fetching a protected resource using an OAuth 2 token."""
"""
simplelogin = OAuth2Session(client_id, token=session["oauth_token"]) simplelogin = OAuth2Session(client_id, token=session["oauth_token"])
return jsonify(simplelogin.get(userinfo_url).json()) return jsonify(simplelogin.get(userinfo_url).json())

View File

@ -74,7 +74,11 @@ from app.oauth.base import oauth_bp
if SENTRY_DSN: if SENTRY_DSN:
LOG.d("enable sentry") LOG.d("enable sentry")
sentry_sdk.init( sentry_sdk.init(
dsn=SENTRY_DSN, integrations=[FlaskIntegration(), SqlalchemyIntegration(),], dsn=SENTRY_DSN,
integrations=[
FlaskIntegration(),
SqlalchemyIntegration(),
],
) )
# the app is served behin nginx which uses http and not https # the app is served behin nginx which uses http and not https

View File

@ -243,14 +243,16 @@ def test_auth_login_forgot_password(flask_client):
db.session.commit() db.session.commit()
r = flask_client.post( r = flask_client.post(
url_for("api.forgot_password"), json={"email": "abcd@gmail.com"}, url_for("api.forgot_password"),
json={"email": "abcd@gmail.com"},
) )
assert r.status_code == 200 assert r.status_code == 200
# No such email, still return 200 # No such email, still return 200
r = flask_client.post( r = flask_client.post(
url_for("api.forgot_password"), json={"email": "not-exist@b.c"}, url_for("api.forgot_password"),
json={"email": "not-exist@b.c"},
) )
assert r.status_code == 200 assert r.status_code == 200

View File

@ -177,7 +177,8 @@ def test_get_mailboxes(flask_client):
db.session.commit() db.session.commit()
r = flask_client.get( r = flask_client.get(
url_for("api.get_mailboxes"), headers={"Authentication": api_key.code}, url_for("api.get_mailboxes"),
headers={"Authentication": api_key.code},
) )
assert r.status_code == 200 assert r.status_code == 200
# m2@example.com is not returned as it's not verified # m2@example.com is not returned as it's not verified

View File

@ -120,7 +120,11 @@ def test_success_v2(flask_client):
r = flask_client.post( r = flask_client.post(
url_for("api.new_custom_alias_v2", hostname="www.test.com"), url_for("api.new_custom_alias_v2", hostname="www.test.com"),
headers={"Authentication": api_key.code}, headers={"Authentication": api_key.code},
json={"alias_prefix": "prefix", "signed_suffix": suffix, "note": "test note",}, json={
"alias_prefix": "prefix",
"signed_suffix": suffix,
"note": "test note",
},
) )
assert r.status_code == 201 assert r.status_code == 201
@ -163,7 +167,11 @@ def test_cannot_create_alias_in_trash(flask_client):
r = flask_client.post( r = flask_client.post(
url_for("api.new_custom_alias_v2", hostname="www.test.com"), url_for("api.new_custom_alias_v2", hostname="www.test.com"),
headers={"Authentication": api_key.code}, headers={"Authentication": api_key.code},
json={"alias_prefix": "prefix", "signed_suffix": suffix, "note": "test note",}, json={
"alias_prefix": "prefix",
"signed_suffix": suffix,
"note": "test note",
},
) )
# assert alias creation is successful # assert alias creation is successful
@ -179,14 +187,21 @@ def test_cannot_create_alias_in_trash(flask_client):
r = flask_client.post( r = flask_client.post(
url_for("api.new_custom_alias_v2", hostname="www.test.com"), url_for("api.new_custom_alias_v2", hostname="www.test.com"),
headers={"Authentication": api_key.code}, headers={"Authentication": api_key.code},
json={"alias_prefix": "prefix", "signed_suffix": suffix, "note": "test note",}, json={
"alias_prefix": "prefix",
"signed_suffix": suffix,
"note": "test note",
},
) )
assert r.status_code == 409 assert r.status_code == 409
def test_success_v3(flask_client): def test_success_v3(flask_client):
user = User.create( user = User.create(
email="a@b.c", password="password", name="Test User", activated=True, email="a@b.c",
password="password",
name="Test User",
activated=True,
) )
db.session.commit() db.session.commit()

View File

@ -69,6 +69,9 @@ def test_logout(flask_client):
) )
# logout # logout
r = flask_client.get(url_for("auth.logout"), follow_redirects=True,) r = flask_client.get(
url_for("auth.logout"),
follow_redirects=True,
)
assert r.status_code == 200 assert r.status_code == 200

View File

@ -82,7 +82,10 @@ def test_add_or_replace_header():
def test_parseaddr_unicode(): def test_parseaddr_unicode():
# only email # only email
assert parseaddr_unicode("abcd@gmail.com") == ("", "abcd@gmail.com",) assert parseaddr_unicode("abcd@gmail.com") == (
"",
"abcd@gmail.com",
)
# ascii address # ascii address
assert parseaddr_unicode("First Last <abcd@gmail.com>") == ( assert parseaddr_unicode("First Last <abcd@gmail.com>") == (