imap.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package main
  2. import (
  3. "io"
  4. "log"
  5. "mime"
  6. "mime/quotedprintable"
  7. "strings"
  8. "github.com/emersion/go-imap"
  9. "github.com/emersion/go-imap-move"
  10. "github.com/emersion/go-imap/client"
  11. "github.com/emersion/go-sasl"
  12. "github.com/emersion/go-smtp"
  13. )
  14. func moveMsg(c *client.Client, msg *imap.Message, dest string) {
  15. log.Printf("moving %v : %s from %s to %s\n", msg.Envelope.Date, msg.Envelope.Subject, msg.Envelope.From[0].Address(), dest)
  16. moveClient := move.NewClient(c)
  17. seqSet := new(imap.SeqSet)
  18. seqSet.AddNum(msg.Uid)
  19. moveClient.UidMoveWithFallback(seqSet, dest)
  20. }
  21. func moveMultiple(c *client.Client, seqSet *imap.SeqSet, dest string) error {
  22. moveClient := move.NewClient(c)
  23. if !seqSet.Empty() {
  24. log.Println("moving multiple to " + dest)
  25. err := moveClient.UidMoveWithFallback(seqSet, dest)
  26. return err
  27. }
  28. return nil
  29. }
  30. func moveFromQuarantine(c *client.Client, mbox *imap.MailboxStatus, address, dest string) error {
  31. log.Printf("moving %s from quarantine to %s\n", address, dest)
  32. moveClient := move.NewClient(c)
  33. from := uint32(1)
  34. to := mbox.Messages
  35. allMessagesSet := new(imap.SeqSet)
  36. allMessagesSet.AddRange(from, to)
  37. var err error = nil
  38. messages := make(chan *imap.Message, 10)
  39. done := make(chan error, 1)
  40. go func() {
  41. done <- c.Fetch(allMessagesSet, []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid}, messages)
  42. }()
  43. moveSet := new(imap.SeqSet)
  44. for msg := range messages {
  45. sender := msg.Envelope.From[0]
  46. if sender.Address() == address {
  47. moveSet.AddNum(msg.Uid)
  48. }
  49. }
  50. if !moveSet.Empty() {
  51. err = moveClient.UidMoveWithFallback(moveSet, dest)
  52. }
  53. if err := <-done; err != nil {
  54. return err
  55. }
  56. return err
  57. }
  58. func sendRepeatedQuarantine(address *imap.Address, lock Lock) {
  59. // todo
  60. log.Printf("sending repeated quarantine to %s from %+v\n", address.Address(), lock)
  61. }
  62. func sendQuarantine(address *imap.Address) {
  63. // todo
  64. log.Printf("sending quarantine to %s\n", address.Address())
  65. }
  66. func forwardMessage(config Config, category, messageID, inReplyTo, subject string, body []byte, recipients []string, sender *imap.Address) error {
  67. // todo reformat, errors, &c.
  68. msg := "To: " + strings.Join(recipients, ", ") + "\r\n" +
  69. "From: " + makeNameAddress(sender, true) + "\r\n" +
  70. "Message-ID: " + messageID + "\r\n" +
  71. "Subject: " + mime.QEncoding.Encode("utf-8", subject) + "\r\n"
  72. if inReplyTo != "" {
  73. msg = msg + "In-Reply-To: " + inReplyTo + "\r\n"
  74. }
  75. msg += "Reply-To: " + mime.QEncoding.Encode("utf-8", strings.Replace(config.Mimir.RecipientTemplate, "[:]", category, 1)) + "\r\n" +
  76. "Content-Type: text/plain; charset=utf-8\r\n" +
  77. "Content-Transfer-Encoding: quoted-printable\r\n" +
  78. "\r\n"
  79. msgReader := strings.NewReader(msg)
  80. auth := sasl.NewPlainClient("", config.Mimir.ImapUsername, config.Mimir.ImapPassword)
  81. c, err := smtp.DialTLS(config.Mimir.SmtpAddress, nil)
  82. if err != nil {
  83. log.Fatal(err)
  84. }
  85. if err = c.Auth(auth); err != nil {
  86. log.Fatal(err)
  87. }
  88. if err := c.Mail(config.Mimir.SmtpSender, nil); err != nil {
  89. log.Fatal(err)
  90. }
  91. for _, recipient := range recipients {
  92. if err := c.Rcpt(recipient); err != nil {
  93. log.Fatal(err)
  94. }
  95. }
  96. wc, err := c.Data()
  97. if err != nil {
  98. log.Fatal(err)
  99. }
  100. _, err = io.Copy(wc, msgReader)
  101. qpWriter := quotedprintable.NewWriter(wc)
  102. _, err = qpWriter.Write(body)
  103. _, err = qpWriter.Write([]byte("\r\n"))
  104. if err != nil {
  105. log.Fatal(err)
  106. }
  107. err = wc.Close()
  108. if err != nil {
  109. log.Fatal(err)
  110. }
  111. err = c.Quit()
  112. if err != nil {
  113. log.Fatal(err)
  114. }
  115. return nil
  116. }
  117. func removeMessage(c *client.Client, msgUid uint32, mailbox string) error {
  118. _, err := c.Select(mailbox, false)
  119. if err != nil {
  120. return err
  121. }
  122. seqset := new(imap.SeqSet)
  123. seqset.AddNum(msgUid)
  124. item := imap.FormatFlagsOp(imap.AddFlags, true)
  125. flags := []interface{}{imap.DeletedFlag}
  126. return c.UidStore(seqset, item, flags, nil)
  127. }