Compare commits
14 commits
Author | SHA1 | Date | |
---|---|---|---|
|
5d41d1961d | ||
|
8bd409148e | ||
|
93c753c0c1 | ||
|
fa74cc1c41 | ||
|
216846c546 | ||
|
a96b243058 | ||
|
0289c01d10 | ||
|
e492310593 | ||
|
c78501432d | ||
|
d720b43fe5 | ||
|
9470b87ddf | ||
|
e96ea44e44 | ||
|
bde99cd3c4 | ||
|
23ce73d2e7 |
37 changed files with 283 additions and 28 deletions
|
@ -191,6 +191,19 @@ func handleBounceWebhook(c echo.Context) error {
|
||||||
}
|
}
|
||||||
bounces = append(bounces, bs...)
|
bounces = append(bounces, bs...)
|
||||||
|
|
||||||
|
// Postmark.
|
||||||
|
case service == "postmark" && app.constants.BouncePostmarkEnabled:
|
||||||
|
bs, err := app.bounce.Postmark.ProcessBounce(rawReq, c)
|
||||||
|
if err != nil {
|
||||||
|
app.log.Printf("error processing postmark notification: %v", err)
|
||||||
|
if _, ok := err.(*echo.HTTPError); ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidData"))
|
||||||
|
}
|
||||||
|
bounces = append(bounces, bs...)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("bounces.unknownService"))
|
return echo.NewHTTPError(http.StatusBadRequest, app.i18n.Ts("bounces.unknownService"))
|
||||||
}
|
}
|
||||||
|
|
13
cmd/init.go
13
cmd/init.go
|
@ -103,6 +103,7 @@ type constants struct {
|
||||||
BounceWebhooksEnabled bool
|
BounceWebhooksEnabled bool
|
||||||
BounceSESEnabled bool
|
BounceSESEnabled bool
|
||||||
BounceSendgridEnabled bool
|
BounceSendgridEnabled bool
|
||||||
|
BouncePostmarkEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type notifTpls struct {
|
type notifTpls struct {
|
||||||
|
@ -400,6 +401,8 @@ func initConstants() *constants {
|
||||||
c.BounceWebhooksEnabled = ko.Bool("bounce.webhooks_enabled")
|
c.BounceWebhooksEnabled = ko.Bool("bounce.webhooks_enabled")
|
||||||
c.BounceSESEnabled = ko.Bool("bounce.ses_enabled")
|
c.BounceSESEnabled = ko.Bool("bounce.ses_enabled")
|
||||||
c.BounceSendgridEnabled = ko.Bool("bounce.sendgrid_enabled")
|
c.BounceSendgridEnabled = ko.Bool("bounce.sendgrid_enabled")
|
||||||
|
c.BouncePostmarkEnabled = ko.Bool("bounce.postmark.enabled")
|
||||||
|
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +671,15 @@ func initBounceManager(app *App) *bounce.Manager {
|
||||||
SESEnabled: ko.Bool("bounce.ses_enabled"),
|
SESEnabled: ko.Bool("bounce.ses_enabled"),
|
||||||
SendgridEnabled: ko.Bool("bounce.sendgrid_enabled"),
|
SendgridEnabled: ko.Bool("bounce.sendgrid_enabled"),
|
||||||
SendgridKey: ko.String("bounce.sendgrid_key"),
|
SendgridKey: ko.String("bounce.sendgrid_key"),
|
||||||
|
Postmark: struct {
|
||||||
|
Enabled bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}{
|
||||||
|
ko.Bool("bounce.postmark.enabled"),
|
||||||
|
ko.String("bounce.postmark.username"),
|
||||||
|
ko.String("bounce.postmark.password"),
|
||||||
|
},
|
||||||
RecordBounceCB: app.core.RecordBounce,
|
RecordBounceCB: app.core.RecordBounce,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ func handleGetSettings(c echo.Context) error {
|
||||||
s.UploadS3AwsSecretAccessKey = strings.Repeat(pwdMask, utf8.RuneCountInString(s.UploadS3AwsSecretAccessKey))
|
s.UploadS3AwsSecretAccessKey = strings.Repeat(pwdMask, utf8.RuneCountInString(s.UploadS3AwsSecretAccessKey))
|
||||||
s.SendgridKey = strings.Repeat(pwdMask, utf8.RuneCountInString(s.SendgridKey))
|
s.SendgridKey = strings.Repeat(pwdMask, utf8.RuneCountInString(s.SendgridKey))
|
||||||
s.SecurityCaptchaSecret = strings.Repeat(pwdMask, utf8.RuneCountInString(s.SecurityCaptchaSecret))
|
s.SecurityCaptchaSecret = strings.Repeat(pwdMask, utf8.RuneCountInString(s.SecurityCaptchaSecret))
|
||||||
|
s.BouncePostmark.Password = strings.Repeat(pwdMask, utf8.RuneCountInString(s.BouncePostmark.Password))
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{s})
|
return c.JSON(http.StatusOK, okResp{s})
|
||||||
}
|
}
|
||||||
|
@ -183,6 +184,9 @@ func handleUpdateSettings(c echo.Context) error {
|
||||||
if set.SendgridKey == "" {
|
if set.SendgridKey == "" {
|
||||||
set.SendgridKey = cur.SendgridKey
|
set.SendgridKey = cur.SendgridKey
|
||||||
}
|
}
|
||||||
|
if set.BouncePostmark.Password == "" {
|
||||||
|
set.BouncePostmark.Password = cur.BouncePostmark.Password
|
||||||
|
}
|
||||||
if set.SecurityCaptchaSecret == "" {
|
if set.SecurityCaptchaSecret == "" {
|
||||||
set.SecurityCaptchaSecret = cur.SecurityCaptchaSecret
|
set.SecurityCaptchaSecret = cur.SecurityCaptchaSecret
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ var migList = []migFunc{
|
||||||
{"v2.3.0", migrations.V2_3_0},
|
{"v2.3.0", migrations.V2_3_0},
|
||||||
{"v2.4.0", migrations.V2_4_0},
|
{"v2.4.0", migrations.V2_4_0},
|
||||||
{"v2.5.0", migrations.V2_5_0},
|
{"v2.5.0", migrations.V2_5_0},
|
||||||
|
{"v2.6.0", migrations.V2_6_0},
|
||||||
}
|
}
|
||||||
|
|
||||||
// upgrade upgrades the database to the current version by running SQL migration files
|
// upgrade upgrades the database to the current version by running SQL migration files
|
||||||
|
|
|
@ -18,12 +18,12 @@ Some mail servers may also return the bounce to the `Reply-To` address, which ca
|
||||||
The bounce webhook API can be used to record bounce events with custom scripting. This could be by reading a mailbox, a database, or mail server logs.
|
The bounce webhook API can be used to record bounce events with custom scripting. This could be by reading a mailbox, a database, or mail server logs.
|
||||||
|
|
||||||
| Method | Endpoint | Description |
|
| Method | Endpoint | Description |
|
||||||
|--------|------------------|------------------------|
|
| ------ | ---------------- | ---------------------- |
|
||||||
| `POST` | /webhooks/bounce | Record a bounce event. |
|
| `POST` | /webhooks/bounce | Record a bounce event. |
|
||||||
|
|
||||||
|
|
||||||
| Name | Data type | Required/Optional | Description |
|
| Name | Data type | Required/Optional | Description |
|
||||||
|-------------------|-----------|-------------------|--------------------------------------------------------------------------------------|
|
| ----------------- | --------- | ----------------- | ------------------------------------------------------------------------------------ |
|
||||||
| `subscriber_uuid` | String | Optional | The UUID of the subscriber. Either this or `email` is required. |
|
| `subscriber_uuid` | String | Optional | The UUID of the subscriber. Either this or `email` is required. |
|
||||||
| `email` | String | Optional | The e-mail of the subscriber. Either this or `subscriber_uuid` is required. |
|
| `email` | String | Optional | The e-mail of the subscriber. Either this or `subscriber_uuid` is required. |
|
||||||
| `campaign_uuid` | String | Optional | UUID of the campaign for which the bounce happened. |
|
| `campaign_uuid` | String | Optional | UUID of the campaign for which the bounce happened. |
|
||||||
|
@ -46,7 +46,7 @@ listmonk supports receiving bounce webhook events from the following SMTP provid
|
||||||
|-----------------------------|------------------|-----------|
|
|-----------------------------|------------------|-----------|
|
||||||
| `https://listmonk.yoursite.com/webhooks/service/ses` | Amazon (AWS) SES | You can use these [Mautic steps](https://docs.mautic.org/en/channels/emails/bounce-management#amazon-webhook) as a general guide, but use your listmonk's endpoint instead. <ul> <li>When creating the *topic* select "standard" instead of the preselected "FIFO". You can put a name and leave everything else at default.</li> <li>When creating a *subscription* choose HTTPS for "Protocol", and leave *"Enable raw message delivery"* UNCHECKED.</li> <li>On the _"SES -> verified identities"_ page, make sure to check **"[include original headers](https://github.com/knadh/listmonk/issues/720#issuecomment-1046877192)"**.</li> <li>The Mautic screenshot suggests you should turn off _email feedback forwarding_, but that's completely optional depending on whether you want want email notifications.</li></ul> |
|
| `https://listmonk.yoursite.com/webhooks/service/ses` | Amazon (AWS) SES | You can use these [Mautic steps](https://docs.mautic.org/en/channels/emails/bounce-management#amazon-webhook) as a general guide, but use your listmonk's endpoint instead. <ul> <li>When creating the *topic* select "standard" instead of the preselected "FIFO". You can put a name and leave everything else at default.</li> <li>When creating a *subscription* choose HTTPS for "Protocol", and leave *"Enable raw message delivery"* UNCHECKED.</li> <li>On the _"SES -> verified identities"_ page, make sure to check **"[include original headers](https://github.com/knadh/listmonk/issues/720#issuecomment-1046877192)"**.</li> <li>The Mautic screenshot suggests you should turn off _email feedback forwarding_, but that's completely optional depending on whether you want want email notifications.</li></ul> |
|
||||||
| `https://listmonk.yoursite.com/webhooks/service/sendgrid` | Sendgrid / Twilio Signed event webhook | [More info](https://docs.sendgrid.com/for-developers/tracking-events/getting-started-event-webhook-security-features) |
|
| `https://listmonk.yoursite.com/webhooks/service/sendgrid` | Sendgrid / Twilio Signed event webhook | [More info](https://docs.sendgrid.com/for-developers/tracking-events/getting-started-event-webhook-security-features) |
|
||||||
|
| `https://listmonk.yoursite.com/webhooks/service/postmark` | Postmark webhook | [More info](https://postmarkapp.com/developer/webhooks/webhooks-overview)
|
||||||
|
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
|
@ -2703,6 +2703,8 @@ components:
|
||||||
type: string
|
type: string
|
||||||
settings.bounces.enableSendgrid:
|
settings.bounces.enableSendgrid:
|
||||||
type: string
|
type: string
|
||||||
|
settings.bounces.enablePostmark:
|
||||||
|
type: string
|
||||||
settings.bounces.enableWebhooks:
|
settings.bounces.enableWebhooks:
|
||||||
type: string
|
type: string
|
||||||
settings.bounces.enabled:
|
settings.bounces.enabled:
|
||||||
|
@ -2721,6 +2723,12 @@ components:
|
||||||
type: string
|
type: string
|
||||||
settings.bounces.sendgridKey:
|
settings.bounces.sendgridKey:
|
||||||
type: string
|
type: string
|
||||||
|
settings.bounces.postmarkUsername:
|
||||||
|
type: string
|
||||||
|
settings.bounces.postmarkUsernameHelp:
|
||||||
|
type: string
|
||||||
|
settings.bounces.postmarkPassword:
|
||||||
|
type: string
|
||||||
settings.bounces.type:
|
settings.bounces.type:
|
||||||
type: string
|
type: string
|
||||||
settings.bounces.username:
|
settings.bounces.username:
|
||||||
|
@ -3398,6 +3406,12 @@ components:
|
||||||
type: boolean
|
type: boolean
|
||||||
bounce.sendgrid_key:
|
bounce.sendgrid_key:
|
||||||
type: string
|
type: string
|
||||||
|
bounce.postmark_enabled:
|
||||||
|
type: boolean
|
||||||
|
bounce.postmark_username:
|
||||||
|
type: string
|
||||||
|
bounce.postmark_password:
|
||||||
|
type: string
|
||||||
bounce.mailboxes:
|
bounce.mailboxes:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
|
|
@ -155,6 +155,12 @@ export default Vue.extend({
|
||||||
hasDummy = 'captcha';
|
hasDummy = 'captcha';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isDummy(form['bounce.postmark'].password)) {
|
||||||
|
form['bounce.postmark'].password = '';
|
||||||
|
} else if (this.hasDummy(form['bounce.postmark'].password)) {
|
||||||
|
hasDummy = 'postmark';
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < form.messengers.length; i += 1) {
|
for (let i = 0; i < form.messengers.length; i += 1) {
|
||||||
// If it's the dummy UI password placeholder, ignore it.
|
// If it's the dummy UI password placeholder, ignore it.
|
||||||
if (this.isDummy(form.messengers[i].password)) {
|
if (this.isDummy(form.messengers[i].password)) {
|
||||||
|
|
|
@ -73,6 +73,33 @@
|
||||||
</b-field>
|
</b-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column is-3">
|
||||||
|
<b-field :label="$t('settings.bounces.enablePostmark')">
|
||||||
|
<b-switch v-model="data['bounce.postmark'].enabled"
|
||||||
|
name="postmark_enabled" :native-value="true"
|
||||||
|
data-cy="btn-enable-bounce-postmark" />
|
||||||
|
</b-field>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<b-field :label="$t('settings.bounces.postmarkUsername')"
|
||||||
|
:message="$t('settings.bounces.postmarkUsernameHelp')">
|
||||||
|
<b-input v-model="data['bounce.postmark'].username" type="text"
|
||||||
|
:disabled="!data['bounce.postmark'].enabled"
|
||||||
|
name="postmark_username"
|
||||||
|
data-cy="btn-enable-bounce-postmark" />
|
||||||
|
</b-field>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<b-field :label="$t('settings.bounces.postmarkPassword')"
|
||||||
|
:message="$t('globals.messages.passwordChange')">
|
||||||
|
<b-input v-model="data['bounce.postmark'].password" type="password"
|
||||||
|
:disabled="!data['bounce.postmark'].enabled"
|
||||||
|
name="postmark_password"
|
||||||
|
data-cy="btn-enable-bounce-postmark" />
|
||||||
|
</b-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Activa SES",
|
"settings.bounces.enableSES": "Activa SES",
|
||||||
"settings.bounces.enableSendgrid": "Activa SendGrid",
|
"settings.bounces.enableSendgrid": "Activa SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Activa els webhooks pels rebots",
|
"settings.bounces.enableWebhooks": "Activa els webhooks pels rebots",
|
||||||
|
"settings.bounces.enablePostmark": "Activa Postmark",
|
||||||
"settings.bounces.enabled": "Activat",
|
"settings.bounces.enabled": "Activat",
|
||||||
"settings.bounces.folder": "Carpeta",
|
"settings.bounces.folder": "Carpeta",
|
||||||
"settings.bounces.folderHelp": "Nom de la carpeta IMAP a escanejar. Ex: Safata d'entrada.",
|
"settings.bounces.folderHelp": "Nom de la carpeta IMAP a escanejar. Ex: Safata d'entrada.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Assumpte",
|
"templates.subject": "Assumpte",
|
||||||
"users.login": "Inicia sessió",
|
"users.login": "Inicia sessió",
|
||||||
"users.logout": "Tanca sessió"
|
"users.logout": "Tanca sessió"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Povolit SES",
|
"settings.bounces.enableSES": "Povolit SES",
|
||||||
"settings.bounces.enableSendgrid": "Povolit SendGrid",
|
"settings.bounces.enableSendgrid": "Povolit SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Povolit webhooky v případě nedoručitelnosti",
|
"settings.bounces.enableWebhooks": "Povolit webhooky v případě nedoručitelnosti",
|
||||||
|
"settings.bounces.enablePostmark": "Povolit Postmark",
|
||||||
"settings.bounces.enabled": "Povoleno",
|
"settings.bounces.enabled": "Povoleno",
|
||||||
"settings.bounces.folder": "Složka",
|
"settings.bounces.folder": "Složka",
|
||||||
"settings.bounces.folderHelp": "Název složky IMAP ke skenování. Např.: Došlá pošta.",
|
"settings.bounces.folderHelp": "Název složky IMAP ke skenování. Např.: Došlá pošta.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Předmět",
|
"templates.subject": "Předmět",
|
||||||
"users.login": "Přihlásit",
|
"users.login": "Přihlásit",
|
||||||
"users.logout": "Odhlásit"
|
"users.logout": "Odhlásit"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Galluogi SES",
|
"settings.bounces.enableSES": "Galluogi SES",
|
||||||
"settings.bounces.enableSendgrid": "Galluogi SendGrid",
|
"settings.bounces.enableSendgrid": "Galluogi SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Galluogi bachau gwe sydd wedi sboncio'n ôl",
|
"settings.bounces.enableWebhooks": "Galluogi bachau gwe sydd wedi sboncio'n ôl",
|
||||||
|
"settings.bounces.enablePostmark": "Galluogi Postmark",
|
||||||
"settings.bounces.enabled": "Wedi galluogi",
|
"settings.bounces.enabled": "Wedi galluogi",
|
||||||
"settings.bounces.folder": "Ffolder",
|
"settings.bounces.folder": "Ffolder",
|
||||||
"settings.bounces.folderHelp": "Enw'r ffolder IMAP i'w sganio. ee: blwch derbyn.",
|
"settings.bounces.folderHelp": "Enw'r ffolder IMAP i'w sganio. ee: blwch derbyn.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Pwnc",
|
"templates.subject": "Pwnc",
|
||||||
"users.login": "Mewngofnodi",
|
"users.login": "Mewngofnodi",
|
||||||
"users.logout": "Allgofnodi"
|
"users.logout": "Allgofnodi"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "SES aktivieren",
|
"settings.bounces.enableSES": "SES aktivieren",
|
||||||
"settings.bounces.enableSendgrid": "SendGrid aktivieren",
|
"settings.bounces.enableSendgrid": "SendGrid aktivieren",
|
||||||
"settings.bounces.enableWebhooks": "Bounce-Webhooks aktivieren",
|
"settings.bounces.enableWebhooks": "Bounce-Webhooks aktivieren",
|
||||||
|
"settings.bounces.enablePostmark": "Postmark aktivieren",
|
||||||
"settings.bounces.enabled": "Aktiviert",
|
"settings.bounces.enabled": "Aktiviert",
|
||||||
"settings.bounces.folder": "Ordner",
|
"settings.bounces.folder": "Ordner",
|
||||||
"settings.bounces.folderHelp": "Name des zu scannenden IMAP-Ordners. z.B.: Inbox.",
|
"settings.bounces.folderHelp": "Name des zu scannenden IMAP-Ordners. z.B.: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Betreff",
|
"templates.subject": "Betreff",
|
||||||
"users.login": "Anmelden",
|
"users.login": "Anmelden",
|
||||||
"users.logout": "Abmelden"
|
"users.logout": "Abmelden"
|
||||||
}
|
}
|
|
@ -363,6 +363,7 @@
|
||||||
"settings.bounces.enableSES": "Enable SES",
|
"settings.bounces.enableSES": "Enable SES",
|
||||||
"settings.bounces.enableSendgrid": "Enable SendGrid",
|
"settings.bounces.enableSendgrid": "Enable SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Enable bounce webhooks",
|
"settings.bounces.enableWebhooks": "Enable bounce webhooks",
|
||||||
|
"settings.bounces.enablePostmark": "Enable Postmark",
|
||||||
"settings.bounces.enabled": "Enabled",
|
"settings.bounces.enabled": "Enabled",
|
||||||
"settings.bounces.folder": "Folder",
|
"settings.bounces.folder": "Folder",
|
||||||
"settings.bounces.folderHelp": "Name of the IMAP folder to scan. Eg: Inbox.",
|
"settings.bounces.folderHelp": "Name of the IMAP folder to scan. Eg: Inbox.",
|
||||||
|
@ -372,6 +373,9 @@
|
||||||
"settings.bounces.scanInterval": "Scan interval",
|
"settings.bounces.scanInterval": "Scan interval",
|
||||||
"settings.bounces.scanIntervalHelp": "Interval at which the bounce mailbox should be scanned for bounces (s for second, m for minute).",
|
"settings.bounces.scanIntervalHelp": "Interval at which the bounce mailbox should be scanned for bounces (s for second, m for minute).",
|
||||||
"settings.bounces.sendgridKey": "SendGrid Key",
|
"settings.bounces.sendgridKey": "SendGrid Key",
|
||||||
|
"settings.bounces.postmarkUsername": "Postmark Username",
|
||||||
|
"settings.bounces.postmarkUsernameHelp": "Postmark allows you to enable basic authorization for webhooks. Make sure to enter the same credentials here and in your Postmark webhook settings.",
|
||||||
|
"settings.bounces.postmarkPassword": "Postmark Password",
|
||||||
"settings.bounces.type": "Type",
|
"settings.bounces.type": "Type",
|
||||||
"settings.bounces.username": "Username",
|
"settings.bounces.username": "Username",
|
||||||
"settings.confirmRestart": "Ensure running campaigns are paused. Restart?",
|
"settings.confirmRestart": "Ensure running campaigns are paused. Restart?",
|
||||||
|
@ -573,4 +577,4 @@
|
||||||
"templates.subject": "Subject",
|
"templates.subject": "Subject",
|
||||||
"users.login": "Login",
|
"users.login": "Login",
|
||||||
"users.logout": "Logout"
|
"users.logout": "Logout"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "Activar SES",
|
"settings.bounces.enableSES": "Activar SES",
|
||||||
"settings.bounces.enableSendgrid": "Activar SendGrid",
|
"settings.bounces.enableSendgrid": "Activar SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Activar webhooks de rebotes",
|
"settings.bounces.enableWebhooks": "Activar webhooks de rebotes",
|
||||||
|
"settings.bounces.enablePostmark": "Activar Postmark",
|
||||||
"settings.bounces.enabled": "Activado",
|
"settings.bounces.enabled": "Activado",
|
||||||
"settings.bounces.folder": "Carpeta",
|
"settings.bounces.folder": "Carpeta",
|
||||||
"settings.bounces.folderHelp": "Nombre de la carpeta IMAP a escanear, por ejemplo: Entrada.",
|
"settings.bounces.folderHelp": "Nombre de la carpeta IMAP a escanear, por ejemplo: Entrada.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Asunto",
|
"templates.subject": "Asunto",
|
||||||
"users.login": "Ingresar",
|
"users.login": "Ingresar",
|
||||||
"users.logout": "Salir"
|
"users.logout": "Salir"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableMailbox": "Ota käyttöön bounce-postilaatikko",
|
"settings.bounces.enableMailbox": "Ota käyttöön bounce-postilaatikko",
|
||||||
"settings.bounces.enableSES": "Ota käyttöön SES",
|
"settings.bounces.enableSES": "Ota käyttöön SES",
|
||||||
"settings.bounces.enableSendgrid": "Ota käyttöön SendGrid",
|
"settings.bounces.enableSendgrid": "Ota käyttöön SendGrid",
|
||||||
|
"settings.bounces.enablePostmark": "Ota käyttöön Postmark",
|
||||||
"settings.bounces.enableWebhooks": "Ota käyttöön palautusten webhookit",
|
"settings.bounces.enableWebhooks": "Ota käyttöön palautusten webhookit",
|
||||||
"settings.bounces.enabled": "Käytössä",
|
"settings.bounces.enabled": "Käytössä",
|
||||||
"settings.bounces.folder": "Kansio",
|
"settings.bounces.folder": "Kansio",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Aihe",
|
"templates.subject": "Aihe",
|
||||||
"users.login": "Kirjaudu sisään",
|
"users.login": "Kirjaudu sisään",
|
||||||
"users.logout": "Kirjaudu ulos"
|
"users.logout": "Kirjaudu ulos"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "Activer SES",
|
"settings.bounces.enableSES": "Activer SES",
|
||||||
"settings.bounces.enableSendgrid": "Activer SendGrid",
|
"settings.bounces.enableSendgrid": "Activer SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Activez les 'webhooks' de rebond",
|
"settings.bounces.enableWebhooks": "Activez les 'webhooks' de rebond",
|
||||||
|
"settings.bounces.enablePostmark": "Activer Postmark",
|
||||||
"settings.bounces.enabled": "Activer",
|
"settings.bounces.enabled": "Activer",
|
||||||
"settings.bounces.folder": "Dossier",
|
"settings.bounces.folder": "Dossier",
|
||||||
"settings.bounces.folderHelp": "Nom du dossier IMAP à scanner. Exple : InBox.",
|
"settings.bounces.folderHelp": "Nom du dossier IMAP à scanner. Exple : InBox.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Objet",
|
"templates.subject": "Objet",
|
||||||
"users.login": "Connecter",
|
"users.login": "Connecter",
|
||||||
"users.logout": "Déconnecter"
|
"users.logout": "Déconnecter"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "SES",
|
"settings.bounces.enableSES": "SES",
|
||||||
"settings.bounces.enableSendgrid": "SendGrid",
|
"settings.bounces.enableSendgrid": "SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Visszapattanó webhook",
|
"settings.bounces.enableWebhooks": "Visszapattanó webhook",
|
||||||
|
"settings.bounces.enablePostmark": "Postmark",
|
||||||
"settings.bounces.enabled": "Engedélyezve",
|
"settings.bounces.enabled": "Engedélyezve",
|
||||||
"settings.bounces.folder": "Mappa",
|
"settings.bounces.folder": "Mappa",
|
||||||
"settings.bounces.folderHelp": "A vizsgálandó IMAP mappa neve. Például: 'Inbox'",
|
"settings.bounces.folderHelp": "A vizsgálandó IMAP mappa neve. Például: 'Inbox'",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Tárgy",
|
"templates.subject": "Tárgy",
|
||||||
"users.login": "Belépés",
|
"users.login": "Belépés",
|
||||||
"users.logout": "Kijelentkezés"
|
"users.logout": "Kijelentkezés"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "Attiva SES",
|
"settings.bounces.enableSES": "Attiva SES",
|
||||||
"settings.bounces.enableSendgrid": "Attiva SendGrid",
|
"settings.bounces.enableSendgrid": "Attiva SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Attiva bounce webhooks",
|
"settings.bounces.enableWebhooks": "Attiva bounce webhooks",
|
||||||
|
"settings.bounces.enablePostmark": "Attiva Postmark",
|
||||||
"settings.bounces.enabled": "Attivato",
|
"settings.bounces.enabled": "Attivato",
|
||||||
"settings.bounces.folder": "Cartella",
|
"settings.bounces.folder": "Cartella",
|
||||||
"settings.bounces.folderHelp": "Nome della cartella IMAP da analizzare. Ad esempio: Posta in arrivo.",
|
"settings.bounces.folderHelp": "Nome della cartella IMAP da analizzare. Ad esempio: Posta in arrivo.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Oggeto",
|
"templates.subject": "Oggeto",
|
||||||
"users.login": "Accesso",
|
"users.login": "Accesso",
|
||||||
"users.logout": "Esci"
|
"users.logout": "Esci"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "SESを有効にする",
|
"settings.bounces.enableSES": "SESを有効にする",
|
||||||
"settings.bounces.enableSendgrid": "SendGridを有効にする",
|
"settings.bounces.enableSendgrid": "SendGridを有効にする",
|
||||||
"settings.bounces.enableWebhooks": "バウンスウェブフックを有効にする",
|
"settings.bounces.enableWebhooks": "バウンスウェブフックを有効にする",
|
||||||
|
"settings.bounces.enablePostmark": "Postmarkを有効にする",
|
||||||
"settings.bounces.enabled": "有効",
|
"settings.bounces.enabled": "有効",
|
||||||
"settings.bounces.folder": "フォルダ",
|
"settings.bounces.folder": "フォルダ",
|
||||||
"settings.bounces.folderHelp": "スキャンするIMAPフォルダの名前。 例: Inbox.",
|
"settings.bounces.folderHelp": "スキャンするIMAPフォルダの名前。 例: Inbox.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "件名",
|
"templates.subject": "件名",
|
||||||
"users.login": "ログイン",
|
"users.login": "ログイン",
|
||||||
"users.logout": "ログアウト"
|
"users.logout": "ログアウト"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "SES പ്രവർത്തനക്ഷമമാക്കുക",
|
"settings.bounces.enableSES": "SES പ്രവർത്തനക്ഷമമാക്കുക",
|
||||||
"settings.bounces.enableSendgrid": "SendGrid പ്രവർത്തനക്ഷമമാക്കുക",
|
"settings.bounces.enableSendgrid": "SendGrid പ്രവർത്തനക്ഷമമാക്കുക",
|
||||||
"settings.bounces.enableWebhooks": "ബൗൺസ് വെബ്ഹുക്കുകൾ പ്രവർത്തനക്ഷമമാക്കുക",
|
"settings.bounces.enableWebhooks": "ബൗൺസ് വെബ്ഹുക്കുകൾ പ്രവർത്തനക്ഷമമാക്കുക",
|
||||||
|
"settings.bounces.enablePostmark": "Postmark പ്രവർത്തനക്ഷമമാക്കുക",
|
||||||
"settings.bounces.enabled": "പ്രവർത്തനക്ഷമമാക്കി",
|
"settings.bounces.enabled": "പ്രവർത്തനക്ഷമമാക്കി",
|
||||||
"settings.bounces.folder": "ഫോൾഡർ",
|
"settings.bounces.folder": "ഫോൾഡർ",
|
||||||
"settings.bounces.folderHelp": "സ്കാൻ ചെയ്യാനുള്ള IMAP ഫോൾഡറിന്റെ പേര്. ഉദാ: ഇൻബോക്സ്.",
|
"settings.bounces.folderHelp": "സ്കാൻ ചെയ്യാനുള്ള IMAP ഫോൾഡറിന്റെ പേര്. ഉദാ: ഇൻബോക്സ്.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "വിഷയം",
|
"templates.subject": "വിഷയം",
|
||||||
"users.login": "പ്രവേശിക്കുക",
|
"users.login": "പ്രവേശിക്കുക",
|
||||||
"users.logout": "പുറത്തുകടക്കുക"
|
"users.logout": "പുറത്തുകടക്കുക"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "SES inschakelen",
|
"settings.bounces.enableSES": "SES inschakelen",
|
||||||
"settings.bounces.enableSendgrid": "SendGrid inschakelen",
|
"settings.bounces.enableSendgrid": "SendGrid inschakelen",
|
||||||
"settings.bounces.enableWebhooks": "Bounce webhooks inschakelen",
|
"settings.bounces.enableWebhooks": "Bounce webhooks inschakelen",
|
||||||
|
"settings.bounces.enablePostmark": "Postmark inschakelen",
|
||||||
"settings.bounces.enabled": "Ingeschakeld",
|
"settings.bounces.enabled": "Ingeschakeld",
|
||||||
"settings.bounces.folder": "Map",
|
"settings.bounces.folder": "Map",
|
||||||
"settings.bounces.folderHelp": "Naam van de IMAP map om te scannen. Bv.: Inbox.",
|
"settings.bounces.folderHelp": "Naam van de IMAP map om te scannen. Bv.: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Onderwerp",
|
"templates.subject": "Onderwerp",
|
||||||
"users.login": "Inloggen",
|
"users.login": "Inloggen",
|
||||||
"users.logout": "Uitloggen"
|
"users.logout": "Uitloggen"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Włącz SES",
|
"settings.bounces.enableSES": "Włącz SES",
|
||||||
"settings.bounces.enableSendgrid": "Włącz SendGrid",
|
"settings.bounces.enableSendgrid": "Włącz SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Włącz webhooki odbić",
|
"settings.bounces.enableWebhooks": "Włącz webhooki odbić",
|
||||||
|
"settings.bounces.enablePostmark": "Włącz Postmark",
|
||||||
"settings.bounces.enabled": "Włączone",
|
"settings.bounces.enabled": "Włączone",
|
||||||
"settings.bounces.folder": "Folder",
|
"settings.bounces.folder": "Folder",
|
||||||
"settings.bounces.folderHelp": "Nazwa folderu IMAP do skanowania. Np: Inbox.",
|
"settings.bounces.folderHelp": "Nazwa folderu IMAP do skanowania. Np: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Temat",
|
"templates.subject": "Temat",
|
||||||
"users.login": "Zaloguj",
|
"users.login": "Zaloguj",
|
||||||
"users.logout": "Wyloguj"
|
"users.logout": "Wyloguj"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Ativar SES",
|
"settings.bounces.enableSES": "Ativar SES",
|
||||||
"settings.bounces.enableSendgrid": "Ativar SendGrid",
|
"settings.bounces.enableSendgrid": "Ativar SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Ativar webhooks bounce",
|
"settings.bounces.enableWebhooks": "Ativar webhooks bounce",
|
||||||
|
"settings.bounces.enablePostmark": "Ativar Postmark",
|
||||||
"settings.bounces.enabled": "Ativado",
|
"settings.bounces.enabled": "Ativado",
|
||||||
"settings.bounces.folder": "Pasta",
|
"settings.bounces.folder": "Pasta",
|
||||||
"settings.bounces.folderHelp": "Noma da pasta IMAP para escanear. Ex: Inbox.",
|
"settings.bounces.folderHelp": "Noma da pasta IMAP para escanear. Ex: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Assunto",
|
"templates.subject": "Assunto",
|
||||||
"users.login": "Entrar",
|
"users.login": "Entrar",
|
||||||
"users.logout": "Sair"
|
"users.logout": "Sair"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Ligar SES",
|
"settings.bounces.enableSES": "Ligar SES",
|
||||||
"settings.bounces.enableSendgrid": "Ligar SendGrid",
|
"settings.bounces.enableSendgrid": "Ligar SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Ligar webhooks de bounces",
|
"settings.bounces.enableWebhooks": "Ligar webhooks de bounces",
|
||||||
|
"settings.bounces.enablePostmark": "Ligar Postmark",
|
||||||
"settings.bounces.enabled": "Ligado",
|
"settings.bounces.enabled": "Ligado",
|
||||||
"settings.bounces.folder": "Pasta",
|
"settings.bounces.folder": "Pasta",
|
||||||
"settings.bounces.folderHelp": "Nome da pasta IMAP para procurar. E.g.: Inbox.",
|
"settings.bounces.folderHelp": "Nome da pasta IMAP para procurar. E.g.: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Assunto",
|
"templates.subject": "Assunto",
|
||||||
"users.login": "Entrar",
|
"users.login": "Entrar",
|
||||||
"users.logout": "Sair"
|
"users.logout": "Sair"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "Activați SES",
|
"settings.bounces.enableSES": "Activați SES",
|
||||||
"settings.bounces.enableSendgrid": "Activați SendGrid",
|
"settings.bounces.enableSendgrid": "Activați SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Activați webhooks bounce",
|
"settings.bounces.enableWebhooks": "Activați webhooks bounce",
|
||||||
|
"settings.bounces.enablePostmark": "Activați Postmark",
|
||||||
"settings.bounces.enabled": "Activat",
|
"settings.bounces.enabled": "Activat",
|
||||||
"settings.bounces.folder": "Director",
|
"settings.bounces.folder": "Director",
|
||||||
"settings.bounces.folderHelp": "Numele folderului IMAP pentru a scana. De exemplu: Inbox.",
|
"settings.bounces.folderHelp": "Numele folderului IMAP pentru a scana. De exemplu: Inbox.",
|
||||||
|
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Включить SES",
|
"settings.bounces.enableSES": "Включить SES",
|
||||||
"settings.bounces.enableSendgrid": "Включить SendGrid",
|
"settings.bounces.enableSendgrid": "Включить SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Включить веб-крючки отскока",
|
"settings.bounces.enableWebhooks": "Включить веб-крючки отскока",
|
||||||
|
"settings.bounces.enablePostmark": "Включить Postmark",
|
||||||
"settings.bounces.enabled": "Включено",
|
"settings.bounces.enabled": "Включено",
|
||||||
"settings.bounces.folder": "Папка",
|
"settings.bounces.folder": "Папка",
|
||||||
"settings.bounces.folderHelp": "Имя папки IMAP для сканирования. Например: Входящие.",
|
"settings.bounces.folderHelp": "Имя папки IMAP для сканирования. Например: Входящие.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Тема",
|
"templates.subject": "Тема",
|
||||||
"users.login": "Вход в систему",
|
"users.login": "Вход в систему",
|
||||||
"users.logout": "Выход из системы"
|
"users.logout": "Выход из системы"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Enable SES",
|
"settings.bounces.enableSES": "Enable SES",
|
||||||
"settings.bounces.enableSendgrid": "Enable SendGrid",
|
"settings.bounces.enableSendgrid": "Enable SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Enable bounce webhooks",
|
"settings.bounces.enableWebhooks": "Enable bounce webhooks",
|
||||||
|
"settings.bounces.enablePostmark": "Enable Postmark",
|
||||||
"settings.bounces.enabled": "Enabled",
|
"settings.bounces.enabled": "Enabled",
|
||||||
"settings.bounces.folder": "Folder",
|
"settings.bounces.folder": "Folder",
|
||||||
"settings.bounces.folderHelp": "Name of the IMAP folder to scan. Eg: Inbox.",
|
"settings.bounces.folderHelp": "Name of the IMAP folder to scan. Eg: Inbox.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Subject",
|
"templates.subject": "Subject",
|
||||||
"users.login": "Login",
|
"users.login": "Login",
|
||||||
"users.logout": "Logout"
|
"users.logout": "Logout"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "Zapnúť SES",
|
"settings.bounces.enableSES": "Zapnúť SES",
|
||||||
"settings.bounces.enableSendgrid": "Zapnúť SendGrid",
|
"settings.bounces.enableSendgrid": "Zapnúť SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Zapnúť webhooky pre nedoručiteľné",
|
"settings.bounces.enableWebhooks": "Zapnúť webhooky pre nedoručiteľné",
|
||||||
|
"settings.bounces.enablePostmark": "Zapnúť Postmark",
|
||||||
"settings.bounces.enabled": "Zapnuté",
|
"settings.bounces.enabled": "Zapnuté",
|
||||||
"settings.bounces.folder": "Priečinok",
|
"settings.bounces.folder": "Priečinok",
|
||||||
"settings.bounces.folderHelp": "Názov kontrolovaného priečinku IMAP. Napríklad INBOX.",
|
"settings.bounces.folderHelp": "Názov kontrolovaného priečinku IMAP. Napríklad INBOX.",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "Predmet",
|
"templates.subject": "Predmet",
|
||||||
"users.login": "Prihlásiť",
|
"users.login": "Prihlásiť",
|
||||||
"users.logout": "Odhlásiť"
|
"users.logout": "Odhlásiť"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "SES'i etkinleştirin",
|
"settings.bounces.enableSES": "SES'i etkinleştirin",
|
||||||
"settings.bounces.enableSendgrid": "SendGrid'i etkinleştirin",
|
"settings.bounces.enableSendgrid": "SendGrid'i etkinleştirin",
|
||||||
"settings.bounces.enableWebhooks": "Sıçrama web kancalarını etkinleştirin",
|
"settings.bounces.enableWebhooks": "Sıçrama web kancalarını etkinleştirin",
|
||||||
|
"settings.bounces.enablePostmark": "Postmark'i etkinleştirin",
|
||||||
"settings.bounces.enabled": "Etkinleştir",
|
"settings.bounces.enabled": "Etkinleştir",
|
||||||
"settings.bounces.folder": "Dizin",
|
"settings.bounces.folder": "Dizin",
|
||||||
"settings.bounces.folderHelp": "Taranacak IMAP klasörünün adı. Örn: Gelen Kutusu.",
|
"settings.bounces.folderHelp": "Taranacak IMAP klasörünün adı. Örn: Gelen Kutusu.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Konu",
|
"templates.subject": "Konu",
|
||||||
"users.login": "Giriş",
|
"users.login": "Giriş",
|
||||||
"users.logout": "Çıkış"
|
"users.logout": "Çıkış"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "Bật SES",
|
"settings.bounces.enableSES": "Bật SES",
|
||||||
"settings.bounces.enableSendgrid": "Bật SendGrid",
|
"settings.bounces.enableSendgrid": "Bật SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "Bật webhook bị trả lại",
|
"settings.bounces.enableWebhooks": "Bật webhook bị trả lại",
|
||||||
|
"settings.bounces.enablePostmark": "Bật Postmark",
|
||||||
"settings.bounces.enabled": "Đã bật",
|
"settings.bounces.enabled": "Đã bật",
|
||||||
"settings.bounces.folder": "Thư mục",
|
"settings.bounces.folder": "Thư mục",
|
||||||
"settings.bounces.folderHelp": "Tên của thư mục IMAP để quét. Vd: Hộp thư đến.",
|
"settings.bounces.folderHelp": "Tên của thư mục IMAP để quét. Vd: Hộp thư đến.",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "Chủ đề",
|
"templates.subject": "Chủ đề",
|
||||||
"users.login": "Đăng nhập",
|
"users.login": "Đăng nhập",
|
||||||
"users.logout": "Đăng xuất"
|
"users.logout": "Đăng xuất"
|
||||||
}
|
}
|
|
@ -365,6 +365,7 @@
|
||||||
"settings.bounces.enableSES": "启用SES",
|
"settings.bounces.enableSES": "启用SES",
|
||||||
"settings.bounces.enableSendgrid": "启用SendGrid",
|
"settings.bounces.enableSendgrid": "启用SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "启用反弹webhooks",
|
"settings.bounces.enableWebhooks": "启用反弹webhooks",
|
||||||
|
"settings.bounces.enablePostmark": "启用Postmark",
|
||||||
"settings.bounces.enabled": "已启用",
|
"settings.bounces.enabled": "已启用",
|
||||||
"settings.bounces.folder": "文件夹",
|
"settings.bounces.folder": "文件夹",
|
||||||
"settings.bounces.folderHelp": "要扫描的 IMAP 文件夹的名称。例如:收件箱。",
|
"settings.bounces.folderHelp": "要扫描的 IMAP 文件夹的名称。例如:收件箱。",
|
||||||
|
@ -577,4 +578,4 @@
|
||||||
"templates.subject": "主题",
|
"templates.subject": "主题",
|
||||||
"users.login": "登录",
|
"users.login": "登录",
|
||||||
"users.logout": "登出"
|
"users.logout": "登出"
|
||||||
}
|
}
|
|
@ -366,6 +366,7 @@
|
||||||
"settings.bounces.enableSES": "啟用SES",
|
"settings.bounces.enableSES": "啟用SES",
|
||||||
"settings.bounces.enableSendgrid": "啟用SendGrid",
|
"settings.bounces.enableSendgrid": "啟用SendGrid",
|
||||||
"settings.bounces.enableWebhooks": "啟用反彈webhooks",
|
"settings.bounces.enableWebhooks": "啟用反彈webhooks",
|
||||||
|
"settings.bounces.enablePostmark": "啟用Postmark",
|
||||||
"settings.bounces.enabled": "已啟用",
|
"settings.bounces.enabled": "已啟用",
|
||||||
"settings.bounces.folder": "文件夾",
|
"settings.bounces.folder": "文件夾",
|
||||||
"settings.bounces.folderHelp": "要掃描的IMAP 文件夾的名稱。例如:收件箱。",
|
"settings.bounces.folderHelp": "要掃描的IMAP 文件夾的名稱。例如:收件箱。",
|
||||||
|
@ -578,4 +579,4 @@
|
||||||
"templates.subject": "主題",
|
"templates.subject": "主題",
|
||||||
"users.login": "登錄",
|
"users.login": "登錄",
|
||||||
"users.logout": "登出"
|
"users.logout": "登出"
|
||||||
}
|
}
|
|
@ -33,6 +33,11 @@ type Opt struct {
|
||||||
SESEnabled bool `json:"ses_enabled"`
|
SESEnabled bool `json:"ses_enabled"`
|
||||||
SendgridEnabled bool `json:"sendgrid_enabled"`
|
SendgridEnabled bool `json:"sendgrid_enabled"`
|
||||||
SendgridKey string `json:"sendgrid_key"`
|
SendgridKey string `json:"sendgrid_key"`
|
||||||
|
Postmark struct {
|
||||||
|
Enabled bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
RecordBounceCB func(models.Bounce) error
|
RecordBounceCB func(models.Bounce) error
|
||||||
}
|
}
|
||||||
|
@ -43,6 +48,7 @@ type Manager struct {
|
||||||
mailbox Mailbox
|
mailbox Mailbox
|
||||||
SES *webhooks.SES
|
SES *webhooks.SES
|
||||||
Sendgrid *webhooks.Sendgrid
|
Sendgrid *webhooks.Sendgrid
|
||||||
|
Postmark *webhooks.Postmark
|
||||||
queries *Queries
|
queries *Queries
|
||||||
opt Opt
|
opt Opt
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
|
@ -77,6 +83,7 @@ func New(opt Opt, q *Queries, lo *log.Logger) (*Manager, error) {
|
||||||
if opt.SESEnabled {
|
if opt.SESEnabled {
|
||||||
m.SES = webhooks.NewSES()
|
m.SES = webhooks.NewSES()
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.SendgridEnabled {
|
if opt.SendgridEnabled {
|
||||||
sg, err := webhooks.NewSendgrid(opt.SendgridKey)
|
sg, err := webhooks.NewSendgrid(opt.SendgridKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -85,6 +92,10 @@ func New(opt Opt, q *Queries, lo *log.Logger) (*Manager, error) {
|
||||||
m.Sendgrid = sg
|
m.Sendgrid = sg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opt.Postmark.Enabled {
|
||||||
|
m.Postmark = webhooks.NewPostmark(opt.Postmark.Username, opt.Postmark.Password)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
118
internal/bounce/webhooks/postmark.go
Normal file
118
internal/bounce/webhooks/postmark.go
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
package webhooks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/knadh/listmonk/models"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
type postmarkNotif struct {
|
||||||
|
RecordType string `json:"RecordType"`
|
||||||
|
MessageStream string `json:"MessageStream"`
|
||||||
|
ID int `json:"ID"`
|
||||||
|
Type string `json:"Type"`
|
||||||
|
TypeCode int `json:"TypeCode"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
Tag string `json:"Tag"`
|
||||||
|
MessageID string `json:"MessageID"`
|
||||||
|
Metadata map[string]string `json:"Metadata"`
|
||||||
|
ServerID int `json:"ServerID"`
|
||||||
|
Description string `json:"Description"`
|
||||||
|
Details string `json:"Details"`
|
||||||
|
Email string `json:"Email"`
|
||||||
|
From string `json:"From"`
|
||||||
|
BouncedAt time.Time `json:"BouncedAt"` // "2019-11-05T16:33:54.9070259Z"
|
||||||
|
DumpAvailable bool `json:"DumpAvailable"`
|
||||||
|
Inactive bool `json:"Inactive"`
|
||||||
|
CanActivate bool `json:"CanActivate"`
|
||||||
|
Subject string `json:"Subject"`
|
||||||
|
Content string `json:"Content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postmark handles webhook notifications (mainly bounce notifications).
|
||||||
|
type Postmark struct {
|
||||||
|
authHandler echo.HandlerFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPostmark(username, password string) *Postmark {
|
||||||
|
return &Postmark{
|
||||||
|
authHandler: middleware.BasicAuth(makePostmarkAuthHandler(username, password))(func(c echo.Context) error {
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessBounce processes Postmark bounce notifications and returns one object.
|
||||||
|
func (p *Postmark) ProcessBounce(b []byte, c echo.Context) ([]models.Bounce, error) {
|
||||||
|
// Do basicauth.
|
||||||
|
if err := p.authHandler(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var n postmarkNotif
|
||||||
|
if err := json.Unmarshal(b, &n); err != nil {
|
||||||
|
return nil, fmt.Errorf("error unmarshalling postmark notification: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore non-bounce messages.
|
||||||
|
if n.RecordType != "Bounce" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
supportedBounceType := true
|
||||||
|
typ := models.BounceTypeHard
|
||||||
|
switch n.Type {
|
||||||
|
case "HardBounce", "BadEmailAddress", "ManuallyDeactivated":
|
||||||
|
typ = models.BounceTypeHard
|
||||||
|
case "SoftBounce", "Transient", "DnsError", "SpamNotification", "VirusNotification", "DMARCPolicy":
|
||||||
|
typ = models.BounceTypeSoft
|
||||||
|
case "SpamComplaint":
|
||||||
|
typ = models.BounceTypeComplaint
|
||||||
|
default:
|
||||||
|
supportedBounceType = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supportedBounceType {
|
||||||
|
return nil, fmt.Errorf("unsupported bounce type: %v", n.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the campaign ID in headers.
|
||||||
|
campUUID := ""
|
||||||
|
if v, ok := n.Metadata["X-Listmonk-Campaign"]; ok {
|
||||||
|
campUUID = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return []models.Bounce{{
|
||||||
|
Email: strings.ToLower(n.Email),
|
||||||
|
CampaignUUID: campUUID,
|
||||||
|
Type: typ,
|
||||||
|
Source: "postmark",
|
||||||
|
Meta: json.RawMessage(b),
|
||||||
|
CreatedAt: n.BouncedAt,
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePostmarkAuthHandler(cfgUser, cfgPassword string) func(username, password string, c echo.Context) (bool, error) {
|
||||||
|
var (
|
||||||
|
u = []byte(cfgUser)
|
||||||
|
p = []byte(cfgPassword)
|
||||||
|
)
|
||||||
|
|
||||||
|
return func(username, password string, c echo.Context) (bool, error) {
|
||||||
|
if len(u) == 0 || len(p) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if subtle.ConstantTimeCompare([]byte(username), u) == 1 && subtle.ConstantTimeCompare([]byte(password), p) == 1 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
17
internal/migrations/v2.6.0.go
Normal file
17
internal/migrations/v2.6.0.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/knadh/koanf/v2"
|
||||||
|
"github.com/knadh/stuffbin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// V2_6_0 performs the DB migrations.
|
||||||
|
func V2_6_0(db *sqlx.DB, fs stuffbin.FileSystem, ko *koanf.Koanf) error {
|
||||||
|
// Insert new preference settings.
|
||||||
|
if _, err := db.Exec(`INSERT INTO settings (key, value) VALUES ('bounce.postmark', '{"enabled": false, "username": "", "password": ""}') ON CONFLICT DO NOTHING;`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -92,7 +92,12 @@ type Settings struct {
|
||||||
SESEnabled bool `json:"bounce.ses_enabled"`
|
SESEnabled bool `json:"bounce.ses_enabled"`
|
||||||
SendgridEnabled bool `json:"bounce.sendgrid_enabled"`
|
SendgridEnabled bool `json:"bounce.sendgrid_enabled"`
|
||||||
SendgridKey string `json:"bounce.sendgrid_key"`
|
SendgridKey string `json:"bounce.sendgrid_key"`
|
||||||
BounceBoxes []struct {
|
BouncePostmark struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
} `json:"bounce.postmark"`
|
||||||
|
BounceBoxes []struct {
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
|
@ -255,6 +255,7 @@ INSERT INTO settings (key, value) VALUES
|
||||||
('bounce.ses_enabled', 'false'),
|
('bounce.ses_enabled', 'false'),
|
||||||
('bounce.sendgrid_enabled', 'false'),
|
('bounce.sendgrid_enabled', 'false'),
|
||||||
('bounce.sendgrid_key', '""'),
|
('bounce.sendgrid_key', '""'),
|
||||||
|
('bounce.postmark', '{"enabled": false, "username": "", "password": ""}'),
|
||||||
('bounce.mailboxes',
|
('bounce.mailboxes',
|
||||||
'[{"enabled":false, "type": "pop", "host":"pop.yoursite.com","port":995,"auth_protocol":"userpass","username":"username","password":"password","return_path": "bounce@listmonk.yoursite.com","scan_interval":"15m","tls_enabled":true,"tls_skip_verify":false}]'),
|
'[{"enabled":false, "type": "pop", "host":"pop.yoursite.com","port":995,"auth_protocol":"userpass","username":"username","password":"password","return_path": "bounce@listmonk.yoursite.com","scan_interval":"15m","tls_enabled":true,"tls_skip_verify":false}]'),
|
||||||
('appearance.admin.custom_css', '""'),
|
('appearance.admin.custom_css', '""'),
|
||||||
|
|
Loading…
Reference in a new issue