diff --git a/lnbits/extensions/smtp/README.md b/lnbits/extensions/smtp/README.md
new file mode 100644
index 00000000..5b7757e2
--- /dev/null
+++ b/lnbits/extensions/smtp/README.md
@@ -0,0 +1,14 @@
+
SMTP Extension
+
+This extension allows you to setup a smtp, to offer sending emails with it for a small fee.
+
+## Requirements
+
+- SMTP Server
+
+## Usage
+
+1. Create new emailaddress
+2. Verify if email goes to your testemail. Testmail is sent on create and update
+3. Share the link with the email form.
+
diff --git a/lnbits/extensions/smtp/__init__.py b/lnbits/extensions/smtp/__init__.py
new file mode 100644
index 00000000..e7419852
--- /dev/null
+++ b/lnbits/extensions/smtp/__init__.py
@@ -0,0 +1,34 @@
+import asyncio
+
+from fastapi import APIRouter
+from fastapi.staticfiles import StaticFiles
+
+from lnbits.db import Database
+from lnbits.helpers import template_renderer
+from lnbits.tasks import catch_everything_and_restart
+
+db = Database("ext_smtp")
+
+smtp_static_files = [
+ {
+ "path": "/smtp/static",
+ "app": StaticFiles(directory="lnbits/extensions/smtp/static"),
+ "name": "smtp_static",
+ }
+]
+
+smtp_ext: APIRouter = APIRouter(prefix="/smtp", tags=["smtp"])
+
+
+def smtp_renderer():
+ return template_renderer(["lnbits/extensions/smtp/templates"])
+
+
+from .tasks import wait_for_paid_invoices
+from .views import * # noqa
+from .views_api import * # noqa
+
+
+def smtp_start():
+ loop = asyncio.get_event_loop()
+ loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
diff --git a/lnbits/extensions/smtp/config.json b/lnbits/extensions/smtp/config.json
new file mode 100644
index 00000000..325ebfa7
--- /dev/null
+++ b/lnbits/extensions/smtp/config.json
@@ -0,0 +1,6 @@
+{
+ "name": "SMTP",
+ "short_description": "Charge sats for sending emails",
+ "tile": "/smtp/static/smtp-bitcoin-email.png",
+ "contributors": ["dni"]
+}
diff --git a/lnbits/extensions/smtp/crud.py b/lnbits/extensions/smtp/crud.py
new file mode 100644
index 00000000..2eee4c3d
--- /dev/null
+++ b/lnbits/extensions/smtp/crud.py
@@ -0,0 +1,168 @@
+from http import HTTPStatus
+from typing import List, Optional, Union
+
+from lnbits.helpers import urlsafe_short_hash
+
+from . import db
+from .models import CreateEmail, CreateEmailaddress, Emailaddresses, Emails
+from .smtp import send_mail
+
+
+def get_test_mail(email, testemail):
+ return CreateEmail(
+ emailaddress_id=email,
+ subject="LNBits SMTP - Test Email",
+ message="This is a test email from the LNBits SMTP extension! email is working!",
+ receiver=testemail,
+ )
+
+
+async def create_emailaddress(data: CreateEmailaddress) -> Emailaddresses:
+
+ emailaddress_id = urlsafe_short_hash()
+
+ # send test mail for checking connection
+ email = get_test_mail(data.email, data.testemail)
+ await send_mail(data, email)
+
+ await db.execute(
+ """
+ INSERT INTO smtp.emailaddress (id, wallet, email, testemail, smtp_server, smtp_user, smtp_password, smtp_port, anonymize, description, cost)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ emailaddress_id,
+ data.wallet,
+ data.email,
+ data.testemail,
+ data.smtp_server,
+ data.smtp_user,
+ data.smtp_password,
+ data.smtp_port,
+ data.anonymize,
+ data.description,
+ data.cost,
+ ),
+ )
+
+ new_emailaddress = await get_emailaddress(emailaddress_id)
+ assert new_emailaddress, "Newly created emailaddress couldn't be retrieved"
+ return new_emailaddress
+
+
+async def update_emailaddress(emailaddress_id: str, **kwargs) -> Emailaddresses:
+ q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+ await db.execute(
+ f"UPDATE smtp.emailaddress SET {q} WHERE id = ?",
+ (*kwargs.values(), emailaddress_id),
+ )
+ row = await db.fetchone(
+ "SELECT * FROM smtp.emailaddress WHERE id = ?", (emailaddress_id,)
+ )
+
+ # send test mail for checking connection
+ email = get_test_mail(row.email, row.testemail)
+ await send_mail(row, email)
+
+ assert row, "Newly updated emailaddress couldn't be retrieved"
+ return Emailaddresses(**row)
+
+
+async def get_emailaddress(emailaddress_id: str) -> Optional[Emailaddresses]:
+ row = await db.fetchone(
+ "SELECT * FROM smtp.emailaddress WHERE id = ?", (emailaddress_id,)
+ )
+ return Emailaddresses(**row) if row else None
+
+
+async def get_emailaddress_by_email(email: str) -> Optional[Emailaddresses]:
+ row = await db.fetchone("SELECT * FROM smtp.emailaddress WHERE email = ?", (email,))
+ return Emailaddresses(**row) if row else None
+
+
+# async def get_emailAddressByEmail(email: str) -> Optional[Emails]:
+# row = await db.fetchone(
+# "SELECT s.*, d.emailaddress as emailaddress FROM smtp.email s INNER JOIN smtp.emailaddress d ON (s.emailaddress_id = d.id) WHERE s.emailaddress = ?",
+# (email,),
+# )
+# return Subdomains(**row) if row else None
+
+
+async def get_emailaddresses(wallet_ids: Union[str, List[str]]) -> List[Emailaddresses]:
+ if isinstance(wallet_ids, str):
+ wallet_ids = [wallet_ids]
+
+ q = ",".join(["?"] * len(wallet_ids))
+ rows = await db.fetchall(
+ f"SELECT * FROM smtp.emailaddress WHERE wallet IN ({q})", (*wallet_ids,)
+ )
+
+ return [Emailaddresses(**row) for row in rows]
+
+
+async def delete_emailaddress(emailaddress_id: str) -> None:
+ await db.execute("DELETE FROM smtp.emailaddress WHERE id = ?", (emailaddress_id,))
+
+
+## create emails
+async def create_email(payment_hash, wallet, data: CreateEmail) -> Emails:
+ await db.execute(
+ """
+ INSERT INTO smtp.email (id, wallet, emailaddress_id, subject, receiver, message, paid)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ payment_hash,
+ wallet,
+ data.emailaddress_id,
+ data.subject,
+ data.receiver,
+ data.message,
+ False,
+ ),
+ )
+
+ new_email = await get_email(payment_hash)
+ assert new_email, "Newly created email couldn't be retrieved"
+ return new_email
+
+
+async def set_email_paid(payment_hash: str) -> Emails:
+ email = await get_email(payment_hash)
+ if email and email.paid == False:
+ await db.execute(
+ """
+ UPDATE smtp.email
+ SET paid = true
+ WHERE id = ?
+ """,
+ (payment_hash,),
+ )
+ new_email = await get_email(payment_hash)
+ assert new_email, "Newly paid email couldn't be retrieved"
+ return new_email
+
+
+async def get_email(email_id: str) -> Optional[Emails]:
+ row = await db.fetchone(
+ "SELECT s.*, d.email as emailaddress FROM smtp.email s INNER JOIN smtp.emailaddress d ON (s.emailaddress_id = d.id) WHERE s.id = ?",
+ (email_id,),
+ )
+ return Emails(**row) if row else None
+
+
+async def get_emails(wallet_ids: Union[str, List[str]]) -> List[Emails]:
+ if isinstance(wallet_ids, str):
+ wallet_ids = [wallet_ids]
+
+ q = ",".join(["?"] * len(wallet_ids))
+ rows = await db.fetchall(
+ f"SELECT s.*, d.email as emailaddress FROM smtp.email s INNER JOIN smtp.emailaddress d ON (s.emailaddress_id = d.id) WHERE s.wallet IN ({q})",
+ (*wallet_ids,),
+ )
+
+ return [Emails(**row) for row in rows]
+
+
+async def delete_email(email_id: str) -> None:
+ await db.execute("DELETE FROM smtp.email WHERE id = ?", (email_id,))
diff --git a/lnbits/extensions/smtp/migrations.py b/lnbits/extensions/smtp/migrations.py
new file mode 100644
index 00000000..16d50166
--- /dev/null
+++ b/lnbits/extensions/smtp/migrations.py
@@ -0,0 +1,35 @@
+async def m001_initial(db):
+
+ await db.execute(
+ f"""
+ CREATE TABLE smtp.emailaddress (
+ id TEXT PRIMARY KEY,
+ wallet TEXT NOT NULL,
+ email TEXT NOT NULL,
+ testemail TEXT NOT NULL,
+ smtp_server TEXT NOT NULL,
+ smtp_user TEXT NOT NULL,
+ smtp_password TEXT NOT NULL,
+ smtp_port TEXT NOT NULL,
+ anonymize BOOLEAN NOT NULL,
+ description TEXT NOT NULL,
+ cost INTEGER NOT NULL,
+ time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
+ );
+ """
+ )
+
+ await db.execute(
+ f"""
+ CREATE TABLE smtp.email (
+ id TEXT PRIMARY KEY,
+ wallet TEXT NOT NULL,
+ emailaddress_id TEXT NOT NULL,
+ subject TEXT NOT NULL,
+ receiver TEXT NOT NULL,
+ message TEXT NOT NULL,
+ paid BOOLEAN NOT NULL,
+ time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
+ );
+ """
+ )
diff --git a/lnbits/extensions/smtp/models.py b/lnbits/extensions/smtp/models.py
new file mode 100644
index 00000000..e2f3fc13
--- /dev/null
+++ b/lnbits/extensions/smtp/models.py
@@ -0,0 +1,47 @@
+from fastapi import Query
+from pydantic import BaseModel
+
+
+class CreateEmailaddress(BaseModel):
+ wallet: str = Query(...)
+ email: str = Query(...)
+ testemail: str = Query(...)
+ smtp_server: str = Query(...)
+ smtp_user: str = Query(...)
+ smtp_password: str = Query(...)
+ smtp_port: str = Query(...)
+ description: str = Query(...)
+ anonymize: bool
+ cost: int = Query(..., ge=0)
+
+
+class Emailaddresses(BaseModel):
+ id: str
+ wallet: str
+ email: str
+ testemail: str
+ smtp_server: str
+ smtp_user: str
+ smtp_password: str
+ smtp_port: str
+ anonymize: bool
+ description: str
+ cost: int
+
+
+class CreateEmail(BaseModel):
+ emailaddress_id: str = Query(...)
+ subject: str = Query(...)
+ receiver: str = Query(...)
+ message: str = Query(...)
+
+
+class Emails(BaseModel):
+ id: str
+ wallet: str
+ emailaddress_id: str
+ subject: str
+ receiver: str
+ message: str
+ paid: bool
+ time: int
diff --git a/lnbits/extensions/smtp/smtp.py b/lnbits/extensions/smtp/smtp.py
new file mode 100644
index 00000000..e77bc0fa
--- /dev/null
+++ b/lnbits/extensions/smtp/smtp.py
@@ -0,0 +1,86 @@
+import re
+import socket
+import time
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
+from email.utils import formatdate
+from http import HTTPStatus
+from smtplib import SMTP_SSL as SMTP
+
+from loguru import logger
+from starlette.exceptions import HTTPException
+
+
+def valid_email(s):
+ # https://regexr.com/2rhq7
+ pat = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
+ if re.match(pat, s):
+ return True
+ msg = f"SMTP - invalid email: {s}."
+ logger.error(msg)
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=msg)
+
+
+async def send_mail(emailaddress, email):
+ valid_email(emailaddress.email)
+ valid_email(email.receiver)
+
+ ts = time.time()
+ date = formatdate(ts, True)
+
+ msg = MIMEMultipart("alternative")
+ msg = MIMEMultipart("alternative")
+ msg["Date"] = date
+ msg["Subject"] = email.subject
+ msg["From"] = emailaddress.email
+ msg["To"] = email.receiver
+
+ signature = "Email sent anonymiously by LNbits Sendmail extension."
+ text = f"""
+{email.message}
+
+{signature}
+"""
+
+ html = f"""
+
+
+
+ {email.message}
+
+
{signature}
+
+
+"""
+
+ part1 = MIMEText(text, "plain")
+ part2 = MIMEText(html, "html")
+ msg.attach(part1)
+ msg.attach(part2)
+
+ try:
+ conn = SMTP(
+ host=emailaddress.smtp_server, port=emailaddress.smtp_port, timeout=10
+ )
+ logger.debug("SMTP - connected to smtp server.")
+ # conn.set_debuglevel(True)
+ except:
+ msg = f"SMTP - error connecting to smtp server: {emailaddress.smtp_server}:{emailaddress.smtp_port}."
+ logger.error(msg)
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=msg)
+ try:
+ conn.login(emailaddress.smtp_user, emailaddress.smtp_password)
+ logger.debug("SMTP - successful login to smtp server.")
+ except:
+ msg = f"SMTP - error login into smtp {emailaddress.smtp_user}."
+ logger.error(msg)
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=msg)
+ try:
+ conn.sendmail(emailaddress.email, email.receiver, msg.as_string())
+ logger.debug("SMTP - successfully send email.")
+ except socket.error as e:
+ msg = f"SMTP - error sending email: {str(e)}."
+ logger.error(msg)
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=msg)
+ finally:
+ conn.quit()
diff --git a/lnbits/extensions/smtp/static/smtp-bitcoin-email.png b/lnbits/extensions/smtp/static/smtp-bitcoin-email.png
new file mode 100644
index 00000000..e80b6c9a
Binary files /dev/null and b/lnbits/extensions/smtp/static/smtp-bitcoin-email.png differ
diff --git a/lnbits/extensions/smtp/tasks.py b/lnbits/extensions/smtp/tasks.py
new file mode 100644
index 00000000..9c544473
--- /dev/null
+++ b/lnbits/extensions/smtp/tasks.py
@@ -0,0 +1,36 @@
+import asyncio
+
+from loguru import logger
+
+from lnbits.core.models import Payment
+from lnbits.tasks import register_invoice_listener
+
+from .crud import get_email, get_emailaddress, set_email_paid
+from .smtp import send_mail
+
+
+async def wait_for_paid_invoices():
+ invoice_queue = asyncio.Queue()
+ register_invoice_listener(invoice_queue)
+ while True:
+ payment = await invoice_queue.get()
+ await on_invoice_paid(payment)
+
+
+async def on_invoice_paid(payment: Payment) -> None:
+ if payment.extra.get("tag") != "smtp":
+ return
+
+ email = await get_email(payment.checking_id)
+ if not email:
+ logger.error("SMTP: email can not by fetched")
+ return
+
+ emailaddress = await get_emailaddress(email.emailaddress_id)
+ if not emailaddress:
+ logger.error("SMTP: emailaddress can not by fetched")
+ return
+
+ await payment.set_pending(False)
+ await send_mail(emailaddress, email)
+ await set_email_paid(payment_hash=payment.payment_hash)
diff --git a/lnbits/extensions/smtp/templates/smtp/_api_docs.html b/lnbits/extensions/smtp/templates/smtp/_api_docs.html
new file mode 100644
index 00000000..cfb811d1
--- /dev/null
+++ b/lnbits/extensions/smtp/templates/smtp/_api_docs.html
@@ -0,0 +1,23 @@
+
+
+
+
+ LNBits SMTP: Get paid sats to send emails
+
+
+ Charge people for using sending an email via your smtp server
+ More details
+
+ Created by, dni
+
+
+
+
diff --git a/lnbits/extensions/smtp/templates/smtp/display.html b/lnbits/extensions/smtp/templates/smtp/display.html
new file mode 100644
index 00000000..7db4a0d6
--- /dev/null
+++ b/lnbits/extensions/smtp/templates/smtp/display.html
@@ -0,0 +1,185 @@
+{% extends "public.html" %} {% block page %}
+
+
+
+
+ {{ email }}
+
+ {{ desc }}
+
+
+
+
+
+ Total cost: {{ cost }} sats
+
+ Submit
+ Cancel
+
+
+
+
+
+
+
+
+
+
+
+
+ Copy invoice
+ Close
+
+
+
+
+
+{% endblock %} {% block scripts %}
+
+{% endblock %}
diff --git a/lnbits/extensions/smtp/templates/smtp/index.html b/lnbits/extensions/smtp/templates/smtp/index.html
new file mode 100644
index 00000000..bf43ad7f
--- /dev/null
+++ b/lnbits/extensions/smtp/templates/smtp/index.html
@@ -0,0 +1,528 @@
+{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
+%} {% block page %}
+
+
+
+
+
+ New Emailaddress
+
+
+
+
+
+
+
+
Emailaddresses
+
+
+ Export to CSV
+
+
+
+ {% raw %}
+
+
+
+
+ {{ col.label }}
+
+
+
+
+
+
+
+
+
+
+ {{ col.value }}
+
+
+
+
+
+
+
+
+
+
+ {% endraw %}
+
+
+
+
+
+
+
+
+
Emails
+
+
+ Export to CSV
+
+
+
+ {% raw %}
+
+
+
+ {{ col.label }}
+
+
+
+
+
+
+
+ {{ col.value }}
+
+
+
+
+
+
+ {% endraw %}
+
+
+
+
+
+
+
+
+ {{SITE_TITLE}} Sendmail extension
+
+
+
+
+ {% include "smtp/_api_docs.html" %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Update Form
+ Create Emailaddress
+ Cancel
+
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(user) }}
+
+{% endblock %}
diff --git a/lnbits/extensions/smtp/views.py b/lnbits/extensions/smtp/views.py
new file mode 100644
index 00000000..df208a77
--- /dev/null
+++ b/lnbits/extensions/smtp/views.py
@@ -0,0 +1,40 @@
+from http import HTTPStatus
+
+from fastapi import Depends, HTTPException, Request
+from fastapi.templating import Jinja2Templates
+from starlette.responses import HTMLResponse
+
+from lnbits.core.models import User
+from lnbits.decorators import check_user_exists
+
+from . import smtp_ext, smtp_renderer
+from .crud import get_emailaddress
+
+templates = Jinja2Templates(directory="templates")
+
+
+@smtp_ext.get("/", response_class=HTMLResponse)
+async def index(request: Request, user: User = Depends(check_user_exists)):
+ return smtp_renderer().TemplateResponse(
+ "smtp/index.html", {"request": request, "user": user.dict()}
+ )
+
+
+@smtp_ext.get("/{emailaddress_id}")
+async def display(request: Request, emailaddress_id):
+ emailaddress = await get_emailaddress(emailaddress_id)
+ if not emailaddress:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Emailaddress does not exist."
+ )
+
+ return smtp_renderer().TemplateResponse(
+ "smtp/display.html",
+ {
+ "request": request,
+ "emailaddress_id": emailaddress.id,
+ "email": emailaddress.email,
+ "desc": emailaddress.description,
+ "cost": emailaddress.cost,
+ },
+ )
diff --git a/lnbits/extensions/smtp/views_api.py b/lnbits/extensions/smtp/views_api.py
new file mode 100644
index 00000000..08a05ef3
--- /dev/null
+++ b/lnbits/extensions/smtp/views_api.py
@@ -0,0 +1,170 @@
+from http import HTTPStatus
+
+from fastapi import Depends, HTTPException, Query
+
+from lnbits.core.crud import get_user
+from lnbits.core.services import check_transaction_status, create_invoice
+from lnbits.decorators import WalletTypeInfo, get_key_type
+from lnbits.extensions.smtp.models import CreateEmail, CreateEmailaddress
+
+from . import smtp_ext
+from .crud import (
+ create_email,
+ create_emailaddress,
+ delete_email,
+ delete_emailaddress,
+ get_email,
+ get_emailaddress,
+ get_emailaddresses,
+ get_emails,
+ update_emailaddress,
+)
+from .smtp import valid_email
+
+
+## EMAILS
+@smtp_ext.get("/api/v1/email")
+async def api_email(
+ g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
+):
+ wallet_ids = [g.wallet.id]
+ if all_wallets:
+ user = await get_user(g.wallet.user)
+ if user:
+ wallet_ids = user.wallet_ids
+ return [email.dict() for email in await get_emails(wallet_ids)]
+
+
+@smtp_ext.get("/api/v1/email/{payment_hash}")
+async def api_smtp_send_email(payment_hash):
+ email = await get_email(payment_hash)
+ if not email:
+ raise HTTPException(
+ status_code=HTTPStatus.BAD_REQUEST, detail="paymenthash is wrong"
+ )
+
+ emailaddress = await get_emailaddress(email.emailaddress_id)
+
+ try:
+ status = await check_transaction_status(email.wallet, payment_hash)
+ is_paid = not status.pending
+ except Exception:
+ return {"paid": False}
+ if is_paid:
+ if emailaddress.anonymize:
+ await delete_email(email.id)
+ return {"paid": True}
+ return {"paid": False}
+
+
+@smtp_ext.post("/api/v1/email/{emailaddress_id}")
+async def api_smtp_make_email(emailaddress_id, data: CreateEmail):
+
+ valid_email(data.receiver)
+
+ emailaddress = await get_emailaddress(emailaddress_id)
+ # If the request is coming for the non-existant emailaddress
+ if not emailaddress:
+ raise HTTPException(
+ status_code=HTTPStatus.BAD_REQUEST,
+ detail="Emailaddress address does not exist.",
+ )
+ try:
+ memo = f"sent email from {emailaddress.email} to {data.receiver}"
+ if emailaddress.anonymize:
+ memo = "sent email"
+
+ payment_hash, payment_request = await create_invoice(
+ wallet_id=emailaddress.wallet,
+ amount=emailaddress.cost,
+ memo=memo,
+ extra={"tag": "smtp"},
+ )
+ except Exception as e:
+ raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
+
+ email = await create_email(
+ payment_hash=payment_hash, wallet=emailaddress.wallet, data=data
+ )
+
+ if not email:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Email could not be fetched."
+ )
+ return {"payment_hash": payment_hash, "payment_request": payment_request}
+
+
+@smtp_ext.delete("/api/v1/email/{email_id}")
+async def api_email_delete(email_id, g: WalletTypeInfo = Depends(get_key_type)):
+ email = await get_email(email_id)
+
+ if not email:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="LNsubdomain does not exist."
+ )
+
+ if email.wallet != g.wallet.id:
+ raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your email.")
+
+ await delete_email(email_id)
+ raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+
+
+## EMAILADDRESSES
+@smtp_ext.get("/api/v1/emailaddress")
+async def api_emailaddresses(
+ g: WalletTypeInfo = Depends(get_key_type),
+ all_wallets: bool = Query(False),
+):
+ wallet_ids = [g.wallet.id]
+ if all_wallets:
+ user = await get_user(g.wallet.user)
+ if user:
+ wallet_ids = user.wallet_ids
+ return [
+ emailaddress.dict() for emailaddress in await get_emailaddresses(wallet_ids)
+ ]
+
+
+@smtp_ext.post("/api/v1/emailaddress")
+@smtp_ext.put("/api/v1/emailaddress/{emailaddress_id}")
+async def api_emailaddress_create(
+ data: CreateEmailaddress,
+ emailaddress_id=None,
+ g: WalletTypeInfo = Depends(get_key_type),
+):
+ if emailaddress_id:
+ emailaddress = await get_emailaddress(emailaddress_id)
+
+ if not emailaddress:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Emailadress does not exist."
+ )
+ if emailaddress.wallet != g.wallet.id:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not your emailaddress."
+ )
+
+ emailaddress = await update_emailaddress(emailaddress_id, **data.dict())
+ else:
+ emailaddress = await create_emailaddress(data=data)
+ return emailaddress.dict()
+
+
+@smtp_ext.delete("/api/v1/emailaddress/{emailaddress_id}")
+async def api_emailaddress_delete(
+ emailaddress_id, g: WalletTypeInfo = Depends(get_key_type)
+):
+ emailaddress = await get_emailaddress(emailaddress_id)
+
+ if not emailaddress:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail="Emailaddress does not exist."
+ )
+ if emailaddress.wallet != g.wallet.id:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not your Emailaddress."
+ )
+
+ await delete_emailaddress(emailaddress_id)
+ raise HTTPException(status_code=HTTPStatus.NO_CONTENT)