Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
.envrc
/cmdg
/med
/conductor/
9 changes: 5 additions & 4 deletions cmd/cmdg/cmdg.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,10 @@ var (
verbose = flag.Bool("verbose", false, "Turn on verbose logging.")
shell = flag.String("shell", "/bin/sh", "Shell to shell out to.")
versionFlag = flag.Bool("version", false, "Show version and exit.")
lynx = flag.String("lynx", "lynx", "HTML render binary.")
enableSign = flag.Bool("sign", false, "Send signed emails by default.")
imageProtocol = flag.String("image_protocol", "none", "Terminal image protocol (none, kitty, iterm2, auto).")

updateSender = flag.String("update_sender", "", `Update default sender address. E.g.: "John Doe" <john.doe@example.com>`)

conn *cmdg.CmdG

// Relative to configDir.
Expand Down Expand Up @@ -133,6 +132,9 @@ func run(ctx context.Context) error {
log.Errorf("Bailing due to error: %v", err)
}
log.Infof("MessageView returned, stopping keys")
if *imageProtocol != "none" {
cmdg.ClearImages(*imageProtocol)
}
keys.Stop()
log.Infof("Shutting down")
return nil
Expand All @@ -146,8 +148,7 @@ func main() {
syscall.Umask(0077)
flag.Parse()
cmdg.Version = version

cmdg.Lynx = *lynx
cmdg.PreferredImageProtocol = *imageProtocol

log.Infof("cmdg %s", version)

Expand Down
16 changes: 6 additions & 10 deletions cmd/cmdg/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ func getInput(ctx context.Context, prefill string, keys *input.Input) (string, e
// Stop UI.
keys.Stop()
defer func() {
if err := keys.Start(); err != nil {
log.Errorf("Failed to restart input: %v", err)
}
_ = keys.Start()
}()

cmd := exec.CommandContext(ctx, visualBinary, tmpf.Name())
Expand Down Expand Up @@ -272,11 +270,7 @@ func compose(ctx context.Context, conn *cmdg.CmdG, headOps []headOp, keys *input
break
}
}
/*
if a == "S" {
// TODO: also archive.
}
*/
// TODO: also archive if a == "S"
return nil
case "d":
st := time.Now()
Expand All @@ -293,7 +287,9 @@ func compose(ctx context.Context, conn *cmdg.CmdG, headOps []headOp, keys *input
break
}
if err != nil {
_ = dialog.Message("Failed to attach", fmt.Sprintf("Failed to attach file: %v", err), keys)
if err := dialog.Message("Failed to attach", fmt.Sprintf("Failed to attach file: %v", err), keys); err != nil {
log.Infof("Failed to show message: %v", err)
}
}
doEdit = false
attachments = append(attachments, f)
Expand Down Expand Up @@ -370,7 +366,7 @@ func chooseFile(ctx context.Context, keys *input.Input) (*file, error) {
// TODO: attach a ReadCloser?
b, err := ioutil.ReadFile(full)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "reading file %q", full)
}
return &file{
name: fis[o.KeyInt].Name(),
Expand Down
40 changes: 33 additions & 7 deletions cmd/cmdg/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ type fakeSend struct {

func (fs *fakeSend) bad(w http.ResponseWriter, f string, args ...interface{}) {
w.WriteHeader(http.StatusBadRequest)
if _, err := fmt.Fprintf(w, f, args...); err != nil {
fs.bad(w, "writing response failed: %v", err)
}
_, _ = fmt.Fprintf(w, f, args...)
}

func (fs *fakeSend) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -61,9 +59,7 @@ func (fs *fakeSend) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
fs.msg = string(raw)
w.WriteHeader(http.StatusOK)
if _, err := fmt.Fprintf(w, `{ "id": "12345" }`); err != nil {
fs.bad(w, "failed to write reply: %v", err)
}
_, _ = fmt.Fprintf(w, `{ "id": "12345" }`)
}

// net.RoundTripper that rewrites requests to the local fake.
Expand All @@ -84,7 +80,7 @@ func (redir *redirector) RoundTrip(r *http.Request) (*http.Response, error) {
}

func crnl(s string) string {
return strings.ReplaceAll(s, "\n", "\r\n")
return strings.Replace(s, "\n", "\r\n", -1)
}

func TestSendMessage(t *testing.T) {
Expand Down Expand Up @@ -208,6 +204,36 @@ Content-Disposition: inline
Content-Type: text/plain; charset="UTF-8"

World
--[a-z0-9]+--`)),
},
{
name: "With attachments",
msg: "To: foo@bar.com\nSubject: hello\n\nWorld",
attachments: []*file{
{name: "test1.txt", content: []byte("content1")},
{name: "test2.txt", content: []byte("content2")},
},
matching: regexp.MustCompile(crnl(`MIME-Version: 1.0
Subject: hello
To: foo@bar.com
Content-Type: multipart/mixed; boundary="[a-z0-9]+"
Content-Disposition: inline

--[a-z0-9]+
Content-Disposition: inline
Content-Type: text/plain; charset="UTF-8"

World
--[a-z0-9]+
Content-Disposition: attachment; filename="test1.txt"
Content-Type: application/octet-stream; name="test1.txt"

content1
--[a-z0-9]+
Content-Disposition: attachment; filename="test2.txt"
Content-Type: application/octet-stream; name="test2.txt"

content2
--[a-z0-9]+--`)),
},
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/cmdg/reply.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ func replyOrForward(ctx context.Context, conn *cmdg.CmdG, keys *input.Input, to,
prefill := strings.Join(headers, "\n") + "\n\n" + strings.Join(body, "\n")
refs, err := msg.GetReferences(ctx)
if err != nil {
// don't care
_ = err
log.Warningf("Failed to get references when replying: %v", err)
}

headOps := []headOp{
Expand Down
16 changes: 5 additions & 11 deletions cmd/cmdg/reply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"net/url"
Expand All @@ -29,14 +28,13 @@ func (h *mockGmailHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Raw string `json:"raw"`
}
if err := json.Unmarshal(content, &d); err != nil {
log.Fatalf("Failed to marshal: %v", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
raw, _ := base64.URLEncoding.DecodeString(d.Raw)
h.sentMsg = string(raw)
w.WriteHeader(http.StatusOK)
if _, err := fmt.Fprint(w, `{"id": "sent-123"}`); err != nil {
log.Fatalf("Failed to write reply: %v", err)
}
_, _ = fmt.Fprint(w, `{"id": "sent-123"}`)
return
}
if r.Method == "GET" && strings.Contains(r.URL.Path, "/messages/msg-123") && !strings.Contains(r.URL.Path, "/attachments") {
Expand All @@ -63,18 +61,14 @@ func (h *mockGmailHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
},
},
}
if err := json.NewEncoder(w).Encode(msg); err != nil {
log.Fatalf("Failed to encode: %v", err)
}
_ = json.NewEncoder(w).Encode(msg)
return
}
if r.Method == "GET" && strings.Contains(r.URL.Path, "/attachments/att-123") {
att := &gmail.MessagePartBody{
Data: base64.URLEncoding.EncodeToString([]byte("attachment content")),
}
if err := json.NewEncoder(w).Encode(att); err != nil {
log.Fatalf("Failed to encode: %v", err)
}
_ = json.NewEncoder(w).Encode(att)
return
}
w.WriteHeader(http.StatusNotFound)
Expand Down
3 changes: 1 addition & 2 deletions cmd/cmdg/view_messagelist.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ Press [enter] to exit
)

var (
//messageListReloadTime = time.Minute
messageListReloadTimeout = 40 * time.Second
messageListHistoryCheckTime = 10 * time.Second
messageListHistoryCheckTimeout = 10 * time.Second
Expand Down Expand Up @@ -713,7 +712,7 @@ func (mv *MessageView) Run(ctx context.Context) error {
switch key {
case "?", input.F1:
if err := help(messageListViewHelp, mv.keys); err != nil {
log.Infof("help() failed: %v", err)
log.Errorf("Failed to show help: %v", err)
}
case input.Enter, input.Right:
if len(mv.messages) == 0 {
Expand Down
Loading
Loading