Add :send-message, prepares & writes email to /tmp
This commit is contained in:
parent
d5e82ecfe0
commit
6c36e04c1f
|
@ -0,0 +1,29 @@
|
||||||
|
package compose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc2/widgets"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register("send-message", SendMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendMessage(aerc *widgets.Aerc, args []string) error {
|
||||||
|
if len(args) > 1 {
|
||||||
|
return errors.New("Usage: send-message")
|
||||||
|
}
|
||||||
|
composer, _ := aerc.SelectedTab().(*widgets.Composer)
|
||||||
|
//config := composer.Config()
|
||||||
|
f, err := os.Create("/tmp/test.eml")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
_, err = composer.Message(f)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
3
go.mod
3
go.mod
|
@ -6,7 +6,7 @@ require (
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
|
||||||
github.com/emersion/go-imap v1.0.0-beta.4
|
github.com/emersion/go-imap v1.0.0-beta.4
|
||||||
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b
|
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b
|
||||||
github.com/emersion/go-message v0.9.2
|
github.com/emersion/go-message v0.10.0
|
||||||
github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 // indirect
|
github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 // indirect
|
||||||
github.com/gdamore/tcell v1.0.0
|
github.com/gdamore/tcell v1.0.0
|
||||||
github.com/go-ini/ini v1.42.0
|
github.com/go-ini/ini v1.42.0
|
||||||
|
@ -20,6 +20,5 @@ require (
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae // indirect
|
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae // indirect
|
||||||
golang.org/x/text v0.3.2 // indirect
|
|
||||||
gopkg.in/ini.v1 v1.42.0 // indirect
|
gopkg.in/ini.v1 v1.42.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -10,9 +10,14 @@ github.com/emersion/go-imap v1.0.0-beta.4 h1:QglkDofK1RhU471SqcHxzRlSuPsCL6YpFc+
|
||||||
github.com/emersion/go-imap v1.0.0-beta.4/go.mod h1:mOPegfAgLVXbhRm1bh2JTX08z2Y3HYmKYpbrKDeAzsQ=
|
github.com/emersion/go-imap v1.0.0-beta.4/go.mod h1:mOPegfAgLVXbhRm1bh2JTX08z2Y3HYmKYpbrKDeAzsQ=
|
||||||
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b h1:q4qkNe/W10qFGD3RWd4meQTkD0+Zrz0L4ekMvlptg60=
|
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b h1:q4qkNe/W10qFGD3RWd4meQTkD0+Zrz0L4ekMvlptg60=
|
||||||
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b/go.mod h1:o14zPKCmEH5WC1vU5SdPoZGgNvQx7zzKSnxPQlobo78=
|
github.com/emersion/go-imap-idle v0.0.0-20180114101550-2af93776db6b/go.mod h1:o14zPKCmEH5WC1vU5SdPoZGgNvQx7zzKSnxPQlobo78=
|
||||||
|
github.com/emersion/go-message v0.9.1 h1:s6HoJ6t+1wHWEs0G/QVR1r5bb6nvx2/b6DuQfknit14=
|
||||||
github.com/emersion/go-message v0.9.1/go.mod h1:m3cK90skCWxm5sIMs1sXxly4Tn9Plvcf6eayHZJ1NzM=
|
github.com/emersion/go-message v0.9.1/go.mod h1:m3cK90skCWxm5sIMs1sXxly4Tn9Plvcf6eayHZJ1NzM=
|
||||||
github.com/emersion/go-message v0.9.2 h1:rJmtGZO1Z71PJDQXbC31EwzlJCsA/8kya6GnebSGp6I=
|
github.com/emersion/go-message v0.9.2 h1:rJmtGZO1Z71PJDQXbC31EwzlJCsA/8kya6GnebSGp6I=
|
||||||
github.com/emersion/go-message v0.9.2/go.mod h1:m3cK90skCWxm5sIMs1sXxly4Tn9Plvcf6eayHZJ1NzM=
|
github.com/emersion/go-message v0.9.2/go.mod h1:m3cK90skCWxm5sIMs1sXxly4Tn9Plvcf6eayHZJ1NzM=
|
||||||
|
github.com/emersion/go-message v0.9.3-0.20190413201152-1e345aac1fa8 h1:yFBYnt6PWNC+PQO70xOI3oayW6alYPRmCN1y0oOfgmQ=
|
||||||
|
github.com/emersion/go-message v0.9.3-0.20190413201152-1e345aac1fa8/go.mod h1:XQBEXJJ+6gGcjLsa3rYvGwTC7IJAIWQuxiTIcUKcIbc=
|
||||||
|
github.com/emersion/go-message v0.10.0 h1:V8hwhZPNIuAIGNLcMZiCzzavUIiODG3COYLsQMBLvG4=
|
||||||
|
github.com/emersion/go-message v0.10.0/go.mod h1:7d2eJfhjiJSnlaKcUPq7sEC7ekWELG6F5Lw2BxOGj6Y=
|
||||||
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 h1:rDJPbyliyym8ZL/Wt71kdolp6yaD4fLIQz638E6JEt0=
|
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197 h1:rDJPbyliyym8ZL/Wt71kdolp6yaD4fLIQz638E6JEt0=
|
||||||
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
github.com/emersion/go-sasl v0.0.0-20161116183048-7e096a0a6197/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||||
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
|
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
package widgets
|
package widgets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
gomail "net/mail"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/emersion/go-message"
|
||||||
|
"github.com/emersion/go-message/mail"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
|
|
||||||
|
@ -79,6 +84,9 @@ func NewComposer(conf *config.AccountConfig) *Composer {
|
||||||
focused: 1,
|
focused: 1,
|
||||||
focusable: []ui.DrawableInteractive{from, to, subject, term},
|
focusable: []ui.DrawableInteractive{from, to, subject, term},
|
||||||
}
|
}
|
||||||
|
c.headers.to = to
|
||||||
|
c.headers.from = from
|
||||||
|
c.headers.subject = subject
|
||||||
|
|
||||||
term.OnClose = c.termClosed
|
term.OnClose = c.termClosed
|
||||||
|
|
||||||
|
@ -107,6 +115,77 @@ func (c *Composer) Focus(focus bool) {
|
||||||
c.focusable[c.focused].Focus(focus)
|
c.focusable[c.focused].Focus(focus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Composer) Config() *config.AccountConfig {
|
||||||
|
return c.config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the email to the given writer, and returns a list of recipients
|
||||||
|
func (c *Composer) Message(writeto io.Writer) ([]string, error) {
|
||||||
|
// Extract headers from the email, if present
|
||||||
|
c.email.Seek(0, os.SEEK_SET)
|
||||||
|
var (
|
||||||
|
rcpts []string
|
||||||
|
header mail.Header
|
||||||
|
body io.Reader
|
||||||
|
)
|
||||||
|
reader, err := mail.CreateReader(c.email)
|
||||||
|
if err == nil {
|
||||||
|
header = reader.Header
|
||||||
|
// TODO: Do we want to let users write a full blown multipart email
|
||||||
|
// into the editor? If so this needs to change
|
||||||
|
part, err := reader.NextPart()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body = part.Body
|
||||||
|
defer reader.Close()
|
||||||
|
} else {
|
||||||
|
c.email.Seek(0, os.SEEK_SET)
|
||||||
|
body = c.email
|
||||||
|
}
|
||||||
|
// Update headers
|
||||||
|
// TODO: Custom header fields
|
||||||
|
mhdr := (*message.Header)(&header.Header)
|
||||||
|
mhdr.SetContentType("text/plain", map[string]string{"charset": "UTF-8"})
|
||||||
|
if subject, _ := header.Subject(); subject == "" {
|
||||||
|
header.SetSubject(c.headers.subject.input.String())
|
||||||
|
}
|
||||||
|
if date, err := header.Date(); err != nil && date != (time.Time{}) {
|
||||||
|
header.SetDate(time.Now())
|
||||||
|
}
|
||||||
|
if from, _ := mhdr.Text("From"); from == "" {
|
||||||
|
mhdr.SetText("From", c.headers.from.input.String())
|
||||||
|
}
|
||||||
|
if to := c.headers.to.input.String(); to != "" {
|
||||||
|
// Dammit Simon, this branch is 3x as long as it ought to be because
|
||||||
|
// your types aren't compatible enough with each other
|
||||||
|
to_rcpts, err := gomail.ParseAddressList(to)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ed_rcpts, err := header.AddressList("To")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, addr := range to_rcpts {
|
||||||
|
ed_rcpts = append(ed_rcpts, (*mail.Address)(addr))
|
||||||
|
}
|
||||||
|
header.SetAddressList("To", ed_rcpts)
|
||||||
|
for _, addr := range ed_rcpts {
|
||||||
|
rcpts = append(rcpts, addr.Address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Add cc, bcc to rcpts
|
||||||
|
// TODO: attachments
|
||||||
|
writer, err := mail.CreateSingleInlineWriter(writeto, header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
io.Copy(writer, body)
|
||||||
|
return rcpts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Composer) termClosed(err error) {
|
func (c *Composer) termClosed(err error) {
|
||||||
// TODO: do we care about that error (note: yes, we do)
|
// TODO: do we care about that error (note: yes, we do)
|
||||||
c.grid.RemoveChild(c.editor)
|
c.grid.RemoveChild(c.editor)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/danwakefield/fnmatch"
|
"github.com/danwakefield/fnmatch"
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
"github.com/emersion/go-message"
|
"github.com/emersion/go-message"
|
||||||
|
_ "github.com/emersion/go-message/charset"
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
|
@ -109,7 +110,8 @@ func NewMessageViewer(conf *config.AercConfig, store *lib.MessageStore,
|
||||||
pager = exec.Command(cmd[0], cmd[1:]...)
|
pager = exec.Command(cmd[0], cmd[1:]...)
|
||||||
|
|
||||||
for _, f := range conf.Filters {
|
for _, f := range conf.Filters {
|
||||||
mime := strings.ToLower(msg.BodyStructure.MIMEType) + "/" + strings.ToLower(msg.BodyStructure.MIMESubType)
|
mime := strings.ToLower(msg.BodyStructure.MIMEType) +
|
||||||
|
"/" + strings.ToLower(msg.BodyStructure.MIMESubType)
|
||||||
switch f.FilterType {
|
switch f.FilterType {
|
||||||
case config.FILTER_MIMETYPE:
|
case config.FILTER_MIMETYPE:
|
||||||
if fnmatch.Match(f.Filter, mime, 0) {
|
if fnmatch.Match(f.Filter, mime, 0) {
|
||||||
|
@ -181,11 +183,12 @@ handle_error:
|
||||||
|
|
||||||
func (mv *MessageViewer) attemptCopy() {
|
func (mv *MessageViewer) attemptCopy() {
|
||||||
if mv.source != nil && mv.pager.Process != nil {
|
if mv.source != nil && mv.pager.Process != nil {
|
||||||
header := make(message.Header)
|
header := message.Header{}
|
||||||
header.Set("Content-Transfer-Encoding", mv.msg.BodyStructure.Encoding)
|
header.SetText("Content-Transfer-Encoding",
|
||||||
|
mv.msg.BodyStructure.Encoding)
|
||||||
header.SetContentType(
|
header.SetContentType(
|
||||||
mv.msg.BodyStructure.MIMEType, mv.msg.BodyStructure.Params)
|
mv.msg.BodyStructure.MIMEType, mv.msg.BodyStructure.Params)
|
||||||
header.SetContentDescription(mv.msg.BodyStructure.Description)
|
header.SetText("Content-Description", mv.msg.BodyStructure.Description)
|
||||||
if mv.filter != nil {
|
if mv.filter != nil {
|
||||||
stdout, _ := mv.filter.StdoutPipe()
|
stdout, _ := mv.filter.StdoutPipe()
|
||||||
mv.filter.Start()
|
mv.filter.Start()
|
||||||
|
|
Loading…
Reference in New Issue