mirror of
https://github.com/lnbits/lnbits.git
synced 2025-03-28 02:31:51 +01:00
remove smtp
This commit is contained in:
parent
77a6ac041c
commit
cb475d7f88
@ -1,14 +0,0 @@
|
||||
<h1>SMTP Extension</h1>
|
||||
|
||||
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.
|
||||
|
@ -1,34 +0,0 @@
|
||||
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: F401,F403
|
||||
from .views_api import * # noqa: F401,F403
|
||||
|
||||
|
||||
def smtp_start():
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "SMTP",
|
||||
"short_description": "Charge sats for sending emails",
|
||||
"tile": "/smtp/static/smtp-bitcoin-email.png",
|
||||
"contributors": ["dni"]
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
from typing import List, Optional, Union
|
||||
|
||||
from lnbits.helpers import urlsafe_short_hash
|
||||
|
||||
from . import db
|
||||
from .models import CreateEmail, CreateEmailaddress, Email, Emailaddress
|
||||
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) -> Emailaddress:
|
||||
|
||||
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) -> Emailaddress:
|
||||
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 Emailaddress(**row)
|
||||
|
||||
|
||||
async def get_emailaddress(emailaddress_id: str) -> Optional[Emailaddress]:
|
||||
row = await db.fetchone(
|
||||
"SELECT * FROM smtp.emailaddress WHERE id = ?", (emailaddress_id,)
|
||||
)
|
||||
return Emailaddress(**row) if row else None
|
||||
|
||||
|
||||
async def get_emailaddress_by_email(email: str) -> Optional[Emailaddress]:
|
||||
row = await db.fetchone("SELECT * FROM smtp.emailaddress WHERE email = ?", (email,))
|
||||
return Emailaddress(**row) if row else None
|
||||
|
||||
|
||||
async def get_emailaddresses(wallet_ids: Union[str, List[str]]) -> List[Emailaddress]:
|
||||
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 [Emailaddress(**row) for row in rows]
|
||||
|
||||
|
||||
async def delete_emailaddress(emailaddress_id: str) -> None:
|
||||
await db.execute("DELETE FROM smtp.emailaddress WHERE id = ?", (emailaddress_id,))
|
||||
|
||||
|
||||
async def create_email(wallet: str, data: CreateEmail, payment_hash: str = "") -> Email:
|
||||
id = urlsafe_short_hash()
|
||||
await db.execute(
|
||||
"""
|
||||
INSERT INTO smtp.email (id, payment_hash, wallet, emailaddress_id, subject, receiver, message, paid)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
id,
|
||||
payment_hash,
|
||||
wallet,
|
||||
data.emailaddress_id,
|
||||
data.subject,
|
||||
data.receiver,
|
||||
data.message,
|
||||
False,
|
||||
),
|
||||
)
|
||||
|
||||
new_email = await get_email(id)
|
||||
assert new_email, "Newly created email couldn't be retrieved"
|
||||
return new_email
|
||||
|
||||
|
||||
async def set_email_paid(payment_hash: str) -> bool:
|
||||
email = await get_email_by_payment_hash(payment_hash)
|
||||
if email and email.paid is False:
|
||||
await db.execute(
|
||||
"UPDATE smtp.email SET paid = true WHERE payment_hash = ?", (payment_hash,)
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def get_email_by_payment_hash(payment_hash: str) -> Optional[Email]:
|
||||
row = await db.fetchone(
|
||||
"SELECT * FROM smtp.email WHERE payment_hash = ?", (payment_hash,)
|
||||
)
|
||||
return Email(**row) if row else None
|
||||
|
||||
|
||||
async def get_email(id: str) -> Optional[Email]:
|
||||
row = await db.fetchone("SELECT * FROM smtp.email WHERE id = ?", (id,))
|
||||
return Email(**row) if row else None
|
||||
|
||||
|
||||
async def get_emails(wallet_ids: Union[str, List[str]]) -> List[Email]:
|
||||
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 [Email(**row) for row in rows]
|
||||
|
||||
|
||||
async def delete_email(email_id: str) -> None:
|
||||
await db.execute("DELETE FROM smtp.email WHERE id = ?", (email_id,))
|
@ -1,39 +0,0 @@
|
||||
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}
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def m002_add_payment_hash(db):
|
||||
await db.execute("ALTER TABLE smtp.email ADD COLUMN payment_hash TEXT;")
|
@ -1,47 +0,0 @@
|
||||
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 Emailaddress(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 Email(BaseModel):
|
||||
id: str
|
||||
wallet: str
|
||||
emailaddress_id: str
|
||||
subject: str
|
||||
receiver: str
|
||||
message: str
|
||||
paid: bool
|
||||
time: int
|
@ -1,110 +0,0 @@
|
||||
import re
|
||||
import socket
|
||||
import time
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.utils import formatdate
|
||||
from smtplib import SMTP_SSL as SMTP
|
||||
from typing import Union
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from .models import CreateEmail, CreateEmailaddress, Email, Emailaddress
|
||||
|
||||
|
||||
async def send_mail(
|
||||
emailaddress: Union[Emailaddress, CreateEmailaddress],
|
||||
email: Union[Email, CreateEmail],
|
||||
):
|
||||
smtp_client = SmtpService(emailaddress)
|
||||
message = smtp_client.create_message(email)
|
||||
await smtp_client.send_mail(email.receiver, message)
|
||||
|
||||
|
||||
def valid_email(s):
|
||||
# https://regexr.com/2rhq7
|
||||
pat = r"[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
|
||||
log = f"SMTP - invalid email: {s}."
|
||||
logger.error(log)
|
||||
raise Exception(log)
|
||||
|
||||
|
||||
class SmtpService:
|
||||
def __init__(self, emailaddress: Union[Emailaddress, CreateEmailaddress]) -> None:
|
||||
self.sender = emailaddress.email
|
||||
self.smtp_server = emailaddress.smtp_server
|
||||
self.smtp_port = emailaddress.smtp_port
|
||||
self.smtp_user = emailaddress.smtp_user
|
||||
self.smtp_password = emailaddress.smtp_password
|
||||
|
||||
def render_email(self, email: Union[Email, CreateEmail]):
|
||||
signature: str = "Email sent by LNbits SMTP extension."
|
||||
text = f"{email.message}\n\n{signature}"
|
||||
html = (
|
||||
"""
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>"""
|
||||
+ email.message
|
||||
+ """</p>
|
||||
<p>"""
|
||||
+ signature
|
||||
+ """</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
)
|
||||
return text, html
|
||||
|
||||
def create_message(self, email: Union[Email, CreateEmail]):
|
||||
ts = time.time()
|
||||
date = formatdate(ts, True)
|
||||
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg["Date"] = date
|
||||
msg["Subject"] = email.subject
|
||||
msg["From"] = self.sender
|
||||
msg["To"] = email.receiver
|
||||
|
||||
text, html = self.render_email(email)
|
||||
|
||||
part1 = MIMEText(text, "plain")
|
||||
part2 = MIMEText(html, "html")
|
||||
msg.attach(part1)
|
||||
msg.attach(part2)
|
||||
return msg
|
||||
|
||||
async def send_mail(self, receiver, msg: MIMEMultipart):
|
||||
|
||||
valid_email(self.sender)
|
||||
valid_email(receiver)
|
||||
|
||||
try:
|
||||
conn = SMTP(host=self.smtp_server, port=int(self.smtp_port), timeout=10)
|
||||
logger.debug("SMTP - connected to smtp server.")
|
||||
# conn.set_debuglevel(True)
|
||||
except:
|
||||
log = f"SMTP - error connecting to smtp server: {self.smtp_server}:{self.smtp_port}."
|
||||
logger.debug(log)
|
||||
raise Exception(log)
|
||||
|
||||
try:
|
||||
conn.login(self.smtp_user, self.smtp_password)
|
||||
logger.debug("SMTP - successful login to smtp server.")
|
||||
except:
|
||||
log = f"SMTP - error login into smtp {self.smtp_user}."
|
||||
logger.error(log)
|
||||
raise Exception(log)
|
||||
|
||||
try:
|
||||
conn.sendmail(self.sender, receiver, msg.as_string())
|
||||
logger.debug("SMTP - successfully send email.")
|
||||
except socket.error as e:
|
||||
log = f"SMTP - error sending email: {str(e)}."
|
||||
logger.error(log)
|
||||
raise Exception(log)
|
||||
finally:
|
||||
conn.quit()
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
@ -1,36 +0,0 @@
|
||||
import asyncio
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from lnbits.core.models import Payment
|
||||
from lnbits.tasks import register_invoice_listener
|
||||
|
||||
from .crud import get_email_by_payment_hash, 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_by_payment_hash(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)
|
@ -1,23 +0,0 @@
|
||||
<q-expansion-item
|
||||
group="extras"
|
||||
icon="swap_vertical_circle"
|
||||
label="About LNBits SMTP"
|
||||
:content-inset-level="0.5"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<h5 class="text-subtitle1 q-my-none">
|
||||
LNBits SMTP: Get paid sats to send emails
|
||||
</h5>
|
||||
<p>
|
||||
Charge people for using sending an email via your smtp server<br />
|
||||
<a
|
||||
href="https://github.com/lnbits/lnbits/tree/main/lnbits/extensions/smtp"
|
||||
>More details</a
|
||||
>
|
||||
<br />
|
||||
<small>Created by, <a href="https://github.com/dni">dni</a></small>
|
||||
</p>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-expansion-item>
|
@ -1,175 +0,0 @@
|
||||
{% extends "public.html" %} {% block page %}
|
||||
<div class="row q-col-gutter-md justify-center">
|
||||
<div class="col-12 col-md-7 col-lg-6 q-gutter-y-md">
|
||||
<q-card class="q-pa-lg">
|
||||
<q-card-section class="q-pa-none">
|
||||
<h3 class="q-my-none">{{ email }}</h3>
|
||||
<br />
|
||||
<h5 class="q-my-none">{{ desc }}</h5>
|
||||
<br />
|
||||
<q-form @submit="Invoice()" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="formDialog.data.receiver"
|
||||
type="text"
|
||||
label="Receiver"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="formDialog.data.subject"
|
||||
type="text"
|
||||
label="Subject"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="formDialog.data.message"
|
||||
type="textarea"
|
||||
label="Message "
|
||||
></q-input>
|
||||
<p>Total cost: {{ cost }} sats</p>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
unelevated
|
||||
color="primary"
|
||||
:disable="formDialog.data.receiver == '' || formDialog.data.subject == '' || formDialog.data.message == ''"
|
||||
type="submit"
|
||||
>Submit</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
<q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog">
|
||||
<q-card
|
||||
v-if="!receive.paymentReq"
|
||||
class="q-pa-lg q-pt-xl lnbits__dialog-card"
|
||||
>
|
||||
</q-card>
|
||||
<q-card v-else class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<div class="text-center q-mb-lg">
|
||||
<a :href="'lightning:' + receive.paymentReq">
|
||||
<q-responsive :ratio="1" class="q-mx-xl">
|
||||
<qrcode
|
||||
:value="paymentReq"
|
||||
:options="{width: 340}"
|
||||
class="rounded-borders"
|
||||
></qrcode>
|
||||
</q-responsive>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn outline color="grey" @click="copyText(receive.paymentReq)"
|
||||
>Copy invoice</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
|
||||
{% endblock %} {% block scripts %}
|
||||
<script>
|
||||
console.log('{{ cost }}')
|
||||
Vue.component(VueQrcode.name, VueQrcode)
|
||||
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
mixins: [windowMixin],
|
||||
data: function () {
|
||||
return {
|
||||
paymentReq: null,
|
||||
redirectUrl: null,
|
||||
formDialog: {
|
||||
show: false,
|
||||
data: {
|
||||
subject: '',
|
||||
receiver: '',
|
||||
message: ''
|
||||
}
|
||||
},
|
||||
receive: {
|
||||
show: false,
|
||||
status: 'pending',
|
||||
paymentReq: null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
closeReceiveDialog: function () {
|
||||
var checker = this.receive.paymentChecker
|
||||
dismissMsg()
|
||||
|
||||
clearInterval(paymentChecker)
|
||||
setTimeout(function () {}, 10000)
|
||||
},
|
||||
Invoice: function () {
|
||||
var self = this
|
||||
axios
|
||||
.post('/smtp/api/v1/email/{{ emailaddress_id }}', {
|
||||
emailaddress_id: '{{ emailaddress_id }}',
|
||||
subject: self.formDialog.data.subject,
|
||||
receiver: self.formDialog.data.receiver,
|
||||
message: self.formDialog.data.message
|
||||
})
|
||||
.then(function (response) {
|
||||
self.paymentReq = response.data.payment_request
|
||||
self.paymentCheck = response.data.payment_hash
|
||||
|
||||
dismissMsg = self.$q.notify({
|
||||
timeout: 0,
|
||||
message: 'Waiting for payment...'
|
||||
})
|
||||
|
||||
self.receive = {
|
||||
show: true,
|
||||
status: 'pending',
|
||||
paymentReq: self.paymentReq
|
||||
}
|
||||
|
||||
paymentChecker = setInterval(function () {
|
||||
axios
|
||||
.get('/smtp/api/v1/email/' + self.paymentCheck)
|
||||
.then(function (res) {
|
||||
console.log(res.data)
|
||||
if (res.data.paid) {
|
||||
clearInterval(paymentChecker)
|
||||
self.receive = {
|
||||
show: false,
|
||||
status: 'complete',
|
||||
paymentReq: null
|
||||
}
|
||||
dismissMsg()
|
||||
|
||||
console.log(self.formDialog)
|
||||
self.formDialog.data.subject = ''
|
||||
self.formDialog.data.receiver = ''
|
||||
self.formDialog.data.message = ''
|
||||
self.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Sent, thank you!',
|
||||
icon: 'thumb_up'
|
||||
})
|
||||
console.log('END')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
}, 2000)
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@ -1,604 +0,0 @@
|
||||
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
|
||||
%} {% block page %}
|
||||
|
||||
<div class="row q-col-gutter-md">
|
||||
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-btn
|
||||
unelevated
|
||||
color="primary"
|
||||
@click="emailaddressDialog.show = true"
|
||||
>New Emailaddress</q-btn
|
||||
>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap q-mb-md">
|
||||
<div class="col">
|
||||
<h5 class="text-subtitle1 q-my-none">Emailaddresses</h5>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<q-btn flat color="grey" @click="exportEmailaddressesCSV"
|
||||
>Export to CSV</q-btn
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<q-table
|
||||
dense
|
||||
flat
|
||||
:data="emailaddresses"
|
||||
row-key="id"
|
||||
:columns="emailaddressTable.columns"
|
||||
:pagination.sync="emailaddressTable.pagination"
|
||||
>
|
||||
{% raw %}
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width></q-th>
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.label }}
|
||||
</q-th>
|
||||
<q-th auto-width></q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
unelevated
|
||||
dense
|
||||
size="xs"
|
||||
icon="link"
|
||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
type="a"
|
||||
:href="props.row.displayUrl"
|
||||
target="_blank"
|
||||
></q-btn>
|
||||
<q-btn
|
||||
unelevated
|
||||
dense
|
||||
size="xs"
|
||||
icon="email"
|
||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
@click="showEmailDialog(props.row.id)"
|
||||
></q-btn>
|
||||
</q-td>
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.value }}
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
@click="updateEmailaddressDialog(props.row.id)"
|
||||
icon="edit"
|
||||
color="light-blue"
|
||||
>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
@click="deleteEmailaddress(props.row.id)"
|
||||
icon="cancel"
|
||||
color="pink"
|
||||
></q-btn>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
{% endraw %}
|
||||
</q-table>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap q-mb-md">
|
||||
<div class="col">
|
||||
<h5 class="text-subtitle1 q-my-none">Emails</h5>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<q-btn flat color="grey" @click="exportEmailsCSV"
|
||||
>Export to CSV</q-btn
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<q-table
|
||||
dense
|
||||
flat
|
||||
:data="emails"
|
||||
row-key="id"
|
||||
:columns="emailsTable.columns"
|
||||
:pagination.sync="emailsTable.pagination"
|
||||
>
|
||||
{% raw %}
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.label }}
|
||||
</q-th>
|
||||
<q-th auto-width></q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.value }}
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
@click="deleteEmail(props.row.id)"
|
||||
icon="cancel"
|
||||
color="pink"
|
||||
></q-btn>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
{% endraw %}
|
||||
</q-table>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 col-lg-5 q-gutter-y-md">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<h6 class="text-subtitle1 q-my-none">
|
||||
{{SITE_TITLE}} Sendmail extension
|
||||
</h6>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
<q-list> {% include "smtp/_api_docs.html" %} </q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
<q-dialog v-model="emailDialog.show" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<q-form @submit="sendEmail()" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailDialog.data.receiver"
|
||||
type="text"
|
||||
label="Receiver"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailDialog.data.subject"
|
||||
type="text"
|
||||
label="Subject"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailDialog.data.message"
|
||||
type="textarea"
|
||||
label="Message "
|
||||
></q-input>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
unelevated
|
||||
color="primary"
|
||||
:disable="emailDialog.data.receiver == '' || emailDialog.data.subject == '' || emailDialog.data.message == ''"
|
||||
type="submit"
|
||||
>Submit</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="emailaddressDialog.show" position="top">
|
||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||
<q-form @submit="sendFormData" class="q-gutter-md">
|
||||
<q-select
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model="emailaddressDialog.data.wallet"
|
||||
:options="g.user.walletOptions"
|
||||
label="Wallet *"
|
||||
>
|
||||
</q-select>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model.trim="emailaddressDialog.data.email"
|
||||
type="text"
|
||||
label="Emailaddress "
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model.trim="emailaddressDialog.data.testemail"
|
||||
type="text"
|
||||
label="Emailaddress to test the server"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailaddressDialog.data.smtp_server"
|
||||
type="text"
|
||||
label="SMTP Host"
|
||||
>
|
||||
</q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailaddressDialog.data.smtp_user"
|
||||
type="text"
|
||||
label="SMTP User"
|
||||
>
|
||||
</q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailaddressDialog.data.smtp_password"
|
||||
type="password"
|
||||
label="SMTP Password"
|
||||
>
|
||||
</q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailaddressDialog.data.smtp_port"
|
||||
type="text"
|
||||
label="SMTP Port"
|
||||
>
|
||||
</q-input>
|
||||
<div id="lolcheck">
|
||||
<q-checkbox
|
||||
name="anonymize"
|
||||
v-model="emailaddressDialog.data.anonymize"
|
||||
label="ANONYMIZE, don't save mails, no addresses in tx"
|
||||
/>
|
||||
</div>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="emailaddressDialog.data.description"
|
||||
type="textarea"
|
||||
label="Description "
|
||||
>
|
||||
</q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.number="emailaddressDialog.data.cost"
|
||||
type="number"
|
||||
label="Amount per email in satoshis"
|
||||
>
|
||||
</q-input>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
v-if="emailaddressDialog.data.id"
|
||||
unelevated
|
||||
color="primary"
|
||||
type="submit"
|
||||
>Update Form</q-btn
|
||||
>
|
||||
<q-btn
|
||||
v-else
|
||||
unelevated
|
||||
color="primary"
|
||||
:disable="enableButton()"
|
||||
type="submit"
|
||||
>Create Emailaddress</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
||||
>Cancel</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
|
||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||
<script>
|
||||
var LNSendmail = function (obj) {
|
||||
obj.date = Quasar.utils.date.formatDate(
|
||||
new Date(obj.time * 1000),
|
||||
'YYYY-MM-DD HH:mm'
|
||||
)
|
||||
obj.displayUrl = ['/smtp/', obj.id].join('')
|
||||
return obj
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
mixins: [windowMixin],
|
||||
data: function () {
|
||||
return {
|
||||
emailaddresses: [],
|
||||
emails: [],
|
||||
emailaddressTable: {
|
||||
columns: [
|
||||
{name: 'id', align: 'left', label: 'ID', field: 'id'},
|
||||
{
|
||||
name: 'anonymize',
|
||||
align: 'left',
|
||||
label: 'Anonymize',
|
||||
field: 'anonymize'
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
align: 'left',
|
||||
label: 'Emailaddress',
|
||||
field: 'email'
|
||||
},
|
||||
{name: 'wallet', align: 'left', label: 'Wallet', field: 'wallet'},
|
||||
{
|
||||
name: 'description',
|
||||
align: 'left',
|
||||
label: 'Description',
|
||||
field: 'description'
|
||||
},
|
||||
{
|
||||
name: 'cost',
|
||||
align: 'left',
|
||||
label: 'Cost',
|
||||
field: 'cost'
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 10
|
||||
}
|
||||
},
|
||||
emailsTable: {
|
||||
columns: [
|
||||
{
|
||||
name: 'emailaddress_id',
|
||||
align: 'left',
|
||||
label: 'From',
|
||||
field: 'emailaddress_id'
|
||||
},
|
||||
{
|
||||
name: 'receiver',
|
||||
align: 'left',
|
||||
label: 'Receiver',
|
||||
field: 'receiver'
|
||||
},
|
||||
{
|
||||
name: 'subject',
|
||||
align: 'left',
|
||||
label: 'Subject',
|
||||
field: 'subject'
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
align: 'left',
|
||||
label: 'Message',
|
||||
field: 'message'
|
||||
},
|
||||
{
|
||||
name: 'paid',
|
||||
align: 'left',
|
||||
label: 'Is paid',
|
||||
field: 'paid'
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 10
|
||||
}
|
||||
},
|
||||
emailDialog: {
|
||||
show: false,
|
||||
data: {}
|
||||
},
|
||||
emailaddressDialog: {
|
||||
show: false,
|
||||
data: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
enableButton: function () {
|
||||
return (
|
||||
this.emailaddressDialog.data.cost == null ||
|
||||
this.emailaddressDialog.data.cost < 0 ||
|
||||
this.emailaddressDialog.data.testemail == null ||
|
||||
this.emailaddressDialog.data.smtp_user == null ||
|
||||
this.emailaddressDialog.data.smtp_password == null ||
|
||||
this.emailaddressDialog.data.smtp_server == null ||
|
||||
this.emailaddressDialog.data.smtp_port == null ||
|
||||
this.emailaddressDialog.data.email == null ||
|
||||
this.emailaddressDialog.data.description == null
|
||||
)
|
||||
},
|
||||
getEmails: function () {
|
||||
var self = this
|
||||
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
'/smtp/api/v1/email?all_wallets=true',
|
||||
this.g.user.wallets[0].inkey
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emails = response.data.map(function (obj) {
|
||||
return LNSendmail(obj)
|
||||
})
|
||||
})
|
||||
},
|
||||
deleteEmail: function (emailId) {
|
||||
var self = this
|
||||
var email = _.findWhere(this.emails, {id: emailId})
|
||||
|
||||
LNbits.utils
|
||||
.confirmDialog('Are you sure you want to delete this email')
|
||||
.onOk(function () {
|
||||
LNbits.api
|
||||
.request(
|
||||
'DELETE',
|
||||
'/smtp/api/v1/email/' + emailId,
|
||||
_.findWhere(self.g.user.wallets, {id: email.wallet}).inkey
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emails = _.reject(self.emails, function (obj) {
|
||||
return obj.id == emailId
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
exportEmailsCSV: function () {
|
||||
LNbits.utils.exportCSV(this.emailsTable.columns, this.emails)
|
||||
},
|
||||
|
||||
getEmailAddresses: function () {
|
||||
var self = this
|
||||
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
'/smtp/api/v1/emailaddress?all_wallets=true',
|
||||
this.g.user.wallets[0].inkey
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emailaddresses = response.data.map(function (obj) {
|
||||
return LNSendmail(obj)
|
||||
})
|
||||
})
|
||||
},
|
||||
sendFormData: function () {
|
||||
var wallet = _.findWhere(this.g.user.wallets, {
|
||||
id: this.emailaddressDialog.data.wallet
|
||||
})
|
||||
var data = this.emailaddressDialog.data
|
||||
if (data.id) {
|
||||
this.updateEmailaddress(wallet, data)
|
||||
} else {
|
||||
this.createEmailaddress(wallet, data)
|
||||
}
|
||||
},
|
||||
|
||||
createEmailaddress: function (wallet, data) {
|
||||
var self = this
|
||||
|
||||
LNbits.api
|
||||
.request('POST', '/smtp/api/v1/emailaddress', wallet.inkey, data)
|
||||
.then(function (response) {
|
||||
self.emailaddresses.push(LNSendmail(response.data))
|
||||
self.emailaddressDialog.show = false
|
||||
self.emailaddressDialog.data = {}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
sendEmail: function () {
|
||||
var self = this
|
||||
var emailaddress = _.findWhere(this.emailaddresses, {
|
||||
id: self.emailDialog.data.emailaddress_id
|
||||
})
|
||||
var wallet = _.findWhere(this.g.user.wallets, {
|
||||
id: emailaddress.wallet
|
||||
})
|
||||
LNbits.api
|
||||
.request(
|
||||
'POST',
|
||||
'/smtp/api/v1/email/' + emailaddress.id + '/send',
|
||||
wallet.adminkey,
|
||||
self.emailDialog.data
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emailDialog.show = false
|
||||
self.emailDialog.data = {}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
showEmailDialog: function (emailaddress_id) {
|
||||
this.emailDialog.data.emailaddress_id = emailaddress_id
|
||||
this.emailDialog.show = true
|
||||
},
|
||||
updateEmailaddressDialog: function (formId) {
|
||||
var link = _.findWhere(this.emailaddresses, {id: formId})
|
||||
this.emailaddressDialog.data = _.clone(link)
|
||||
this.emailaddressDialog.show = true
|
||||
},
|
||||
updateEmailaddress: function (wallet, data) {
|
||||
var self = this
|
||||
|
||||
LNbits.api
|
||||
.request(
|
||||
'PUT',
|
||||
'/smtp/api/v1/emailaddress/' + data.id,
|
||||
wallet.inkey,
|
||||
data
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emailaddresses = _.reject(self.emailaddresses, function (obj) {
|
||||
return obj.id == data.id
|
||||
})
|
||||
self.emailaddresses.push(LNSendmail(response.data))
|
||||
self.emailaddressDialog.show = false
|
||||
self.emailaddressDialog.data = {}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
deleteEmailaddress: function (emailaddressId) {
|
||||
var self = this
|
||||
var emailaddresses = _.findWhere(this.emailaddresses, {
|
||||
id: emailaddressId
|
||||
})
|
||||
|
||||
LNbits.utils
|
||||
.confirmDialog(
|
||||
'Are you sure you want to delete this emailaddress link?'
|
||||
)
|
||||
.onOk(function () {
|
||||
LNbits.api
|
||||
.request(
|
||||
'DELETE',
|
||||
'/smtp/api/v1/emailaddress/' + emailaddressId,
|
||||
_.findWhere(self.g.user.wallets, {id: emailaddresses.wallet})
|
||||
.inkey
|
||||
)
|
||||
.then(function (response) {
|
||||
self.emailaddresses = _.reject(
|
||||
self.emailaddresses,
|
||||
function (obj) {
|
||||
return obj.id == emailaddressId
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
exportEmailaddressesCSV: function () {
|
||||
LNbits.utils.exportCSV(
|
||||
this.emailaddressTable.columns,
|
||||
this.emailaddresses
|
||||
)
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if (this.g.user.wallets.length) {
|
||||
this.getEmailAddresses()
|
||||
this.getEmails()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@ -1,40 +0,0 @@
|
||||
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,
|
||||
},
|
||||
)
|
@ -1,190 +0,0 @@
|
||||
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, require_admin_key
|
||||
|
||||
from . import smtp_ext
|
||||
from .crud import (
|
||||
create_email,
|
||||
create_emailaddress,
|
||||
delete_email,
|
||||
delete_emailaddress,
|
||||
get_email,
|
||||
get_email_by_payment_hash,
|
||||
get_emailaddress,
|
||||
get_emailaddresses,
|
||||
get_emails,
|
||||
update_emailaddress,
|
||||
)
|
||||
from .models import CreateEmail, CreateEmailaddress
|
||||
from .smtp import send_mail, 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_by_payment_hash(payment_hash)
|
||||
if not email:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.BAD_REQUEST, detail="paymenthash is wrong"
|
||||
)
|
||||
|
||||
emailaddress = await get_emailaddress(email.emailaddress_id)
|
||||
assert emailaddress
|
||||
|
||||
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 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.post(
|
||||
"/api/v1/email/{emailaddress_id}/send", dependencies=[Depends(require_admin_key)]
|
||||
)
|
||||
async def api_smtp_make_email_send(emailaddress_id, data: CreateEmail):
|
||||
valid_email(data.receiver)
|
||||
emailaddress = await get_emailaddress(emailaddress_id)
|
||||
if not emailaddress:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.BAD_REQUEST,
|
||||
detail="Emailaddress address does not exist.",
|
||||
)
|
||||
email = await create_email(wallet=emailaddress.wallet, data=data)
|
||||
if not email:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.NOT_FOUND, detail="Email could not be fetched."
|
||||
)
|
||||
await send_mail(emailaddress, email)
|
||||
return {"sent": True}
|
||||
|
||||
|
||||
@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)
|
Loading…
x
Reference in New Issue
Block a user