Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #5314 Email Address Friendly Name Error #5318

Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 99 additions & 6 deletions src/components/notifications/SendGrid.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,67 @@
<template>
<div class="mb-3">
<label for="sendgrid-api-key" class="form-label">{{ $t("SendGrid API Key") }}</label>
<HiddenInput id="push-api-key" v-model="$parent.notification.sendgridApiKey" :required="true" autocomplete="new-password"></HiddenInput>
<HiddenInput id="push-api-key" v-model="$parent.notification.sendgridApiKey" required autocomplete="new-password"></HiddenInput>
</div>
<div class="mb-3">
<label for="sendgrid-from-email" class="form-label">{{ $t("From Email") }}</label>
<input id="sendgrid-from-email" v-model="$parent.notification.sendgridFromEmail" type="email" class="form-control" required>
<input
id="sendgrid-from-email"
v-model="$parent.notification.sendgridFromEmail"
type="text"
class="form-control"
:class="{ 'is-invalid': errors.from }"
required
@input="validateEmail($event, 'from')"
>
<div v-if="errors.from" class="invalid-feedback">
{{ $t("Please use format: Friendly Name <email@domain.com> or just email@domain.com") }}
louislam marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
<div class="mb-3">
<label for="sendgrid-to-email" class="form-label">{{ $t("To Email") }}</label>
<input id="sendgrid-to-email" v-model="$parent.notification.sendgridToEmail" type="email" class="form-control" required>
<input
id="sendgrid-to-email"
v-model="$parent.notification.sendgridToEmail"
type="text"
class="form-control"
:class="{ 'is-invalid': errors.to }"
required
@input="validateEmail($event, 'to')"
>
<div v-if="errors.to" class="invalid-feedback">
{{ $t("Please use format: Friendly Name <email@domain.com> or just email@domain.com") }}
</div>
</div>
<div class="mb-3">
<label for="sendgrid-cc-email" class="form-label">{{ $t("smtpCC") }}</label>
<input id="sendgrid-cc-email" v-model="$parent.notification.sendgridCcEmail" type="email" class="form-control">
<input
id="sendgrid-cc-email"
v-model="$parent.notification.sendgridCcEmail"
type="text"
class="form-control"
:class="{ 'is-invalid': errors.cc }"
@input="validateEmail($event, 'cc')"
>
<div class="form-text">{{ $t("Separate multiple email addresses with commas") }}</div>
<div v-if="errors.cc" class="invalid-feedback">
{{ $t("Please use format: Friendly Name <email@domain.com> or just email@domain.com for each address") }}
</div>
</div>
<div class="mb-3">
<label for="sendgrid-bcc-email" class="form-label">{{ $t("smtpBCC") }}</label>
<input id="sendgrid-bcc-email" v-model="$parent.notification.sendgridBccEmail" type="email" class="form-control">
<small class="form-text text-muted">{{ $t("Separate multiple email addresses with commas") }}</small>
<input
id="sendgrid-bcc-email"
v-model="$parent.notification.sendgridBccEmail"
type="text"
class="form-control"
:class="{ 'is-invalid': errors.bcc }"
louislam marked this conversation as resolved.
Show resolved Hide resolved
@input="validateEmail($event, 'bcc')"
>
<div class="form-text">{{ $t("Separate multiple email addresses with commas") }}</div>
<div v-if="errors.bcc" class="invalid-feedback">
{{ $t("Please use format: Friendly Name <email@domain.com> or just email@domain.com for each address") }}
</div>
</div>
<div class="mb-3">
<label for="sendgrid-subject" class="form-label">{{ $t("Subject:") }}</label>
Expand All @@ -38,10 +80,61 @@ export default {
components: {
HiddenInput,
},

data() {
return {
errors: {
from: false,
to: false,
cc: false,
bcc: false
}
};
},

mounted() {
if (typeof this.$parent.notification.sendgridSubject === "undefined") {
this.$parent.notification.sendgridSubject = "Notification from Your Uptime Kuma";
}
},

methods: {
isValidEmailFormat(value) {
const friendlyEmailRegex = /^[^<>]+ <[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}>$/;
const emailOnlyRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
louislam marked this conversation as resolved.
Show resolved Hide resolved
return friendlyEmailRegex.test(value) || emailOnlyRegex.test(value);
},

validateEmail(event, field) {
const value = event.target.value;

if (!value) {
this.errors[field] = false;
return;
}

if (field === "cc" || field === "bcc") {
if (value.includes(",")) {
this.errors[field] = !value.split(",")
.map(email => email.trim())
.every(email => this.isValidEmailFormat(email));
return;
}
}

this.errors[field] = !this.isValidEmailFormat(value);
}
}
};
</script>

<style scoped>
.is-invalid {
border-color: #dc3545;
padding-right: calc(1.5em + 0.75rem);
louislam marked this conversation as resolved.
Show resolved Hide resolved
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
louislam marked this conversation as resolved.
Show resolved Hide resolved
}
</style>
Loading