強引にGoのメールでverpに対応する

GolangでVERP対応したくて色々と調べましたが
強引にやる方法しか思いつかなかったけどせっかく調べたので記録する。
ソースはこちらを参考にさせていただきました(感謝)
Golang Cafe #16 まとめ その2 smtpパッケージ

verpって単一の宛先のみでカンマ区切りだったりccだったりbccだったりは対応できないっぽいです。
送るなら1メール1ユーザにしないとダメ?

postfix設定

main.cf /etc/postfix/main.cf

1
2
3
recipient_delimiter = +
default_verp_delimiters = -=
smtpd_authorized_verp_clients = $mynetworks

以下sendMailはsmtp.SendMailと引数を一緒にしています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
func sendMail(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
  var client *smtp.Client
  var err error

  if client, err = smtp.Dial(addr); err != nil {
      fmt.Fprintf(os.Stderr, "Error: %v\n", err)
      os.Exit(1)
  }

  defer client.Close()

  if err = client.Hello("localhost"); err != nil {
      fmt.Fprintf(os.Stderr, "Error: %v\n", err)
      os.Exit(1)
  }

  if auth != nil {
      if err = client.Auth(auth); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }
  }

  for _, addr := range to {
      if err = client.Reset(); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }

      if err = mail(client, from); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }

      if err = client.Rcpt(addr); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }

      var w io.WriteCloser

      if w, err = client.Data(); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }

      if _, err = w.Write([]byte(msg)); err != nil {
          fmt.Fprintf(os.Stderr, "Error: %v\n", err)
          os.Exit(1)
      }

      w.Close()
  }

  if err = client.Quit(); err != nil {
      fmt.Fprintf(os.Stderr, "Error: %v\n", err)
      os.Exit(1)
  }

  return nil
}

func mail(c *smtp.Client, from string) error {
  cmdStr := "MAIL FROM:<%s> XVERP"

  // 8BITMIMEは考慮しない

  _, _, err := cmd(c, 250, cmdStr, from)
  return err
}

func cmd(c *smtp.Client, expectCode int, format string, args ...interface{}) (int, string, error) {
  id, err := c.Text.Cmd(format, args...)
  if err != nil {
      return 0, "", err
  }
  c.Text.StartResponse(id)
  defer c.Text.EndResponse(id)
  code, msg, err := c.Text.ReadResponse(expectCode)
  return code, msg, err
}

Comments