Skip to content

Commit 61e2942

Browse files
committed
the goods
1 parent 18477ef commit 61e2942

8 files changed

Lines changed: 242 additions & 0 deletions

File tree

.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Dockerfile
2+
.git
3+
bin
4+
src
5+
README.md

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ _testmain.go
2222
*.exe
2323
*.test
2424
*.prof
25+
26+
src
27+
bin

Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM golang:1.4-cross
2+
3+
RUN mkdir -p /go/src/app
4+
WORKDIR /go/src/app
5+
6+
ENV CROSSPLATFORMS \
7+
linux/amd64 linux/386 linux/arm \
8+
darwin/amd64 darwin/386 \
9+
freebsd/amd64 freebsd/386 freebsd/arm \
10+
windows/amd64 windows/386
11+
12+
ENV GOARM 5
13+
14+
CMD set -x \
15+
&& go-wrapper download \
16+
&& for platform in $CROSSPLATFORMS; do \
17+
GOOS=${platform%/*} \
18+
GOARCH=${platform##*/} \
19+
go build -v -o bin/email-me-${platform%/*}-${platform##*/}; \
20+
done

build.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
set -x
3+
4+
rm -rf bin/
5+
docker build --rm -t email-me .
6+
docker run --rm -v $PWD:/go/src/app -it email-me

command.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"os"
6+
"os/exec"
7+
"os/user"
8+
"text/template"
9+
"time"
10+
)
11+
12+
const emailTemplate = `From: {{.From}}
13+
To: {{.To}}
14+
Subject: {{.Subject}}
15+
16+
Cmd: {{.Result.Cmd.Args}}
17+
Start: {{.Result.Start}}
18+
End: {{.Result.End}}
19+
Duration: {{.Result.Duration}}
20+
ProcessState: {{.Result.Cmd.ProcessState}}
21+
Error: {{.Result.Error}}
22+
Stderr:{{if .Result.StderrExtra}}
23+
... {{.Result.StderrExtra}} more bytes ...{{end}}
24+
{{.Result.Stderr}}
25+
26+
Stdout:{{if .Result.StdoutExtra}}
27+
... {{.Result.StdoutExtra}} more bytes ...{{end}}
28+
{{.Result.Stdout}}
29+
`
30+
31+
type Message struct {
32+
To string
33+
From string
34+
Subject string
35+
Result *Result
36+
}
37+
38+
func (m *Message) Bytes() []byte {
39+
var buf bytes.Buffer
40+
t := template.New("mail")
41+
t, _ = t.Parse(emailTemplate)
42+
t.Execute(&buf, m)
43+
return buf.Bytes()
44+
}
45+
46+
func (m *Message) String() string {
47+
return string(m.Bytes())
48+
}
49+
50+
type Result struct {
51+
Cmd *exec.Cmd
52+
Error error
53+
Start time.Time
54+
End time.Time
55+
Duration time.Duration
56+
Stdout string
57+
Stderr string
58+
StdoutExtra int
59+
StderrExtra int
60+
}
61+
62+
func identity() string {
63+
var username string
64+
user, err := user.Current()
65+
if err != nil {
66+
username = "root"
67+
} else {
68+
username = user.Username
69+
}
70+
71+
hostname, err := os.Hostname()
72+
if err != nil {
73+
hostname = "localhost"
74+
}
75+
return username + "@" + hostname
76+
}
77+
78+
type Mailer interface {
79+
Send([]string, string, []byte) error
80+
}
81+
82+
func findMailer() Mailer {
83+
if _, err := exec.LookPath("sendmail"); err == nil {
84+
return &SendMailMailer{}
85+
}
86+
87+
return &SMTPMailer{}
88+
}

main.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"io"
7+
"log"
8+
"os"
9+
"os/exec"
10+
"runtime"
11+
"time"
12+
13+
"github.com/cespare/window"
14+
"github.com/jeanfric/goembed/countingwriter"
15+
)
16+
17+
const Version = "0.1.0"
18+
19+
var (
20+
toFlag = flag.String("to", "", "email address to send output to")
21+
subjectFlag = flag.String("s", "", "subject of email (optional)")
22+
maxFlag = flag.Int("max", 10000, "max bytes to capture for stdout/stderr")
23+
)
24+
25+
func usageAndExit(s string) {
26+
fmt.Printf("!! %s\n", s)
27+
flag.Usage()
28+
fmt.Println()
29+
fmt.Printf("%s version: %s (%s on %s/%s; %s)\n", os.Args[0], Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.Compiler)
30+
os.Exit(1)
31+
}
32+
33+
func init() {
34+
runtime.GOMAXPROCS(1)
35+
runtime.LockOSThread()
36+
37+
flag.Usage = func() {
38+
fmt.Fprint(os.Stderr, "usage: email-me [flags] [command]\n")
39+
flag.PrintDefaults()
40+
}
41+
flag.Parse()
42+
}
43+
44+
func main() {
45+
if *toFlag == "" {
46+
usageAndExit("missing -to=[address]")
47+
}
48+
49+
args := flag.Args()
50+
if len(args) == 0 {
51+
usageAndExit("missing [command]")
52+
}
53+
54+
truncStdout := window.NewWriter(*maxFlag)
55+
truncStderr := window.NewWriter(*maxFlag)
56+
countedStdout := countingwriter.New(truncStdout)
57+
countedStderr := countingwriter.New(truncStderr)
58+
child := exec.Command(args[0], args[1:]...)
59+
child.Stdout = io.MultiWriter(os.Stdout, countedStdout)
60+
child.Stderr = io.MultiWriter(os.Stderr, countedStderr)
61+
62+
start := time.Now()
63+
err := child.Run()
64+
end := time.Now()
65+
66+
stdout := truncStdout.Bytes()
67+
stderr := truncStderr.Bytes()
68+
69+
r := &Result{
70+
Cmd: child,
71+
Error: err,
72+
Start: start,
73+
End: end,
74+
Duration: end.Sub(start),
75+
Stdout: string(stdout),
76+
Stderr: string(stderr),
77+
StdoutExtra: countedStdout.BytesWritten() - len(stdout),
78+
StderrExtra: countedStderr.BytesWritten() - len(stderr),
79+
}
80+
81+
me := identity()
82+
subject := *subjectFlag
83+
if subject == "" {
84+
subject = fmt.Sprintf("%s", child.Args)
85+
}
86+
87+
m := &Message{
88+
To: *toFlag,
89+
From: me,
90+
Subject: subject,
91+
Result: r,
92+
}
93+
94+
if err := findMailer().Send([]string{*toFlag}, me, m.Bytes()); err != nil {
95+
log.Fatal(err)
96+
}
97+
}

sendmail.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"os/exec"
6+
)
7+
8+
type SendMailMailer struct{}
9+
10+
func (m *SendMailMailer) Send(to []string, from string, body []byte) error {
11+
sendmail := exec.Command("sendmail", to...)
12+
sendmail.Stdin = bytes.NewReader(body)
13+
return sendmail.Run()
14+
}

smtp.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import "net/smtp"
4+
5+
type SMTPMailer struct{}
6+
7+
func (m *SMTPMailer) Send(to []string, from string, body []byte) error {
8+
return smtp.SendMail("localhost:25", nil, from, to, body)
9+
}

0 commit comments

Comments
 (0)