feat: add test email and improve on email notifications (#3018)
This commit is contained in:
parent
9bd037b6e7
commit
f61471b0f2
7 changed files with 111 additions and 30 deletions
|
|
@ -24,7 +24,7 @@ from lnbits.core.models.notifications import (
|
|||
)
|
||||
from lnbits.core.services.nostr import fetch_nip5_details, send_nostr_dm
|
||||
from lnbits.core.services.websockets import websocket_manager
|
||||
from lnbits.helpers import check_callback_url
|
||||
from lnbits.helpers import check_callback_url, is_valid_email_address
|
||||
from lnbits.settings import settings
|
||||
from lnbits.utils.nostr import normalize_private_key
|
||||
|
||||
|
|
@ -111,41 +111,56 @@ async def send_telegram_message(token: str, chat_id: str, message: str) -> dict:
|
|||
return response.json()
|
||||
|
||||
|
||||
async def send_email_notification(message: str) -> dict:
|
||||
await send_email(
|
||||
settings.lnbits_email_notifications_server,
|
||||
settings.lnbits_email_notifications_port,
|
||||
settings.lnbits_email_notifications_password,
|
||||
settings.lnbits_email_notifications_email,
|
||||
settings.lnbits_email_notifications_to_emails,
|
||||
"LNbits Notification",
|
||||
message,
|
||||
)
|
||||
return {"status": "ok"}
|
||||
async def send_email_notification(
|
||||
message: str, subject: str = "LNbits Notification"
|
||||
) -> dict:
|
||||
if not settings.lnbits_email_notifications_enabled:
|
||||
return {"status": "error", "message": "Email notifications are disabled"}
|
||||
try:
|
||||
await send_email(
|
||||
settings.lnbits_email_notifications_server,
|
||||
settings.lnbits_email_notifications_port,
|
||||
settings.lnbits_email_notifications_username,
|
||||
settings.lnbits_email_notifications_password,
|
||||
settings.lnbits_email_notifications_email,
|
||||
settings.lnbits_email_notifications_to_emails,
|
||||
subject,
|
||||
message,
|
||||
)
|
||||
return {"status": "ok"}
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending email notification: {e}")
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
async def send_email(
|
||||
server: str,
|
||||
port: int,
|
||||
username: str,
|
||||
password: str,
|
||||
from_email: str,
|
||||
to_emails: list,
|
||||
to_emails: list[str],
|
||||
subject: str,
|
||||
message: str,
|
||||
):
|
||||
) -> bool:
|
||||
if not is_valid_email_address(from_email):
|
||||
raise ValueError(f"Invalid from email address: {from_email}")
|
||||
if len(to_emails) == 0:
|
||||
raise ValueError("No email addresses provided")
|
||||
for email in to_emails:
|
||||
if not is_valid_email_address(email):
|
||||
raise ValueError(f"Invalid email address: {email}")
|
||||
msg = MIMEMultipart()
|
||||
msg["From"] = from_email
|
||||
msg["To"] = ", ".join(to_emails)
|
||||
msg["Subject"] = subject
|
||||
msg.attach(MIMEText(message, "plain"))
|
||||
try:
|
||||
with smtplib.SMTP(server, port) as smtp_server:
|
||||
smtp_server.starttls()
|
||||
smtp_server.login(from_email, password)
|
||||
smtp_server.sendmail(from_email, to_emails, msg.as_string())
|
||||
logger.debug(f"Emails sent successfully to: {', '.join(to_emails)}")
|
||||
except Exception as e:
|
||||
logger.debug(f"Failed to send email: {e}")
|
||||
username = username if len(username) > 0 else from_email
|
||||
with smtplib.SMTP(server, port) as smtp_server:
|
||||
smtp_server.starttls()
|
||||
smtp_server.login(username, password)
|
||||
smtp_server.sendmail(from_email, to_emails, msg.as_string())
|
||||
return True
|
||||
|
||||
|
||||
def is_message_type_enabled(message_type: NotificationType) -> bool:
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@
|
|||
<div class="col-sm-12">
|
||||
<q-separator></q-separator>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<strong v-text="$t('notifications_email_config')"></strong>
|
||||
<q-item tag="label" v-ripple>
|
||||
|
|
@ -194,6 +193,24 @@
|
|||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item tag="label" v-ripple>
|
||||
<q-item-section>
|
||||
<q-item-label
|
||||
v-text="$t('notifications_send_email_username')"
|
||||
></q-item-label>
|
||||
<q-item-label
|
||||
caption
|
||||
v-text="$t('notifications_send_email_username_desc')"
|
||||
></q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-input
|
||||
:type="hideInputToggle ? 'password' : 'text'"
|
||||
filled
|
||||
v-model="formData.lnbits_email_notifications_username"
|
||||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item tag="label" v-ripple>
|
||||
<q-item-section>
|
||||
<q-item-label
|
||||
|
|
@ -212,7 +229,19 @@
|
|||
/>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-btn
|
||||
@click="sendTestEmail()"
|
||||
label="Send Test Email Notification"
|
||||
color="primary"
|
||||
class="q-mt-md"
|
||||
></q-btn>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<q-item tag="label" v-ripple>
|
||||
<q-item-section>
|
||||
<q-item-label
|
||||
|
|
@ -249,9 +278,6 @@
|
|||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<q-item tag="label" v-ripple>
|
||||
<q-item-section>
|
||||
<q-item-label
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from lnbits.core.services import (
|
|||
get_balance_delta,
|
||||
update_cached_settings,
|
||||
)
|
||||
from lnbits.core.services.notifications import send_email_notification
|
||||
from lnbits.core.services.settings import dict_to_settings
|
||||
from lnbits.decorators import check_admin, check_super_user
|
||||
from lnbits.server import server_restart
|
||||
|
|
@ -50,6 +51,18 @@ async def api_monitor():
|
|||
}
|
||||
|
||||
|
||||
@admin_router.get(
|
||||
"/api/v1/testemail",
|
||||
name="TestEmail",
|
||||
description="send a test email to the admin",
|
||||
dependencies=[Depends(check_admin)],
|
||||
)
|
||||
async def api_test_email():
|
||||
return await send_email_notification(
|
||||
"This is a LNbits test email.", "LNbits Test Email"
|
||||
)
|
||||
|
||||
|
||||
@admin_router.get("/api/v1/settings", response_model=Optional[AdminSettings])
|
||||
async def api_get_settings(
|
||||
user: User = Depends(check_admin),
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ class NotificationsSettings(LNbitsSettings):
|
|||
lnbits_telegram_notifications_chat_id: str = Field(default="")
|
||||
lnbits_email_notifications_enabled: bool = Field(default=False)
|
||||
lnbits_email_notifications_email: str = Field(default="")
|
||||
lnbits_email_notifications_username: str = Field(default="")
|
||||
lnbits_email_notifications_password: str = Field(default="")
|
||||
lnbits_email_notifications_server: str = Field(default="smtp.protonmail.ch")
|
||||
lnbits_email_notifications_port: int = Field(default=587)
|
||||
|
|
|
|||
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -198,9 +198,13 @@ window.localisation.en = {
|
|||
|
||||
notifications_email_config: 'Email Configuration',
|
||||
notifications_enable_email: 'Enable Email',
|
||||
notifications_enable_email_desc: 'Send notfications over Email',
|
||||
notifications_enable_email_desc: 'Send notfications over email',
|
||||
notifications_send_test_email: 'Send test email',
|
||||
notifications_send_email: 'Send email',
|
||||
notifications_send_email_desc: 'Email you will send from',
|
||||
notifications_send_email_username: 'Username',
|
||||
notifications_send_email_username_desc:
|
||||
'Username, will use the email if not set',
|
||||
notifications_send_email_password: 'Send email password',
|
||||
notifications_send_email_password_desc:
|
||||
'Password for the email you will send from',
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ window.AdminPageLogic = {
|
|||
LNbits.api
|
||||
.request('GET', '/admin/api/v1/restart/')
|
||||
.then(response => {
|
||||
Quasar.Notify.create({
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! Restarted Server',
|
||||
icon: null
|
||||
|
|
@ -450,7 +450,29 @@ window.AdminPageLogic = {
|
|||
formatDate(date) {
|
||||
return moment(date * 1000).fromNow()
|
||||
},
|
||||
|
||||
sendTestEmail() {
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
'/admin/api/v1/testemail',
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
.then(response => {
|
||||
if (response.data.status === 'error') {
|
||||
throw new Error(response.data.message)
|
||||
}
|
||||
this.$q.notify({
|
||||
message: 'Test email sent!',
|
||||
color: 'positive'
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
this.$q.notify({
|
||||
message: error.message,
|
||||
color: 'negative'
|
||||
})
|
||||
})
|
||||
},
|
||||
getAudit() {
|
||||
LNbits.api
|
||||
.request('GET', '/admin/api/v1/audit', this.g.user.wallets[0].adminkey)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue