github.com/seeker-insurance/kit@v0.0.13/mailman/mailman.go (about)

     1  package mailman
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"path"
     8  	"strings"
     9  	"text/template"
    10  
    11  	"github.com/seeker-insurance/kit/assets"
    12  	"github.com/spf13/viper"
    13  )
    14  
    15  type Address struct {
    16  	Name  string
    17  	Email string
    18  }
    19  
    20  type Config struct {
    21  	From   *Address
    22  	Domain string
    23  }
    24  
    25  type Mailer interface {
    26  	Config() *Config
    27  	Send(to *Address, content *Content, vars *MergeVars) error
    28  }
    29  
    30  type Template struct {
    31  	Subject   *template.Template
    32  	HtmlBody  *template.Template
    33  	PlainBody *template.Template
    34  }
    35  
    36  type Content struct {
    37  	Subject   *bytes.Buffer
    38  	HtmlBody  *bytes.Buffer
    39  	PlainBody *bytes.Buffer
    40  }
    41  
    42  type MergeVars struct {
    43  	SubjectVars map[string]string
    44  	BodyVars    map[string]string
    45  }
    46  
    47  type mergeVars interface{}
    48  
    49  var (
    50  	TemplateDir string
    51  	Templates   map[string]*Template
    52  	mailer      Mailer
    53  )
    54  
    55  func newTemplate(s string) (*template.Template, error) {
    56  	return template.New("").Parse(s)
    57  }
    58  
    59  func setDefaultTemplateDir() {
    60  	dir := path.Join("data", "bin", "mail")
    61  
    62  	if _, err := assets.Dir(dir); err == nil {
    63  		TemplateDir = dir
    64  	}
    65  }
    66  
    67  func Configure(m Mailer) {
    68  	setDefaultTemplateDir()
    69  
    70  	Templates = make(map[string]*Template)
    71  	mailer = m
    72  }
    73  
    74  func AddTemplate(key string, subject string, htmlBody string, plainBody string) error {
    75  	var s, h, p *template.Template
    76  	var err error
    77  	if s, err = newTemplate(subject); err != nil {
    78  		return err
    79  	}
    80  	if h, err = newTemplate(htmlBody); err != nil {
    81  		return err
    82  	}
    83  	if p, err = newTemplate(plainBody); err != nil {
    84  		return err
    85  	}
    86  
    87  	Templates[key] = &Template{s, h, p}
    88  	return nil
    89  }
    90  
    91  func readEmailTemplates(key string) ([][]byte, error) {
    92  	templates := make([][]byte, 3)
    93  	var err error
    94  
    95  	for i, part := range []string{"subject", "html", "plain"} {
    96  		fileName := fmt.Sprintf("%s_%s.tmpl", key, part)
    97  		p := path.Join(TemplateDir, fileName)
    98  
    99  		if templates[i], err = assets.Get(p); err != nil {
   100  			return templates, err
   101  		}
   102  	}
   103  
   104  	return templates, nil
   105  }
   106  
   107  func RegisterTemplate(keys ...string) error {
   108  	if len(TemplateDir) == 0 {
   109  		return errors.New("TemplateDir not set")
   110  	}
   111  	for _, key := range keys {
   112  		parts, err := readEmailTemplates(key)
   113  		if err != nil {
   114  			return err
   115  		}
   116  		if err := AddTemplate(key, string(parts[0]), string(parts[1]), string(parts[2])); err != nil {
   117  			return err
   118  		}
   119  	}
   120  	return nil
   121  }
   122  
   123  func Send(to *Address, templateKey string, vars *MergeVars) error {
   124  	substr := viper.GetString("email_whitelist_pattern")
   125  	if substr != "" && !strings.Contains(to.Email, substr) {
   126  		return nil
   127  	}
   128  
   129  	if mailer == nil {
   130  		return errors.New("Mail has not been configured")
   131  	}
   132  
   133  	template := Templates[templateKey]
   134  	if template == nil {
   135  		return fmt.Errorf("Template not found for key [%s]", templateKey)
   136  	}
   137  
   138  	content := &Content{
   139  		new(bytes.Buffer),
   140  		new(bytes.Buffer),
   141  		new(bytes.Buffer),
   142  	}
   143  
   144  	if err := template.Subject.Execute(content.Subject, vars.SubjectVars); err != nil {
   145  		return err
   146  	}
   147  	if err := template.HtmlBody.Execute(content.HtmlBody, vars.BodyVars); err != nil {
   148  		return err
   149  	}
   150  	if err := template.PlainBody.Execute(content.PlainBody, vars.BodyVars); err != nil {
   151  		return err
   152  	}
   153  
   154  	return mailer.Send(to, content, vars)
   155  }