1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 17:47:03 +00:00

Merge in REST changes

This commit is contained in:
James Hillyerd
2013-10-11 18:09:15 -07:00
19 changed files with 146 additions and 23 deletions

View File

@@ -6,7 +6,7 @@
"Resources": {
"Include": "README*,LICENSE*,bin,etc,themes"
},
"PackageVersion": "20131001",
"PackageVersion": "20131010",
"PrereleaseInfo": "snapshot",
"FormatVersion": "0.8"
}

1
bin/mailbox-list.sh Executable file
View File

@@ -0,0 +1 @@
curl -i -H "Accept: application/json" --noproxy localhost http://localhost:9000/mailbox/$1

1
bin/message-delete.sh Executable file
View File

@@ -0,0 +1 @@
curl -i -H "Accept: application/json" --noproxy localhost -X DELETE http://localhost:9000/mailbox/$1/$2

1
bin/message-source.sh Executable file
View File

@@ -0,0 +1 @@
curl -i -H "Accept: application/json" --noproxy localhost http://localhost:9000/mailbox/$1/$2/source

View File

@@ -25,7 +25,7 @@ type SmtpConfig struct {
type Pop3Config struct {
Ip4address net.IP
Ip4port int
Domain string
Domain string
MaxIdleSeconds int
}
@@ -35,6 +35,7 @@ type WebConfig struct {
TemplateDir string
TemplateCache bool
PublicDir string
GreetingFile string
}
type DataStoreConfig struct {
@@ -328,6 +329,13 @@ func parseWebConfig() error {
}
webConfig.PublicDir = str
option = "greeting.file"
str, err = Config.String(section, option)
if err != nil {
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
}
webConfig.GreetingFile = str
return nil
}

View File

@@ -81,6 +81,10 @@ template.cache=false
# Path to the selected themes public (static) files
public.dir=%(install.dir)s/themes/%(theme)s/public
# Path to the greeting HTML displayed on front page, can
# be moved out of installation dir for customization
greeting.file=%(install.dir)s/themes/greeting.html
#############################################################################
[datastore]

View File

@@ -81,6 +81,10 @@ template.cache=true
# Path to the selected themes public (static) files
public.dir=%(install.dir)s/themes/%(theme)s/public
# Path to the greeting HTML displayed on front page, can
# be moved out of installation dir for customization
greeting.file=%(install.dir)s/themes/greeting.html
#############################################################################
[datastore]

View File

@@ -81,6 +81,10 @@ template.cache=true
# Path to the selected themes public (static) files
public.dir=%(install.dir)s/themes/%(theme)s/public
# Path to the greeting HTML displayed on front page, can
# be moved out of installation dir for customization
greeting.file=%(install.dir)s/themes/greeting.html
#############################################################################
[datastore]

View File

@@ -81,6 +81,10 @@ template.cache=true
# Path to the selected themes public (static) files
public.dir=%(install.dir)s\themes\%(theme)s\public
# Path to the greeting HTML displayed on front page, can
# be moved out of installation dir for customization
greeting.file=%(install.dir)s\themes\greeting.html
#############################################################################
[datastore]

9
themes/greeting.html Normal file
View File

@@ -0,0 +1,9 @@
<p>Inbucket is an email testing service; it will accept email for any email
address and make it available to view without a password.</p>
<p>To view email for a particular address, enter the username portion
of the address into the box on the upper right and click <em>go</em>.</p>
<p>This message can be customized by editing greeting.html. Change the
configuration option <code>greeting.file</code> if you'd like to move it
outside of the Inbucket installation directory.</p>

View File

@@ -47,7 +47,7 @@ Released for free under a Creative Commons Attribution 2.5 License
</div>
<div id="footer">
<p>Inbucket is an open source project hosted at
<a href="http://jhillyerd.github.com/inbucket/">github</a>.
<a href="http://jhillyerd.github.io/inbucket/">github</a>.
Design by <a href="http://www.freecsstemplates.org/">FCT</a>.</p>
</div>
</body>

View File

@@ -15,14 +15,14 @@
function() {
$('.listEntry').removeClass("listEntrySelected")
$(this).addClass("listEntrySelected")
$('#emailContent').load('/mailbox/show/{{.name}}/' + this.id)
$('#emailContent').load('/mailbox/{{.name}}/' + this.id)
}
)
$("#messageList").slideDown()
}
function loadList() {
$('#messageList').load("/mailbox/list/{{.name}}", listLoaded)
$('#messageList').load("/mailbox/{{.name}}", listLoaded)
}
function reloadList() {
@@ -38,20 +38,20 @@
function deleteMessage(id) {
$('#emailContent').empty()
$.ajax({
type: 'POST',
url: '/mailbox/delete/{{.name}}/' + id,
type: 'DELETE',
url: '/mailbox/{{.name}}/' + id,
success: reloadList
})
}
function htmlView(id) {
window.open('/mailbox/html/{{.name}}/' + id, '_blank',
window.open('/mailbox/{{.name}}/' + id + "/html", '_blank',
'width=800,height=600,' +
'menubar=yes,resizable=yes,scrollbars=yes,status=yes,toolbar=yes')
}
function messageSource(id) {
window.open('/mailbox/source/{{.name}}/' + id, '_blank',
window.open('/mailbox/{{.name}}/' + id + "/source", '_blank',
'width=800,height=600,' +
'menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no')
}

View File

@@ -9,11 +9,4 @@
</div>
{{end}}
{{define "content"}}
<p>Inbucket is an email testing service; it will accept email for any email
address and make it available to view without a password.</p>
<p>To view email for a particular address, enter the username portion
of the address into the box on the upper right and click <em>go</em>.</p>
{{end}}
{{define "content"}}{{.greeting}}{{end}}

View File

@@ -139,6 +139,24 @@
<p>Metrics are polled every 10 seconds. Inbucket does not keep history for the
10 minute graphs, but your web browser will accumulate the data over time.</p>
<div class="box">
<h3>Configuration</h3>
<table class="metrics">
<tr>
<th>SMTP Listener:</th>
<td><span>{{.smtpListener}}</span></td>
</tr>
<tr>
<th>POP3 Listener:</th>
<td><span>{{.pop3Listener}}</span></td>
</tr>
<tr>
<th>HTTP Listener:</th>
<td><span>{{.webListener}}</span></td>
</tr>
</table>
<p class="last">&nbsp;</p>
</div>
<div class="box">
<h3>General Metrics</h3>
<table class="metrics">

View File

@@ -5,18 +5,37 @@ import (
"github.com/gorilla/sessions"
"github.com/jhillyerd/inbucket/smtpd"
"net/http"
"strings"
)
type Context struct {
Vars map[string]string
Session *sessions.Session
DataStore smtpd.DataStore
IsJson bool
}
func (c *Context) Close() {
// Do nothing
}
// headerMatch returns true if the request header specified by name contains
// the specified value. Case is ignored.
func headerMatch(req *http.Request, name string, value string) bool {
name = http.CanonicalHeaderKey(name)
value = strings.ToLower(value)
if header := req.Header[name]; header != nil {
for _, hv := range header {
if value == strings.ToLower(hv) {
return true
}
}
}
return false
}
func NewContext(req *http.Request) (*Context, error) {
vars := mux.Vars(req)
sess, err := sessionStore.Get(req, "inbucket")
@@ -25,6 +44,7 @@ func NewContext(req *http.Request) (*Context, error) {
Vars: vars,
Session: sess,
DataStore: ds,
IsJson: headerMatch(req, "Accept", "application/json"),
}
if err != nil {
return ctx, err

View File

@@ -7,8 +7,14 @@ import (
"io"
"net/http"
"strconv"
"time"
)
type JsonMessageHeader struct {
Mailbox, Id, From, Subject string
Date time.Time
}
func MailboxIndex(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
name := req.FormValue("name")
if len(name) == 0 {
@@ -37,6 +43,20 @@ func MailboxList(w http.ResponseWriter, req *http.Request, ctx *Context) (err er
}
log.LogTrace("Got %v messsages", len(messages))
if ctx.IsJson {
jmessages := make([]*JsonMessageHeader, len(messages))
for i, msg := range messages {
jmessages[i] = &JsonMessageHeader{
Mailbox: name,
Id: msg.Id(),
From: msg.From(),
Subject: msg.Subject(),
Date: msg.Date(),
}
}
return RenderJson(w, jmessages)
}
return RenderPartial("mailbox/_list.html", w, map[string]interface{}{
"ctx": ctx,
"name": name,
@@ -214,6 +234,11 @@ func MailboxDelete(w http.ResponseWriter, req *http.Request, ctx *Context) (err
if err != nil {
return err
}
if ctx.IsJson {
return RenderJson(w, "OK")
}
w.Header().Set("Content-Type", "text/plain")
io.WriteString(w, "OK")
return nil

13
web/rest.go Normal file
View File

@@ -0,0 +1,13 @@
package web
import (
"encoding/json"
"net/http"
)
func RenderJson(w http.ResponseWriter, data interface{}) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("Expires", "-1")
enc := json.NewEncoder(w)
return enc.Encode(data)
}

View File

@@ -1,20 +1,38 @@
package web
import (
"fmt"
"github.com/jhillyerd/inbucket/config"
"html/template"
"io/ioutil"
"net/http"
)
func RootIndex(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
greeting, err := ioutil.ReadFile(config.GetWebConfig().GreetingFile)
if err != nil {
return fmt.Errorf("Failed to load greeting: %v", err)
}
return RenderTemplate("root/index.html", w, map[string]interface{}{
"ctx": ctx,
"greeting": template.HTML(string(greeting)),
})
}
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
retentionMinutes := config.GetDataStoreConfig().RetentionMinutes
smtpListener := fmt.Sprintf("%s:%d", config.GetSmtpConfig().Ip4address.String(),
config.GetSmtpConfig().Ip4port)
pop3Listener := fmt.Sprintf("%s:%d", config.GetPop3Config().Ip4address.String(),
config.GetPop3Config().Ip4port)
webListener := fmt.Sprintf("%s:%d", config.GetWebConfig().Ip4address.String(),
config.GetWebConfig().Ip4port)
return RenderTemplate("root/status.html", w, map[string]interface{}{
"ctx": ctx,
"ctx": ctx,
"retentionMinutes": retentionMinutes,
"smtpListener": smtpListener,
"pop3Listener": pop3Listener,
"webListener": webListener,
})
}

View File

@@ -35,11 +35,11 @@ func setupRoutes(cfg config.WebConfig) {
r.Path("/").Handler(handler(RootIndex)).Name("RootIndex").Methods("GET")
r.Path("/status").Handler(handler(RootStatus)).Name("RootStatus").Methods("GET")
r.Path("/mailbox").Handler(handler(MailboxIndex)).Name("MailboxIndex").Methods("GET")
r.Path("/mailbox/list/{name}").Handler(handler(MailboxList)).Name("MailboxList").Methods("GET")
r.Path("/mailbox/show/{name}/{id}").Handler(handler(MailboxShow)).Name("MailboxShow").Methods("GET")
r.Path("/mailbox/html/{name}/{id}").Handler(handler(MailboxHtml)).Name("MailboxHtml").Methods("GET")
r.Path("/mailbox/source/{name}/{id}").Handler(handler(MailboxSource)).Name("MailboxSource").Methods("GET")
r.Path("/mailbox/delete/{name}/{id}").Handler(handler(MailboxDelete)).Name("MailboxDelete").Methods("POST")
r.Path("/mailbox/{name}").Handler(handler(MailboxList)).Name("MailboxList").Methods("GET")
r.Path("/mailbox/{name}/{id}").Handler(handler(MailboxShow)).Name("MailboxShow").Methods("GET")
r.Path("/mailbox/{name}/{id}/html").Handler(handler(MailboxHtml)).Name("MailboxHtml").Methods("GET")
r.Path("/mailbox/{name}/{id}/source").Handler(handler(MailboxSource)).Name("MailboxSource").Methods("GET")
r.Path("/mailbox/{name}/{id}").Handler(handler(MailboxDelete)).Name("MailboxDelete").Methods("DELETE")
r.Path("/mailbox/dattach/{name}/{id}/{num}/{file}").Handler(handler(MailboxDownloadAttach)).Name("MailboxDownloadAttach").Methods("GET")
r.Path("/mailbox/vattach/{name}/{id}/{num}/{file}").Handler(handler(MailboxViewAttach)).Name("MailboxViewAttach").Methods("GET")