summaryrefslogtreecommitdiff
path: root/mailing/sendmail_mailer.go
blob: ad864fb737d84914160720495de66606fbe3f7ce (plain)
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
package mailing

import (
	"errors"
	"fmt"
	"github.com/kch42/simpleconf"
	"os/exec"
)

// SendmailMailer is a Mailer implementation that sends mail using a sendmail-ish executable.
//
// Sendmail-ish in this context means:
//
// 	* The executable must accept the from address using the `-f <addr>` switch
// 	* The executable must accept the to address as a parameter
// 	* The executable expects a mail (including all headers) on stdin that is terminated by EOF
type SendmailMailer struct {
	Exec string
	Args []string
}

func (sm SendmailMailer) Mail(to, from string, msg []byte) (outerr error) {
	off := len(sm.Args)
	args := make([]string, off+3)
	copy(args, sm.Args)
	args[off] = "-f"
	args[off+1] = from
	args[off+2] = to

	cmd := exec.Command(sm.Exec, args...)
	pipe, err := cmd.StdinPipe()
	if err != nil {
		return err
	}

	if err = cmd.Start(); err != nil {
		return err
	}
	defer func() {
		pipe.Close()
		err := cmd.Wait()
		if outerr == nil {
			outerr = err
		}
	}()

	_, err = pipe.Write(msg)
	return err
}

// SendmailMailerCreator creates an SendmailMailer using configuration values in the [mail] section.
//
// 	exec - The name of the executable
// 	argX - (optional) Additional arguments for the executable. X is a ascending number starting with 1
func SendmailMailerCreator(conf simpleconf.Config) (Mailer, error) {
	rv := SendmailMailer{}
	var err error

	if rv.Exec, err = conf.GetString("mail", "exec"); err != nil {
		return rv, errors.New("Missing [mail] exec config")
	}

	for i := 1; ; i++ {
		arg, err := conf.GetString("mail", fmt.Sprintf("arg%d", i))
		if err != nil {
			break
		}

		rv.Args = append(rv.Args, arg)
	}

	return rv, nil
}