A webmail client. Forked from https://git.sr.ht/~migadu/alps
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

113 行
2.3 KiB

  1. package koushin
  2. import (
  3. "fmt"
  4. "time"
  5. "io"
  6. "github.com/emersion/go-message/mail"
  7. "github.com/emersion/go-smtp"
  8. )
  9. func (s *Server) connectSMTP() (*smtp.Client, error) {
  10. var c *smtp.Client
  11. var err error
  12. if s.smtp.tls {
  13. c, err = smtp.DialTLS(s.smtp.host, nil)
  14. if err != nil {
  15. return nil, fmt.Errorf("failed to connect to SMTPS server: %v", err)
  16. }
  17. } else {
  18. c, err = smtp.Dial(s.smtp.host)
  19. if err != nil {
  20. return nil, fmt.Errorf("failed to connect to SMTP server: %v", err)
  21. }
  22. if !s.smtp.insecure {
  23. if err := c.StartTLS(nil); err != nil {
  24. c.Close()
  25. return nil, fmt.Errorf("STARTTLS failed: %v", err)
  26. }
  27. }
  28. }
  29. return c, err
  30. }
  31. type OutgoingMessage struct {
  32. from string
  33. to []string
  34. subject string
  35. text string
  36. }
  37. func (msg *OutgoingMessage) WriteTo(w io.Writer) error {
  38. from := []*mail.Address{{"", msg.from}}
  39. to := make([]*mail.Address, len(msg.to))
  40. for i, addr := range msg.to {
  41. to[i] = &mail.Address{"", addr}
  42. }
  43. var h mail.Header
  44. h.SetDate(time.Now())
  45. h.SetAddressList("From", from)
  46. h.SetAddressList("To", to)
  47. h.SetText("Subject", msg.subject)
  48. mw, err := mail.CreateWriter(w, h)
  49. if err != nil {
  50. return fmt.Errorf("failed to create mail writer: %v", err)
  51. }
  52. var th mail.InlineHeader
  53. th.Set("Content-Type", "text/plain; charset=utf-8")
  54. tw, err := mw.CreateSingleInline(th)
  55. if err != nil {
  56. return fmt.Errorf("failed to create text part: %v", err)
  57. }
  58. defer tw.Close()
  59. if _, err := io.WriteString(tw, msg.text); err != nil {
  60. return fmt.Errorf("failed to write text part: %v", err)
  61. }
  62. if err := tw.Close(); err != nil {
  63. return fmt.Errorf("failed to close text part: %v", err)
  64. }
  65. if err := mw.Close(); err != nil {
  66. return fmt.Errorf("failed to close mail writer: %v", err)
  67. }
  68. return nil
  69. }
  70. func sendMessage(c *smtp.Client, msg *OutgoingMessage) error {
  71. if err := c.Mail(msg.from, nil); err != nil {
  72. return fmt.Errorf("MAIL FROM failed: %v", err)
  73. }
  74. for _, to := range msg.to {
  75. if err := c.Rcpt(to); err != nil {
  76. return fmt.Errorf("RCPT TO failed: %v", err)
  77. }
  78. }
  79. w, err := c.Data()
  80. if err != nil {
  81. return fmt.Errorf("DATA failed: %v", err)
  82. }
  83. defer w.Close()
  84. if err := msg.WriteTo(w); err != nil {
  85. return fmt.Errorf("failed to write outgoing message: %v", err)
  86. }
  87. if err := w.Close(); err != nil {
  88. return fmt.Errorf("failed to close SMTP data writer: %v", err)
  89. }
  90. return nil
  91. }