func sendmail(m *gomail.Message, name string, arg ...string) (output []byte, err error) {
	cmd := exec.Command(name, arg...)
	cmd.Stderr = os.Stderr
	buf := new(bytes.Buffer)
	cmd.Stdout, cmd.Stderr = buf, os.Stderr
	w, err := cmd.StdinPipe()
	if err != nil {
		return nil, err
	}
	if err = cmd.Start(); err != nil {
		return nil, err
	}
	if _, err := m.WriteTo(w); err != nil {
		return nil, err
	}
	w.Close()
	err = cmd.Wait()
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
sendmail runs the given named command with arguments and dumps the message
to standard input. Standard output of the command is returned.
package email
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/mail"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"text/template"
	"time"
	"gopkg.in/gomail.v2"
)
const msgTmpl = `
{{ define "subject" -}}
Multipass Login
{{- end }}
{{ define "text/plain" }}
Hi,
You requested a Multipass access token. Please follow the link to login.
	{{.LoginURL}}
Didn't request an access token? Please ignore this message, no harm done.
Be secure,
Multipass Bot
{{ end }}
{{ define "text/html" }}
<p>Hi,<p>
<p>You requested a Multipass access token. Please follow the link to login.</p>
<p><a href="{{.LoginURL}}">Multipass Login Link</a></p>
<p>Didn't request an access token? Please ignore this message, no harm done.</p>
<p>Be secure,</p>
<p>Multipass Bot</p>
{{ end }}
`
var (
	ErrInvalidHandle   = errors.New("invalid handle")
	ErrInvalidResource = errors.New("invalid resource")
	ErrInvalidAddress  = errors.New("invalid address")
)
type UserService struct {
	from     *mail.Address
	template *template.Template
	lock      sync.Mutex
	handles   []string
	resources []string
	channel chan *gomail.Message
}
type Options struct {
	FromAddr                     string
	SMTPAddr, SMTPUser, SMTPPass string
	SMTPClientName               string
	SMTPClientArgs               []string
	MailTemplate                 string
}
func NewUserService(opt Options) (*UserService, error) {
	s := &UserService{}
	from, err := mail.ParseAddress(opt.FromAddr)
	if err != nil {
		return nil, err
	}
	s.from = from
	s.template = template.Must(template.New("").Parse(msgTmpl))
	if opt.MailTemplate != "" {
		if _, err := s.template.ParseFiles(opt.MailTemplate); err != nil {
			log.Println("ignoring invalid mail template at", opt.MailTemplate)
		}
	}
	s.channel = make(chan *gomail.Message)
	switch opt.SMTPClientName != "" {
	case true:
		go runMSA(s.channel, opt.SMTPClientName, opt.SMTPClientArgs...)
	default:
		host := "localhost"
		port := 25
		if len(opt.SMTPAddr) > 0 {
			host = opt.SMTPAddr
		}
		h, p, err := net.SplitHostPort(opt.SMTPAddr)
		if err == nil {
			host = h
			i, err := strconv.Atoi(p)
			if err != nil {
				return nil, err
			}
			port = i
		}
		go runMTA(s.channel, host, opt.SMTPUser, opt.SMTPPass, port)
	}
	return s, nil
}