diff --git a/frontend/src/Subscriber.js b/frontend/src/Subscriber.js
index c840a6a..dde8f03 100644
--- a/frontend/src/Subscriber.js
+++ b/frontend/src/Subscriber.js
@@ -1,4 +1,5 @@
import React from "react"
+import { Link } from "react-router-dom"
import {
Row,
Col,
@@ -156,6 +157,27 @@ class CreateFormDef extends React.PureComponent {
})
}
+ handleSendOptinMail = record => {
+ this.props
+ .request(cs.Routes.SendSubscriberOptinMail, cs.MethodPost, {
+ id: record.id
+ })
+ .then(r => {
+ notification["success"]({
+ placement: cs.MsgPosition,
+ message: "Sent",
+ description: `Opt-in e-mail sentto ${record.email}`
+ })
+ })
+ .catch(e => {
+ notification["error"]({
+ placement: cs.MsgPosition,
+ message: "Error",
+ description: e.message
+ })
+ })
+ }
+
render() {
const { formType, record } = this.props
const { getFieldDecorator } = this.props.form
@@ -240,6 +262,24 @@ class CreateFormDef extends React.PureComponent {
))}
)}
+ {record.lists &&
+ record.lists.some(l => {
+ return (
+ l.subscription_status === cs.SubscriptionStatusUnConfirmed
+ )
+ }) && (
+
+ {
+ e.preventDefault()
+ this.handleSendOptinMail(record)
+ }}
+ to={`/`}
+ >
+ Send opt-in e-mail
+
+
+ )}
diff --git a/frontend/src/constants.js b/frontend/src/constants.js
index 9b6c31d..f167e4d 100644
--- a/frontend/src/constants.js
+++ b/frontend/src/constants.js
@@ -83,6 +83,7 @@ export const Routes = {
UpdateSubscriber: "/api/subscribers/:id",
DeleteSubscriber: "/api/subscribers/:id",
DeleteSubscribers: "/api/subscribers",
+ SendSubscriberOptinMail: "/api/subscribers/:id/optin",
BlacklistSubscriber: "/api/subscribers/:id/blacklist",
BlacklistSubscribers: "/api/subscribers/blacklist",
AddSubscriberToLists: "/api/subscribers/lists/:id",
diff --git a/handlers.go b/handlers.go
index 52713e4..e462e4b 100644
--- a/handlers.go
+++ b/handlers.go
@@ -44,6 +44,7 @@ func registerHandlers(e *echo.Echo) {
e.GET("/api/subscribers/:id/export", handleExportSubscriberData)
e.POST("/api/subscribers", handleCreateSubscriber)
e.PUT("/api/subscribers/:id", handleUpdateSubscriber)
+ e.POST("/api/subscribers/:id/optin", handleGetSubscriberSendOptin)
e.PUT("/api/subscribers/blacklist", handleBlacklistSubscribers)
e.PUT("/api/subscribers/:id/blacklist", handleBlacklistSubscribers)
e.PUT("/api/subscribers/lists/:id", handleManageSubscriberLists)
diff --git a/subscribers.go b/subscribers.go
index e18c254..f2c9fdb 100644
--- a/subscribers.go
+++ b/subscribers.go
@@ -232,6 +232,36 @@ func handleUpdateSubscriber(c echo.Context) error {
return handleGetSubscriber(c)
}
+// handleGetSubscriberSendOptin sends an optin confirmation e-mail to a subscriber.
+func handleGetSubscriberSendOptin(c echo.Context) error {
+ var (
+ app = c.Get("app").(*App)
+ id, _ = strconv.Atoi(c.Param("id"))
+ out models.Subscribers
+ )
+
+ if id < 1 {
+ return echo.NewHTTPError(http.StatusBadRequest, "Invalid subscriber ID.")
+ }
+
+ // Fetch the subscriber.
+ err := app.Queries.GetSubscriber.Select(&out, id, nil)
+ if err != nil {
+ return echo.NewHTTPError(http.StatusInternalServerError,
+ fmt.Sprintf("Error fetching subscriber: %s", pqErrMsg(err)))
+ }
+ if len(out) == 0 {
+ return echo.NewHTTPError(http.StatusBadRequest, "Subscriber not found.")
+ }
+
+ if err := sendOptinConfirmation(out[0], nil, app); err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest,
+ "Error sending opt-in e-mail.")
+ }
+
+ return c.JSON(http.StatusOK, okResp{true})
+}
+
// handleBlacklistSubscribers handles the blacklisting of one or more subscribers.
// It takes either an ID in the URI, or a list of IDs in the request body.
func handleBlacklistSubscribers(c echo.Context) error {