init: pristine aerc 0.20.0 source
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
package jmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/lib/log"
|
||||
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||
"git.sr.ht/~rockorager/go-jmap"
|
||||
"git.sr.ht/~rockorager/go-jmap/mail/email"
|
||||
"git.sr.ht/~rockorager/go-jmap/mail/emailsubmission"
|
||||
"git.sr.ht/~rockorager/go-jmap/mail/mailbox"
|
||||
"github.com/emersion/go-message/mail"
|
||||
)
|
||||
|
||||
func (w *JMAPWorker) handleStartSend(msg *types.StartSendingMessage) error {
|
||||
reader, writer := io.Pipe()
|
||||
send := &jmapSendWriter{writer: writer, done: make(chan error)}
|
||||
|
||||
w.w.PostMessage(&types.MessageWriter{
|
||||
Message: types.RespondTo(msg),
|
||||
Writer: send,
|
||||
}, nil)
|
||||
|
||||
go func() {
|
||||
defer log.PanicHandler()
|
||||
defer close(send.done)
|
||||
|
||||
identity, err := w.getSenderIdentity(msg.From)
|
||||
if err != nil {
|
||||
send.done <- err
|
||||
return
|
||||
}
|
||||
|
||||
blob, err := w.Upload(reader)
|
||||
if err != nil {
|
||||
send.done <- err
|
||||
return
|
||||
}
|
||||
|
||||
var req jmap.Request
|
||||
|
||||
// Import the blob into drafts
|
||||
req.Invoke(&email.Import{
|
||||
Account: w.AccountId(),
|
||||
Emails: map[string]*email.EmailImport{
|
||||
"aerc": {
|
||||
BlobID: blob.ID,
|
||||
MailboxIDs: map[jmap.ID]bool{
|
||||
w.roles[mailbox.RoleDrafts]: true,
|
||||
},
|
||||
Keywords: map[string]bool{
|
||||
"$draft": true,
|
||||
"$seen": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
from := &emailsubmission.Address{Email: msg.From.Address}
|
||||
var rcpts []*emailsubmission.Address
|
||||
for _, address := range msg.Rcpts {
|
||||
rcpts = append(rcpts, &emailsubmission.Address{
|
||||
Email: address.Address,
|
||||
})
|
||||
}
|
||||
envelope := &emailsubmission.Envelope{MailFrom: from, RcptTo: rcpts}
|
||||
onSuccess := jmap.Patch{
|
||||
"keywords/$draft": nil,
|
||||
w.rolePatch(mailbox.RoleSent): true,
|
||||
w.rolePatch(mailbox.RoleDrafts): nil,
|
||||
}
|
||||
for _, dir := range msg.CopyTo {
|
||||
mbox, ok := w.dir2mbox[dir]
|
||||
if ok && mbox != w.roles[mailbox.RoleSent] {
|
||||
onSuccess[w.mboxPatch(mbox)] = true
|
||||
}
|
||||
}
|
||||
// Create the submission
|
||||
req.Invoke(&emailsubmission.Set{
|
||||
Account: w.AccountId(),
|
||||
Create: map[jmap.ID]*emailsubmission.EmailSubmission{
|
||||
"sub": {
|
||||
IdentityID: identity,
|
||||
EmailID: "#aerc",
|
||||
Envelope: envelope,
|
||||
},
|
||||
},
|
||||
OnSuccessUpdateEmail: map[jmap.ID]jmap.Patch{
|
||||
"#sub": onSuccess,
|
||||
},
|
||||
})
|
||||
|
||||
resp, err := w.Do(&req)
|
||||
if err != nil {
|
||||
send.done <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, inv := range resp.Responses {
|
||||
switch r := inv.Args.(type) {
|
||||
case *email.ImportResponse:
|
||||
if err, ok := r.NotCreated["aerc"]; ok {
|
||||
send.done <- wrapSetError(err)
|
||||
return
|
||||
}
|
||||
case *emailsubmission.SetResponse:
|
||||
if err, ok := r.NotCreated["sub"]; ok {
|
||||
send.done <- wrapSetError(err)
|
||||
return
|
||||
}
|
||||
case *jmap.MethodError:
|
||||
send.done <- wrapMethodError(r)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type jmapSendWriter struct {
|
||||
writer *io.PipeWriter
|
||||
done chan error
|
||||
}
|
||||
|
||||
func (w *jmapSendWriter) Write(data []byte) (int, error) {
|
||||
return w.writer.Write(data)
|
||||
}
|
||||
|
||||
func (w *jmapSendWriter) Close() error {
|
||||
writeErr := w.writer.Close()
|
||||
sendErr := <-w.done
|
||||
if writeErr != nil {
|
||||
return writeErr
|
||||
}
|
||||
return sendErr
|
||||
}
|
||||
|
||||
func (w *JMAPWorker) getSenderIdentity(from *mail.Address) (jmap.ID, error) {
|
||||
if len(w.identities) == 0 {
|
||||
if err := w.GetIdentities(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
name, domain, _ := strings.Cut(from.Address, "@")
|
||||
for _, ident := range w.identities {
|
||||
n, d, _ := strings.Cut(ident.Email, "@")
|
||||
switch {
|
||||
case n == name && d == domain:
|
||||
fallthrough
|
||||
case n == "*" && d == domain:
|
||||
return ident.ID, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no identity found for address: %s@%s", name, domain)
|
||||
}
|
||||
Reference in New Issue
Block a user