Skip to content

Commit

Permalink
feat: added newsletter support check, cleanup alias form, fixed empty…
Browse files Browse the repository at this point in the history
… input error on encrypt, sync locales and updated snapshots
  • Loading branch information
titanism committed Aug 14, 2024
1 parent 585f025 commit 134454c
Show file tree
Hide file tree
Showing 36 changed files with 705 additions and 221 deletions.
6 changes: 5 additions & 1 deletion app/controllers/web/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ async function encryptTxt(ctx) {

ctx.request.body.input = ctx.request.body.input
.replace(/forward-email=/i, '')
.replace(/forward-email-port=/i, '');
.replace(/forward-email-port=/i, '')
.trim();

if (
ctx.request.body.input
Expand All @@ -28,6 +29,9 @@ async function encryptTxt(ctx) {
)
throw Boom.badRequest(ctx.translateError('INPUT_HAD_FE_SV'));

if (!isSANB(ctx.request.body.input))
throw Boom.badRequest(ctx.translateError('UNKNOWN_ERROR'));

const encryptedValue = encrypt(
ctx.request.body.input.trim(),
16,
Expand Down
7 changes: 7 additions & 0 deletions app/models/domains.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ Invite.plugin(mongooseCommonPlugin, {
});

const Domains = new mongoose.Schema({
has_newsletter: {
type: Boolean,
default: false,
index: true
},
newsletter_sent_at: Date,

// <https://github.com/forwardemail/free-email-forwarding/issues/235>
webhook_key: {
type: String
Expand Down
4 changes: 1 addition & 3 deletions app/views/guides/provider.pug
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,7 @@ block body
name="input",
value=user ? user.email : "[email protected]"
)
button.btn.btn-dark.btn-sm.mt-1(
type="submit"
)
button.btn.btn-dark.btn-sm.mt-1(type="submit")
i.fas.fa-user-secret
= " "
= t("Encrypt")
Expand Down
13 changes: 8 additions & 5 deletions app/views/my-account/domains/advanced-settings.pug
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,9 @@ block body
.card-body
+planRequired(false)
p.card-text
strong!= t('Need to verify that <a href="%s" target="_blank">webhooks</a> are sent by us?', l('/faq#do-you-support-webhooks'))
strong!= t('Need to verify that <a href="%s" target="_blank">webhooks</a> are sent by us?', l("/faq#do-you-support-webhooks"))
= " "
!= t('You can check that the remote server\'s IP address is one of ours listed under our public <a href="%s" target="_blank">IP Addresses</a> page.', l('/ips'))
!= t('You can check that the remote server\'s IP address is one of ours listed under our public <a href="%s" target="_blank">IP Addresses</a> page.', l("/ips"))
= " "
!= t("Additionally, you can also use this webhook key to compare the <code>X-Webhook-Signature</code> header with the computed payload body.")
= " "
Expand All @@ -478,7 +478,7 @@ block body
input#webhook-key.form-control(
type="text",
readonly,
value=domain.webhook_key ? decrypt(domain.webhook_key) : ''
value=domain.webhook_key ? decrypt(domain.webhook_key) : ""
)
.input-group-append
button.btn.btn-primary(
Expand All @@ -493,11 +493,14 @@ block body
.card-footer.text-right
ul.list-inline.mb-0
li.list-inline-item
form.ajax-form.confirm-prompt(action=l(`/my-account/domains/${domain.name}/advanced-settings/reset-domain-webhook-key`), method="POST")
form.ajax-form.confirm-prompt(
action=l(`/my-account/domains/${domain.name}/advanced-settings/reset-domain-webhook-key`),
method="POST"
)
input(type="hidden", name="_method", value="DELETE")
button.btn.btn-danger(type="submit")= t("Reset Key")
li.list-inline-item
a.btn.btn-dark(href=l('/faq#do-you-support-webhooks'))= t("Learn more")
a.btn.btn-dark(href=l("/faq#do-you-support-webhooks"))= t("Learn more")

//- Restricted Alias Names
if domain.group === 'admin'
Expand Down
144 changes: 76 additions & 68 deletions app/views/my-account/domains/aliases/_form.pug
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@ if alias
= " "
span.text-danger= t("(required)")
.input-group
.input-group-prepend
button.generate-random-alias.btn.btn-dark.border-themed(
data-target="#input-alias-name",
type="button",
data-toggle="tooltip",
title=t("Generate random alias")
)
i.fa.fa-dice
input#input-alias-name.form-control.border-themed(
input#input-alias-name.form-control.border-themed.d-flex(
required,
readonly=isUbuntuAlias && domain.group !== "admin",
value=alias ? alias.name : domain && domain.aliases && domain.aliases.length === 0 && isSANB(ctx.query.q) ? striptags(ctx.query.q).split("@")[0].toLowerCase().trim() : "",
Expand All @@ -33,25 +25,33 @@ if alias
.input-group-text.bg-dark.text-white.border-themed
if domain
input(type="hidden", name="domain", required, value=domain.id)
= `@${domain.name}`
small= `@${domain.name}`
else
i.fa.fa-at
small= "@"
if !domain || !domain.is_global
.alert.alert-secondary.small.text-center.mt-3
= t('Use an asterisk "*" for a catch-all alias.')
if !domain
= " "
= t("Catch-all aliases are not supported on vanity and disposable domains that we provide.")
= " "
!= t('We also support <a href="%s" target="_blank" class="alert-link">regular expressions</a>.', l("/faq#do-you-support-regular-expressions-or-regex"))
ul.list-inline.text-center.mb-0
li.list-inline-item
button.generate-random-alias.btn.btn-primary(
data-target="#input-alias-name",
type="button"
)
i.fa.fa-dice
= " "
= t("Generate random alias")
if domain
.input-group-append
li.list-inline-item
button.btn.btn-success(type="submit")
if alias
= t("Update Alias")
else
= t("Create Alias")
ul.list-inline
li.list-inline-item.small.text-black.text-themed-50
if !domain || !domain.is_global
= t('Use an asterisk "*" for a catch-all alias.')
if !domain
= " "
= t("Catch-all aliases are not supported on vanity and disposable domains that we provide.")
if !domain || !domain.is_global
li.list-inline-item.small.text-black.text-themed-50!= t('We also support <a href="%s" target="_blank">regular expressions</a>.', l("/faq#do-you-support-regular-expressions-or-regex"))
if !domain
.form-group.col-md-6
label(for="select-alias-domain")
Expand Down Expand Up @@ -102,31 +102,32 @@ if alias
= " "
= t("Add new domain")
if !domain || !domain.is_global && (!isUbuntuAlias || domain.group === 'admin')
.form-group
= "IMAP/POP3/CalDAV"
= " "
span.text-muted= t("(optional)")
.form-group.form-check
input#input-has-imap.form-check-input(
type="checkbox",
name="has_imap",
checked=alias ? alias.has_imap : false,
value="true"
)
label.form-check-label(for="input-has-imap")
= "IMAP/POP3/CalDAV"
= " "
span.text-muted= t("(optional)")
.alert.alert-success
.form-check.text-left.small
input#input-has-imap.form-check-input(
type="checkbox",
name="has_imap",
checked=alias ? alias.has_imap : false,
value="true"
)
label.form-check-label(for="input-has-imap")
!= t('This will enable <span class="notranslate">IMAP/POP3/CalDAV</span> for this alias.')
= " "
= t("You can have this and forwarding recipients enabled at the same time.")
= " "
!= t('If you would like to learn more about storage, please <a class="alert-link" href="%s" target="_blank">click here to read our deep dive on Encrypted Email.</a>', l("/blog/docs/best-quantum-safe-encrypted-email-service"))
strong= t("Recommended:")
= " "
!= t('This will enable <span class="notranslate">IMAP/POP3/CalDAV</span> for this alias.')
= " "
= t("You can have this and forwarding recipients enabled at the same time.")
= " "
!= t('If you would like to learn more about storage, please <a class="alert-link" href="%s" target="_blank">click here to read our deep dive on Encrypted Email.</a>', l("/blog/docs/best-quantum-safe-encrypted-email-service"))
.form-group
label(for="textarea-alias-recipients")
= t("Forwarding Recipients")
= " "
span.text-muted= t("(optional)")
textarea#textarea-alias-recipients.form-control(name="recipients", rows=1)= alias && Array.isArray(alias.recipients) ? alias.recipients.join(", ") : user.email
p.form-text.small.text-black.text-themed-50
.alert.alert-secondary.small.mt-3
if alias
= t('Recipients must be a line-break/space/comma separated list of valid email addresses, fully-qualified domain names ("FQDN"), IP addresses, and/or webhook URL\'s. We will automatically remove duplicate entries for you and perform validation when you click "Update Alias" below.')
else
Expand All @@ -143,14 +144,16 @@ if !domain || !domain.is_global && (!isUbuntuAlias || domain.group === 'admin')
maxlength=150,
rows=1
)= alias ? alias.description : ""
p.form-text.small.text-black.text-themed-50= t("Description has a max of 150 characters.")
.alert.alert-secondary.small.mt-3
= t("Description has a max of 150 characters.")
.form-group
label(for="input-alias-labels")
= t("Labels")
= " "
span.text-muted= "(optional; for organization purposes only)"
textarea#input-alias-labels.form-control(name="labels", rows=1)= alias && Array.isArray(alias.labels) ? _.without(alias.labels, "catch-all").join(", ") : ""
p.form-text.small.text-black.text-themed-50= t("Labels must be a line-break/space/comma separated list with a maximum of 20 characters per label.")
.alert.alert-secondary.small.mt-3
= t("Labels must be a line-break/space/comma separated list with a maximum of 20 characters per label.")
if !domain || (domain && !domain.is_global)
.form-group.form-check
input#input-has-recipient-verification.form-check-input(
Expand All @@ -159,20 +162,29 @@ if !domain || (domain && !domain.is_global)
value="true",
checked=alias ? alias.has_recipient_verification : domain && domain.has_recipient_verification
)
label.form-check-label(for="input-has-recipient-verification")= t("Requires recipients to click email verification link")
p.form-text.small.text-black.text-themed-50= t("If you check this, then each forwarding recipient will be required to click an email verification link in order for emails to flow through.")
label.form-check-label(for="input-has-recipient-verification")
= t("Requires recipients to click email verification link")
= " "
span.text-muted= t("(optional)")
.alert.alert-warning.small.mt-3
= t("If you check this, then each forwarding recipient will be required to click an email verification link in order for emails to flow through.")
.form-group.form-check
input#input-is-enabled.form-check-input(
type="checkbox",
name="is_enabled",
value="true",
checked=alias ? alias.is_enabled : true
)
label.form-check-label(for="input-is-enabled")= t("Active")
p.form-text.small.text-black.text-themed-50= t("If you uncheck this, then this email will be deactivated and no emails will flow through. However emails will NOT bounce until this alias is completely deleted.")
label.form-check-label(for="input-is-enabled")
= t("Active")
= " "
span.text-muted= t("(optional)")
.alert.alert-warning.small.mt-3
= t("If you uncheck this, then this email will be deactivated and no emails will flow through.")
//- error_code_if_disabled
.form-group
label(for="select-error-code-if-disabled")= t("If the alias is not active (disabled), then this error code will be returned when a sender attempts to send email to this alias.")
label(for="select-error-code-if-disabled")
= t("If not active, then this error code will be used:")
select#select-error-code-if-disabled.form-control(
name="error_code_if_disabled"
)
Expand Down Expand Up @@ -200,32 +212,28 @@ if !domain || !domain.is_global && (!isUbuntuAlias || domain.group === 'admin')
= t("OpenPGP for Storage")
= " "
span.text-muted= t("(optional)")
= " "
span.badge.badge-success= t("New")
p.form-text.small.text-black.text-themed-50
.alert.alert-warning.small.mt-3
!= t('Our storage is already encrypted using ChaCha20-Poly1305 encryption. However if you\'d like double the level of encryption, then if you have <span class="notranslate">IMAP/POP3/CalDAV</span> enabled and if you also check this, then all future emails stored will also be encrypted with the public key below.')
= " "
!= t('If this is checked and no public key is entered below, then we will attempt to perform a lookup <a href="%s" target="_blank">using Web Key Directory</a> ("WKD").', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
!= t('If this is checked and no public key is entered below, then we will attempt to perform a lookup <a href="%s" target="_blank" class="alert-link">using Web Key Directory</a> ("WKD").', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
label(for="textarea-public-key")
= t('End-to-end Encryption ("E2EE")')
= t("OpenPGP Public Key for E2EE")
= " "
span.text-muted= t("(optional)")
= " "
span.badge.badge-success= t("New")
p.form-text.small.text-black.text-themed-50
!= t('Please enter your optional OpenPGP public key below in ASCII Armor format. This feature enables you to use end-to-end encryption ("E2EE") with <a href="%s" target="_blank">supported email clients</a> and recipients.', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
= " "
!= t('<strong class="text-decoration-underline">This assumes you have already <a href="%s" target="_blank">followed our instructions</a></strong> and <a href="https://keys.openpgp.org/upload" target="_blank">uploaded your public key to the keys.openpgp.org server</a> (or are self-hosting).', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
ul.list-inline.mb-3
li.list-inline-item
a.btn.btn-success.btn-sm(
href=l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"),
target="_blank"
)= t("Learn more")
li.list-inline-item
a.btn.btn-primary.btn-sm(
href="/.well-known/openpgpkey/hu/mxqp8ogw4jfq83a58pn1wy1ccc1cx3f5.txt",
target="_blank"
)= t("View Example")
.form-group
textarea#textarea-public-key.form-control(name="public_key", rows=3)= alias && alias.public_key ? alias.public_key : ""
.alert.alert-secondary.small
!= t('Please enter your optional OpenPGP public key above in ASCII Armor format. This feature enables you to use end-to-end encryption ("E2EE") with <a href="%s" target="_blank" class="alert-link">supported email clients</a> and recipients.', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
= " "
!= t('<strong class="text-decoration-underline">This assumes you have already <a href="%s" target="_blank" class="alert-link">followed our instructions</a></strong> and <a href="https://keys.openpgp.org/upload" target="_blank" class="alert-link">uploaded your public key to the keys.openpgp.org server</a> (or are self-hosting).', l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"))
ul.list-inline.mt-1.mb-0
li.list-inline-item
a.btn.btn-success.btn-sm(
href=l("/faq#do-you-support-openpgpmime-end-to-end-encryption-e2ee-and-web-key-directory-wkd"),
target="_blank"
)= t("Learn more")
li.list-inline-item
a.btn.btn-primary.btn-sm(
href="/.well-known/openpgpkey/hu/mxqp8ogw4jfq83a58pn1wy1ccc1cx3f5.txt",
target="_blank"
)= t("View Example")
20 changes: 6 additions & 14 deletions app/views/my-account/domains/aliases/_table.pug
Original file line number Diff line number Diff line change
Expand Up @@ -223,29 +223,23 @@ p.text-center.d-lg-none
name="format",
value="eml"
)
label.form-check-label(
for="input-radio-eml"
)= t("EML")
label.form-check-label(for="input-radio-eml")= t("EML")
.form-check
input#input-radio-mbox.form-check-input(
type="radio",
required,
name="format",
value="mbox"
)
label.form-check-label(
for="input-radio-eml"
)= t("MBOX")
label.form-check-label(for="input-radio-eml")= t("MBOX")
.form-check
input#input-radio-sqlite.form-check-input(
type="radio",
required,
name="format",
value="sqlite"
)
label.form-check-label(
for="input-radio-sqlite"
)
label.form-check-label(for="input-radio-sqlite")
= t("SQLite")
= " "
= "("
Expand All @@ -254,10 +248,10 @@ p.text-center.d-lg-none
.small.help-text.text-muted
= t("Note that after downloading this SQLite file, you will need to download and install this open-source software to decrypt and open it:")
= " "
a(
a.alert-link(
href="https://github.com/pawelsalawa/sqlitestudio",
target="_blank"
).alert-link= "SQLiteStudio"
)= "SQLiteStudio"
= " "
!= t('After opening SQLiteStudio, you must select <span class="notranslate">"WxSQLite3"</span> as the database type and use <span class="notranslate">"sqleet"</span> cipher to decrypt it using your password.')
p.font-weight-bold.lead= t("Enter current password to get a new backup:")
Expand Down Expand Up @@ -298,9 +292,7 @@ p.text-center.d-lg-none
.modal-dialog.modal-lg(role="document")
.modal-content
.modal-header.text-center.d-block
h4.d-inline-block.ml-4(
id=`modal-qrcode-${alias.id}-title`
)= t("Get QR Code for Device Provisioning")
h4.d-inline-block.ml-4(id=`modal-qrcode-${alias.id}-title`)= t("Get QR Code for Device Provisioning")
button.close(
type="button",
data-dismiss="modal",
Expand Down
11 changes: 0 additions & 11 deletions app/views/my-account/domains/aliases/form.pug
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,6 @@ block body
.col
include ../../../_breadcrumbs
.container.py-3
if domain && domain.group === 'admin' && !alias
.row.text-center.my-2
.col
form.ajax-form.confirm-prompt.d-inline-block(
action=l(`/my-account/domains/${domain.name}/aliases/import`),
method="POST"
)
button.btn.btn-lg.btn-dark(type="submit")
!= t('Import <span class="notranslate">TXT</span> Records')
= " "
i.fa.fa-cloud-download-alt
.row
.col
.card.border-themed
Expand Down
Loading

0 comments on commit 134454c

Please sign in to comment.