Skip to content

Commit

Permalink
Add server smtp module and switch auth
Browse files Browse the repository at this point in the history
  • Loading branch information
scotttrinh committed Nov 6, 2024
1 parent 67e8a06 commit 02628d1
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 110 deletions.
10 changes: 6 additions & 4 deletions edb/lib/cfg.edgeql
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ CREATE TYPE cfg::SMTPProviderConfig EXTENDING cfg::EmailProviderConfig {
CREATE ANNOTATION std::description :=
"Password for login after connected to SMTP server.";
};
CREATE REQUIRED PROPERTY security -> ext::auth::SMTPSecurity {
SET default := ext::auth::SMTPSecurity.STARTTLSOrPlainText;
CREATE REQUIRED PROPERTY security -> cfg::SMTPSecurity {
SET default := cfg::SMTPSecurity.STARTTLSOrPlainText;
CREATE ANNOTATION std::description :=
"Security mode of the connection to SMTP server. \
By default, initiate a STARTTLS upgrade if supported by the \
Expand Down Expand Up @@ -224,11 +224,13 @@ ALTER TYPE cfg::AbstractConfig {
};

CREATE MULTI LINK email_providers -> cfg::EmailProviderConfig {
CREATE ANNOTATION cfg::system := 'true';
CREATE ANNOTATION std::description :=
'The list of email providers that can be used to send emails.';
};

CREATE PROPERTY current_email_provider_name -> std::str {
CREATE ANNOTATION cfg::system := 'true';
CREATE ANNOTATION std::description :=
'The name of the current email provider.';
};

CREATE PROPERTY allow_dml_in_functions -> std::bool {
Expand Down
28 changes: 8 additions & 20 deletions edb/server/protocol/auth_ext/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import random

from typing import Any, Coroutine
from edb.server import tenant
from edb.server import tenant, smtp

from . import util, ui, smtp
from . import util, ui


async def send_password_reset_email(
Expand All @@ -15,7 +15,6 @@ async def send_password_reset_email(
reset_url: str,
test_mode: bool,
) -> None:
from_addr = util.get_config(db, "ext::auth::SMTPConfig::sender")
app_details_config = util.get_app_details_config(db)
if app_details_config is None:
email_args = {}
Expand All @@ -27,16 +26,13 @@ async def send_password_reset_email(
brand_color=app_details_config.brand_color,
)
msg = ui.render_password_reset_email(
from_addr=from_addr,
to_addr=to_addr,
reset_url=reset_url,
**email_args,
)
coro = smtp.send_email(
db,
smtp_provider = smtp.SMTP(db)
coro = smtp_provider.send(
msg,
sender=from_addr,
recipients=to_addr,
test_mode=test_mode,
)
await _protected_send(coro, tenant)
Expand All @@ -51,7 +47,6 @@ async def send_verification_email(
provider: str,
test_mode: bool,
) -> None:
from_addr = util.get_config(db, "ext::auth::SMTPConfig::sender")
app_details_config = util.get_app_details_config(db)
verification_token_params = urllib.parse.urlencode(
{
Expand All @@ -71,16 +66,13 @@ async def send_verification_email(
brand_color=app_details_config.brand_color,
)
msg = ui.render_verification_email(
from_addr=from_addr,
to_addr=to_addr,
verify_url=verify_url,
**email_args,
)
coro = smtp.send_email(
db,
smtp_provider = smtp.SMTP(db)
coro = smtp_provider.send(
msg,
sender=from_addr,
recipients=to_addr,
test_mode=test_mode,
)
await _protected_send(coro, tenant)
Expand All @@ -93,7 +85,6 @@ async def send_magic_link_email(
link: str,
test_mode: bool,
) -> None:
from_addr = util.get_config(db, "ext::auth::SMTPConfig::sender")
app_details_config = util.get_app_details_config(db)
if app_details_config is None:
email_args = {}
Expand All @@ -105,16 +96,13 @@ async def send_magic_link_email(
brand_color=app_details_config.brand_color,
)
msg = ui.render_magic_link_email(
from_addr=from_addr,
to_addr=to_addr,
link=link,
**email_args,
)
coro = smtp.send_email(
db,
smtp_provider = smtp.SMTP(db)
coro = smtp_provider.send(
msg,
sender=from_addr,
recipients=to_addr,
test_mode=test_mode,
)
await _protected_send(coro, tenant)
Expand Down
95 changes: 30 additions & 65 deletions edb/server/protocol/auth_ext/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
from typing import cast, Optional

import html

from email.mime import multipart
from email.mime import text as mime_text
import email.message

from edb.server.protocol.auth_ext import config as auth_config

Expand Down Expand Up @@ -701,35 +699,26 @@ def render_magic_link_sent_page(

def render_password_reset_email(
*,
from_addr: str,
to_addr: str,
reset_url: str,
app_name: Optional[str] = None,
logo_url: Optional[str] = None,
dark_logo_url: Optional[str] = None,
brand_color: Optional[str] = "#007bff",
) -> multipart.MIMEMultipart:
msg = multipart.MIMEMultipart()
msg["From"] = from_addr
) -> email.message.EmailMessage:
msg = email.message.EmailMessage()
msg["To"] = to_addr
msg["Subject"] = "Reset password"
alternative = multipart.MIMEMultipart('alternative')
plain_text_msg = mime_text.MIMEText(
f"""
plain_text_content = f"""
Somebody requested a new password for the {app_name or ''} account associated
with {to_addr}.
Please paste the following URL into your browser address bar to verify your
email address:
{reset_url}
""",
"plain",
"utf-8",
)
alternative.attach(plain_text_msg)

content = f"""
"""
html_content = f"""
<tr>
<td
style="
Expand Down Expand Up @@ -940,52 +929,42 @@ def render_password_reset_email(
</td>
</tr>
""" # noqa: E501
html_msg = mime_text.MIMEText(

msg.set_content(plain_text_content, subtype="plain")
msg.add_alternative(
render.base_default_email(
content=html_content,
app_name=app_name,
logo_url=logo_url,
content=content,
),
"html",
"utf-8",
subtype="html",
)
alternative.attach(html_msg)
msg.attach(alternative)
return msg


def render_verification_email(
*,
from_addr: str,
to_addr: str,
verify_url: str,
app_name: Optional[str] = None,
logo_url: Optional[str] = None,
dark_logo_url: Optional[str] = None,
brand_color: Optional[str] = "#007bff",
) -> multipart.MIMEMultipart:
msg = multipart.MIMEMultipart()
msg["From"] = from_addr
) -> email.message.EmailMessage:
msg = email.message.EmailMessage()
msg["To"] = to_addr
msg["Subject"] = (
f"Verify your email{f' for {app_name}' if app_name else ''}"
)
alternative = multipart.MIMEMultipart('alternative')
plain_text_msg = mime_text.MIMEText(
f"""
plain_text_content = f"""
Congratulations, you're registered{f' at {app_name}' if app_name else ''}!
Please paste the following URL into your browser address bar to verify your
email address:
{verify_url}
""",
"plain",
"utf-8",
)
alternative.attach(plain_text_msg)

content = f"""
"""
html_content = f"""
<tr>
<td
align="left"
Expand Down Expand Up @@ -1113,50 +1092,38 @@ def render_verification_email(
</div>
</td>
</tr>
"""

html_msg = mime_text.MIMEText(
"""
msg.set_content(plain_text_content, subtype="plain")
msg.set_content(
render.base_default_email(
content=html_content,
app_name=app_name,
logo_url=logo_url,
content=content,
),
"html",
"utf-8",
subtype="html",
)
alternative.attach(html_msg)
msg.attach(alternative)
return msg


def render_magic_link_email(
*,
from_addr: str,
to_addr: str,
link: str,
app_name: Optional[str] = None,
logo_url: Optional[str] = None,
dark_logo_url: Optional[str] = None,
brand_color: Optional[str] = "#007bff",
) -> multipart.MIMEMultipart:
msg = multipart.MIMEMultipart()
msg["From"] = from_addr
) -> email.message.EmailMessage:
msg = email.message.EmailMessage()
msg["To"] = to_addr
msg["Subject"] = "Sign in link"
alternative = multipart.MIMEMultipart('alternative')
plain_text_msg = mime_text.MIMEText(
f"""
plain_text_content = f"""
Please paste the following URL into your browser address bar to be signed into
your account:
{link}
""",
"plain",
"utf-8",
)
alternative.attach(plain_text_msg)
content = f"""
"""
html_content = f"""
<tr>
<td
align="left"
Expand Down Expand Up @@ -1249,15 +1216,13 @@ def render_magic_link_email(
</td>
</tr>
"""
html_msg = mime_text.MIMEText(
msg.set_content(plain_text_content, subtype="plain")
msg.set_content(
render.base_default_email(
content=html_content,
app_name=app_name,
logo_url=logo_url,
content=content,
),
"html",
"utf-8",
subtype="html",
)
alternative.attach(html_msg)
msg.attach(alternative)
return msg
Loading

0 comments on commit 02628d1

Please sign in to comment.