From 69f20e56706ad7fb93813f4c3f2058bb6f85de30 Mon Sep 17 00:00:00 2001 From: Aine Date: Mon, 22 Aug 2022 18:43:12 +0300 Subject: [PATCH] try to receive attachments --- README.md | 3 +-- bot/bot.go | 25 +++++++++++++++++++++++-- smtp/server.go | 2 +- smtp/session.go | 29 ++++++++++++++++++++++++----- smtp/smtp.go | 3 ++- utils/file.go | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 utils/file.go diff --git a/README.md b/README.md index cafe5cd..b80f7c0 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,7 @@ An Email to Matrix bridge - [x] Matrix bot - [x] Configuration in room's account data - [x] Receive emails to matrix rooms -- [ ] **BUG**: no auto invites -- [ ] Receive attachments +- [x] Receive attachments (untested) - [ ] Map email threads to matrix threads ### Send diff --git a/bot/bot.go b/bot/bot.go index d2c8da0..1337071 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -71,7 +71,7 @@ func (b *Bot) Start() error { } // 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)] if !ok || roomID == "" { return errors.New("room not found") @@ -88,7 +88,28 @@ func (b *Bot) Send(from, to, subject, body string) error { content := format.RenderMarkdown(text.String(), true, true) _, err := b.lp.Send(roomID, content) - return err + if err != nil { + 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 diff --git a/smtp/server.go b/smtp/server.go index 61a1df9..7794baa 100644 --- a/smtp/server.go +++ b/smtp/server.go @@ -46,7 +46,7 @@ func Start(domain, port, loglevel string, client Client) error { s.AuthDisabled = true s.ReadTimeout = 10 * time.Second s.WriteTimeout = 10 * time.Second - s.MaxMessageBytes = 63 * 1024 + s.MaxMessageBytes = 128 * 1024 if log.GetLevel() == "DEBUG" || log.GetLevel() == "TRACE" { s.Debug = os.Stdout } diff --git a/smtp/session.go b/smtp/session.go index 0bdc22f..1927bb1 100644 --- a/smtp/session.go +++ b/smtp/session.go @@ -52,17 +52,36 @@ func (s *session) Rcpt(to string) error { 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 { parser := enmime.NewParser() - env, err := parser.ReadEnvelope(r) + eml, err := parser.ReadEnvelope(r) if err != nil { return err } - text := env.Text - if env.HTML != "" { - text = env.HTML + text := eml.Text + if eml.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() {} diff --git a/smtp/smtp.go b/smtp/smtp.go index 5ebe1ce..e954406 100644 --- a/smtp/smtp.go +++ b/smtp/smtp.go @@ -3,11 +3,12 @@ package smtp import ( "context" + "gitlab.com/etke.cc/postmoogle/utils" "maunium.net/go/mautrix/id" ) // Client interface to send emails type Client interface { 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 } diff --git a/utils/file.go b/utils/file.go new file mode 100644 index 0000000..25c6a98 --- /dev/null +++ b/utils/file.go @@ -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, + } +}