mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 17:47:03 +00:00
Allow monitoring of a particular mailbox for #44
- No UI to access, just append /mailbox to /monitor URL
- Changed API URLs:
- /api/v1/monitor/messages - all
- /api/v1/monitor/messages/{name} - specific
This commit is contained in:
@@ -16,6 +16,8 @@ func SetupRoutes(r *mux.Router) {
|
|||||||
httpd.Handler(MailboxDeleteV1)).Name("MailboxDeleteV1").Methods("DELETE")
|
httpd.Handler(MailboxDeleteV1)).Name("MailboxDeleteV1").Methods("DELETE")
|
||||||
r.Path("/api/v1/mailbox/{name}/{id}/source").Handler(
|
r.Path("/api/v1/mailbox/{name}/{id}/source").Handler(
|
||||||
httpd.Handler(MailboxSourceV1)).Name("MailboxSourceV1").Methods("GET")
|
httpd.Handler(MailboxSourceV1)).Name("MailboxSourceV1").Methods("GET")
|
||||||
r.Path("/api/v1/monitor/all/messages").Handler(
|
r.Path("/api/v1/monitor/messages").Handler(
|
||||||
httpd.Handler(MonitorAllMessagesV1)).Name("MonitorAllMessagesV1").Methods("GET")
|
httpd.Handler(MonitorAllMessagesV1)).Name("MonitorAllMessagesV1").Methods("GET")
|
||||||
|
r.Path("/api/v1/monitor/messages/{name}").Handler(
|
||||||
|
httpd.Handler(MonitorMailboxMessagesV1)).Name("MonitorMailboxMessagesV1").Methods("GET")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/jhillyerd/inbucket/log"
|
"github.com/jhillyerd/inbucket/log"
|
||||||
"github.com/jhillyerd/inbucket/msghub"
|
"github.com/jhillyerd/inbucket/msghub"
|
||||||
"github.com/jhillyerd/inbucket/rest/model"
|
"github.com/jhillyerd/inbucket/rest/model"
|
||||||
|
"github.com/jhillyerd/inbucket/smtpd"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -33,15 +34,18 @@ var upgrader = websocket.Upgrader{
|
|||||||
|
|
||||||
// msgListener handles messages from the msghub
|
// msgListener handles messages from the msghub
|
||||||
type msgListener struct {
|
type msgListener struct {
|
||||||
hub *msghub.Hub
|
hub *msghub.Hub // Global message hub
|
||||||
c chan msghub.Message
|
c chan msghub.Message // Queue of messages from Receive()
|
||||||
|
mailbox string // Name of mailbox to monitor, "" == all mailboxes
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMsgListener creates a listener and registers it
|
// newMsgListener creates a listener and registers it. Optional mailbox parameter will restrict
|
||||||
func newMsgListener(hub *msghub.Hub) *msgListener {
|
// messages sent to WebSocket to that mailbox only.
|
||||||
|
func newMsgListener(hub *msghub.Hub, mailbox string) *msgListener {
|
||||||
ml := &msgListener{
|
ml := &msgListener{
|
||||||
hub: hub,
|
hub: hub,
|
||||||
c: make(chan msghub.Message, 100),
|
c: make(chan msghub.Message, 100),
|
||||||
|
mailbox: mailbox,
|
||||||
}
|
}
|
||||||
hub.AddListener(ml)
|
hub.AddListener(ml)
|
||||||
return ml
|
return ml
|
||||||
@@ -49,11 +53,15 @@ func newMsgListener(hub *msghub.Hub) *msgListener {
|
|||||||
|
|
||||||
// Receive handles an incoming message
|
// Receive handles an incoming message
|
||||||
func (ml *msgListener) Receive(msg msghub.Message) error {
|
func (ml *msgListener) Receive(msg msghub.Message) error {
|
||||||
|
if ml.mailbox != "" && ml.mailbox != msg.Mailbox {
|
||||||
|
// Did not match mailbox name
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ml.c <- msg
|
ml.c <- msg
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WSReader makes sure the websocket client is still connected
|
// WSReader makes sure the websocket client is still connected, discards any messages from client
|
||||||
func (ml *msgListener) WSReader(conn *websocket.Conn) {
|
func (ml *msgListener) WSReader(conn *websocket.Conn) {
|
||||||
defer ml.Close()
|
defer ml.Close()
|
||||||
conn.SetReadLimit(maxMessageSize)
|
conn.SetReadLimit(maxMessageSize)
|
||||||
@@ -152,7 +160,34 @@ func MonitorAllMessagesV1(
|
|||||||
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
||||||
|
|
||||||
// Create, register listener; then interact with conn
|
// Create, register listener; then interact with conn
|
||||||
ml := newMsgListener(ctx.MsgHub)
|
ml := newMsgListener(ctx.MsgHub, "")
|
||||||
|
go ml.WSWriter(conn)
|
||||||
|
ml.WSReader(conn)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonitorMailboxMessagesV1(
|
||||||
|
w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
||||||
|
name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Upgrade to Websocket
|
||||||
|
conn, err := upgrader.Upgrade(w, req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
httpd.ExpWebSocketConnectsCurrent.Add(1)
|
||||||
|
defer func() {
|
||||||
|
_ = conn.Close()
|
||||||
|
httpd.ExpWebSocketConnectsCurrent.Add(-1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Tracef("HTTP[%v] Upgraded to websocket", req.RemoteAddr)
|
||||||
|
|
||||||
|
// Create, register listener; then interact with conn
|
||||||
|
ml := newMsgListener(ctx.MsgHub, name)
|
||||||
go ml.WSWriter(conn)
|
go ml.WSWriter(conn)
|
||||||
ml.WSReader(conn)
|
ml.WSReader(conn)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var baseURL = window.location.protocol + '//' + window.location.host;
|
var baseURL = window.location.protocol + '//' + window.location.host;
|
||||||
|
|
||||||
function startMonitor() {
|
function startMonitor(mailbox) {
|
||||||
$.addTemplateFormatter({
|
$.addTemplateFormatter({
|
||||||
"date": function(value, template) {
|
"date": function(value, template) {
|
||||||
return moment(value).calendar();
|
return moment(value).calendar();
|
||||||
@@ -13,7 +13,10 @@ function startMonitor() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var uri = '/api/v1/monitor/all/messages'
|
var uri = '/api/v1/monitor/messages'
|
||||||
|
if (mailbox) {
|
||||||
|
uri += '/' + mailbox;
|
||||||
|
}
|
||||||
var l = window.location;
|
var l = window.location;
|
||||||
var url = ((l.protocol === "https:") ? "wss://" : "ws://") + l.host + uri
|
var url = ((l.protocol === "https:") ? "wss://" : "ws://") + l.host + uri
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#nav-monitor').addClass('active');
|
$('#nav-monitor').addClass('active');
|
||||||
startMonitor();
|
startMonitor('{{.name}}');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<script type="text/html" id="message-template">
|
<script type="text/html" id="message-template">
|
||||||
@@ -32,7 +32,12 @@ $(document).ready(function () {
|
|||||||
<button class="btn btn-primary" onclick="clearClick();">Clear</button>
|
<button class="btn btn-primary" onclick="clearClick();">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="small">Messages will be listed here shortly after delivery.</p>
|
<p class="small">
|
||||||
|
Messages will be listed here shortly after delivery.
|
||||||
|
{{with .name}}
|
||||||
|
Only showing messages for mailbox <code>{{.}}</code>.
|
||||||
|
{{end}}
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="table-responsive clearfix">
|
<div class="table-responsive clearfix">
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jhillyerd/inbucket/config"
|
"github.com/jhillyerd/inbucket/config"
|
||||||
"github.com/jhillyerd/inbucket/httpd"
|
"github.com/jhillyerd/inbucket/httpd"
|
||||||
|
"github.com/jhillyerd/inbucket/smtpd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RootIndex serves the Inbucket landing page
|
// RootIndex serves the Inbucket landing page
|
||||||
@@ -49,6 +50,34 @@ func RootMonitor(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootMonitorMailbox serves the Inbucket monitor page for a particular mailbox
|
||||||
|
func RootMonitorMailbox(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
||||||
|
if !config.GetWebConfig().MonitorVisible {
|
||||||
|
ctx.Session.AddFlash("Monitor is disabled in configuration", "errors")
|
||||||
|
_ = ctx.Session.Save(req, w)
|
||||||
|
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
|
||||||
|
if err != nil {
|
||||||
|
ctx.Session.AddFlash(err.Error(), "errors")
|
||||||
|
_ = ctx.Session.Save(req, w)
|
||||||
|
http.Redirect(w, req, httpd.Reverse("RootIndex"), http.StatusSeeOther)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Get flash messages, save session
|
||||||
|
errorFlash := ctx.Session.Flashes("errors")
|
||||||
|
if err = ctx.Session.Save(req, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Render template
|
||||||
|
return httpd.RenderTemplate("root/monitor.html", w, map[string]interface{}{
|
||||||
|
"ctx": ctx,
|
||||||
|
"errorFlash": errorFlash,
|
||||||
|
"name": name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// RootStatus serves the Inbucket status page
|
// RootStatus serves the Inbucket status page
|
||||||
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
|
||||||
smtpListener := fmt.Sprintf("%s:%d", config.GetSMTPConfig().IP4address.String(),
|
smtpListener := fmt.Sprintf("%s:%d", config.GetSMTPConfig().IP4address.String(),
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ func SetupRoutes(r *mux.Router) {
|
|||||||
httpd.Handler(RootIndex)).Name("RootIndex").Methods("GET")
|
httpd.Handler(RootIndex)).Name("RootIndex").Methods("GET")
|
||||||
r.Path("/monitor").Handler(
|
r.Path("/monitor").Handler(
|
||||||
httpd.Handler(RootMonitor)).Name("RootMonitor").Methods("GET")
|
httpd.Handler(RootMonitor)).Name("RootMonitor").Methods("GET")
|
||||||
|
r.Path("/monitor/{name}").Handler(
|
||||||
|
httpd.Handler(RootMonitorMailbox)).Name("RootMonitorMailbox").Methods("GET")
|
||||||
r.Path("/status").Handler(
|
r.Path("/status").Handler(
|
||||||
httpd.Handler(RootStatus)).Name("RootStatus").Methods("GET")
|
httpd.Handler(RootStatus)).Name("RootStatus").Methods("GET")
|
||||||
r.Path("/link/{name}/{id}").Handler(
|
r.Path("/link/{name}/{id}").Handler(
|
||||||
|
|||||||
Reference in New Issue
Block a user