message.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package idavollr
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "log"
  8. "github.com/emersion/go-imap"
  9. "github.com/emersion/go-imap/client"
  10. "github.com/emersion/go-message"
  11. )
  12. type AbstractImapMessage interface {
  13. Section() *imap.BodySectionName
  14. Message() *imap.Message
  15. MimeType() string
  16. SetMessageBytes([]byte)
  17. MessageBytes() []byte
  18. SetMimeMessage(*message.Entity)
  19. MimeMessage() *message.Entity
  20. SetMessageReader(io.Reader)
  21. MessageReader() io.Reader
  22. SetMessageBody([]byte)
  23. SetClient(*client.Client)
  24. Client() *client.Client
  25. }
  26. type ImapMessage struct {
  27. Sect *imap.BodySectionName
  28. Msg *imap.Message
  29. Mimetype string
  30. cli *client.Client
  31. msgBytes []byte
  32. mimeMsg *message.Entity
  33. bdyRdr io.Reader
  34. bdy []byte
  35. }
  36. func (m ImapMessage) Section() *imap.BodySectionName {
  37. return m.Sect
  38. }
  39. func (m ImapMessage) Message() *imap.Message {
  40. return m.Msg
  41. }
  42. func (m ImapMessage) MimeType() string {
  43. return m.Mimetype
  44. }
  45. func (m *ImapMessage) SetMessageBytes(b []byte) {
  46. m.msgBytes = b
  47. }
  48. func (m ImapMessage) MessageBytes() []byte {
  49. return m.msgBytes
  50. }
  51. func (m *ImapMessage) SetMimeMessage(msg *message.Entity) {
  52. m.mimeMsg = msg
  53. }
  54. func (m ImapMessage) MimeMessage() *message.Entity {
  55. return m.mimeMsg
  56. }
  57. func (m *ImapMessage) SetMessageReader(r io.Reader) {
  58. m.bdyRdr = r
  59. }
  60. func (m ImapMessage) MessageReader() io.Reader {
  61. return m.bdyRdr
  62. }
  63. func (m *ImapMessage) SetMessageBody(b []byte) {
  64. m.bdy = b
  65. }
  66. func (m ImapMessage) MessageBody() []byte {
  67. return m.bdy
  68. }
  69. func (m *ImapMessage) SetClient(c *client.Client) {
  70. m.cli = c
  71. }
  72. func (m ImapMessage) Client() *client.Client {
  73. return m.cli
  74. }
  75. func ReadMessageBody(m AbstractImapMessage) (AbstractImapMessage, error) {
  76. r := m.Message().GetBody(m.Section())
  77. if r == nil {
  78. return m, MalformedMessageError{
  79. Cause: errors.New("no body in message"),
  80. MessageID: m.Message().Envelope.MessageId,
  81. }
  82. }
  83. messageBytes, err := io.ReadAll(r)
  84. m.SetMessageBytes(messageBytes)
  85. return m, err
  86. }
  87. func ParseMimeMessage(m AbstractImapMessage) (AbstractImapMessage, error) {
  88. r := bytes.NewReader(m.MessageBytes())
  89. message, err := message.Read(r)
  90. m.SetMimeMessage(message)
  91. return m, err
  92. }
  93. func getNextPart(message *message.Entity, ID string, mimetype string) (io.Reader, error) {
  94. if mr := message.MultipartReader(); mr != nil {
  95. for {
  96. p, err := mr.NextPart()
  97. if err == io.EOF {
  98. break
  99. } else if err != nil {
  100. return nil, fmt.Errorf("while reading next part: %w", err)
  101. }
  102. return getNextPart(p, ID, mimetype)
  103. }
  104. } else {
  105. t, _, err := message.Header.ContentType()
  106. if err != nil {
  107. return nil, fmt.Errorf("while getting content type: %w", err)
  108. }
  109. if t == mimetype {
  110. return message.Body, nil
  111. }
  112. }
  113. return nil, MalformedMessageError{
  114. Cause: errors.New(mimetype + " not found"),
  115. MessageID: ID,
  116. }
  117. }
  118. func GetBody(m AbstractImapMessage) (AbstractImapMessage, error) {
  119. reader, err := getNextPart(m.MimeMessage(), m.Message().Envelope.MessageId, m.MimeType())
  120. m.SetMessageReader(reader)
  121. return m, err
  122. }
  123. func ReadBody(m AbstractImapMessage) (AbstractImapMessage, error) {
  124. body, err := io.ReadAll(m.MessageReader())
  125. m.SetMessageBody(body)
  126. return m, err
  127. }
  128. func RecoverMalformedMessage(m AbstractImapMessage, err error) (AbstractImapMessage, error) {
  129. var malformedMessageError MalformedMessageError
  130. if errors.As(err, &malformedMessageError) {
  131. err = nil
  132. log.Println(malformedMessageError.Error())
  133. log.Println(string(m.MessageBytes()))
  134. }
  135. return m, err
  136. }
  137. func RecoverErroredMessages(m AbstractImapMessage, err error) (AbstractImapMessage, error) {
  138. log.Printf("message %s errored: %v\n", m.Message().Envelope.MessageId, err)
  139. return m, nil
  140. }