try to receive attachments
This commit is contained in:
@@ -10,8 +10,7 @@ An Email to Matrix bridge
|
|||||||
- [x] Matrix bot
|
- [x] Matrix bot
|
||||||
- [x] Configuration in room's account data
|
- [x] Configuration in room's account data
|
||||||
- [x] Receive emails to matrix rooms
|
- [x] Receive emails to matrix rooms
|
||||||
- [ ] **BUG**: no auto invites
|
- [x] Receive attachments (untested)
|
||||||
- [ ] Receive attachments
|
|
||||||
- [ ] Map email threads to matrix threads
|
- [ ] Map email threads to matrix threads
|
||||||
|
|
||||||
### Send
|
### Send
|
||||||
|
|||||||
23
bot/bot.go
23
bot/bot.go
@@ -71,7 +71,7 @@ func (b *Bot) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send email to matrix room
|
// Send email to matrix room
|
||||||
func (b *Bot) Send(from, to, subject, body string) error {
|
func (b *Bot) Send(ctx context.Context, from, to, subject, body string, files []*utils.File) error {
|
||||||
roomID, ok := b.rooms[utils.Mailbox(to)]
|
roomID, ok := b.rooms[utils.Mailbox(to)]
|
||||||
if !ok || roomID == "" {
|
if !ok || roomID == "" {
|
||||||
return errors.New("room not found")
|
return errors.New("room not found")
|
||||||
@@ -88,9 +88,30 @@ func (b *Bot) Send(from, to, subject, body string) error {
|
|||||||
|
|
||||||
content := format.RenderMarkdown(text.String(), true, true)
|
content := format.RenderMarkdown(text.String(), true, true)
|
||||||
_, err := b.lp.Send(roomID, content)
|
_, err := b.lp.Send(roomID, content)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
req := file.Convert()
|
||||||
|
resp, err := b.lp.GetClient().UploadMedia(req)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(ctx, roomID, "cannot upload file %s: %v", req.FileName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = b.lp.Send(roomID, &event.MessageEventContent{
|
||||||
|
MsgType: event.MsgFile,
|
||||||
|
Body: req.FileName,
|
||||||
|
URL: resp.ContentURI.CUString(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
b.Error(ctx, roomID, "cannot send uploaded file %s: %v", req.FileName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetMappings returns mapping of mailbox = room
|
// GetMappings returns mapping of mailbox = room
|
||||||
func (b *Bot) GetMappings(ctx context.Context) (map[string]id.RoomID, error) {
|
func (b *Bot) GetMappings(ctx context.Context) (map[string]id.RoomID, error) {
|
||||||
if len(b.rooms) == 0 {
|
if len(b.rooms) == 0 {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func Start(domain, port, loglevel string, client Client) error {
|
|||||||
s.AuthDisabled = true
|
s.AuthDisabled = true
|
||||||
s.ReadTimeout = 10 * time.Second
|
s.ReadTimeout = 10 * time.Second
|
||||||
s.WriteTimeout = 10 * time.Second
|
s.WriteTimeout = 10 * time.Second
|
||||||
s.MaxMessageBytes = 63 * 1024
|
s.MaxMessageBytes = 128 * 1024
|
||||||
if log.GetLevel() == "DEBUG" || log.GetLevel() == "TRACE" {
|
if log.GetLevel() == "DEBUG" || log.GetLevel() == "TRACE" {
|
||||||
s.Debug = os.Stdout
|
s.Debug = os.Stdout
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,17 +52,36 @@ func (s *session) Rcpt(to string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *session) parseAttachments(parts []*enmime.Part) []*utils.File {
|
||||||
|
files := make([]*utils.File, 0, len(parts))
|
||||||
|
for _, attachment := range parts {
|
||||||
|
for _, err := range attachment.Errors {
|
||||||
|
s.log.Warn("attachment error: %v", err)
|
||||||
|
}
|
||||||
|
file := utils.NewFile(attachment.FileName, attachment.ContentType, attachment.Content)
|
||||||
|
files = append(files, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
func (s *session) Data(r io.Reader) error {
|
func (s *session) Data(r io.Reader) error {
|
||||||
parser := enmime.NewParser()
|
parser := enmime.NewParser()
|
||||||
env, err := parser.ReadEnvelope(r)
|
eml, err := parser.ReadEnvelope(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
text := env.Text
|
text := eml.Text
|
||||||
if env.HTML != "" {
|
if eml.HTML != "" {
|
||||||
text = env.HTML
|
text = eml.HTML
|
||||||
}
|
}
|
||||||
return s.client.Send(s.from, s.to, env.GetHeader("Subject"), text)
|
|
||||||
|
attachments := s.parseAttachments(eml.Attachments)
|
||||||
|
inlines := s.parseAttachments(eml.Inlines)
|
||||||
|
files := make([]*utils.File, 0, len(attachments)+len(inlines))
|
||||||
|
files = append(files, attachments...)
|
||||||
|
files = append(files, inlines...)
|
||||||
|
return s.client.Send(s.ctx, s.from, s.to, eml.GetHeader("Subject"), text, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) Reset() {}
|
func (s *session) Reset() {}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ package smtp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"gitlab.com/etke.cc/postmoogle/utils"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client interface to send emails
|
// Client interface to send emails
|
||||||
type Client interface {
|
type Client interface {
|
||||||
GetMappings(context.Context) (map[string]id.RoomID, error)
|
GetMappings(context.Context) (map[string]id.RoomID, error)
|
||||||
Send(from, mailbox, subject, body string) error
|
Send(ctx context.Context, from, mailbox, subject, body string, files []*utils.File) error
|
||||||
}
|
}
|
||||||
|
|||||||
35
utils/file.go
Normal file
35
utils/file.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"maunium.net/go/mautrix"
|
||||||
|
)
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
Length int
|
||||||
|
Content []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFile(name, contentType string, content []byte) *File {
|
||||||
|
file := &File{
|
||||||
|
Name: name,
|
||||||
|
Type: contentType,
|
||||||
|
Content: content,
|
||||||
|
}
|
||||||
|
file.Length = len(content)
|
||||||
|
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Convert() mautrix.ReqUploadMedia {
|
||||||
|
return mautrix.ReqUploadMedia{
|
||||||
|
ContentBytes: f.Content,
|
||||||
|
Content: bytes.NewReader(f.Content),
|
||||||
|
ContentLength: int64(f.Length),
|
||||||
|
ContentType: f.Type,
|
||||||
|
FileName: f.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user