github.com/glennzw/gophish@v0.8.1-0.20190824020715-24fe998a3aa0/models/template_context.go (about)

     1  package models
     2  
     3  import (
     4  	"bytes"
     5  	"net/mail"
     6  	"net/url"
     7  	"path"
     8  	"text/template"
     9  )
    10  
    11  // TemplateContext is an interface that allows both campaigns and email
    12  // requests to have a PhishingTemplateContext generated for them.
    13  type TemplateContext interface {
    14  	getFromAddress() string
    15  	getBaseURL() string
    16  }
    17  
    18  // PhishingTemplateContext is the context that is sent to any template, such
    19  // as the email or landing page content.
    20  type PhishingTemplateContext struct {
    21  	From        string
    22  	URL         string
    23  	Tracker     string
    24  	TrackingURL string
    25  	RId         string
    26  	BaseURL     string
    27  	BaseRecipient
    28  }
    29  
    30  // NewPhishingTemplateContext returns a populated PhishingTemplateContext,
    31  // parsing the correct fields from the provided TemplateContext and recipient.
    32  func NewPhishingTemplateContext(ctx TemplateContext, r BaseRecipient, rid string) (PhishingTemplateContext, error) {
    33  	f, err := mail.ParseAddress(ctx.getFromAddress())
    34  	if err != nil {
    35  		return PhishingTemplateContext{}, err
    36  	}
    37  	fn := f.Name
    38  	if fn == "" {
    39  		fn = f.Address
    40  	}
    41  	templateURL, err := ExecuteTemplate(ctx.getBaseURL(), r)
    42  	if err != nil {
    43  		return PhishingTemplateContext{}, err
    44  	}
    45  
    46  	// For the base URL, we'll reset the the path and the query
    47  	// This will create a URL in the form of http://example.com
    48  	baseURL, _ := url.Parse(templateURL)
    49  	baseURL.Path = ""
    50  	baseURL.RawQuery = ""
    51  
    52  	phishURL, _ := url.Parse(templateURL)
    53  	q := phishURL.Query()
    54  	q.Set(RecipientParameter, rid)
    55  	phishURL.RawQuery = q.Encode()
    56  
    57  	trackingURL, _ := url.Parse(templateURL)
    58  	trackingURL.Path = path.Join(trackingURL.Path, "/track")
    59  	trackingURL.RawQuery = q.Encode()
    60  
    61  	return PhishingTemplateContext{
    62  		BaseRecipient: r,
    63  		BaseURL:       baseURL.String(),
    64  		URL:           phishURL.String(),
    65  		TrackingURL:   trackingURL.String(),
    66  		Tracker:       "<img alt='' style='display: none' src='" + trackingURL.String() + "'/>",
    67  		From:          fn,
    68  		RId:           rid,
    69  	}, nil
    70  }
    71  
    72  // ExecuteTemplate creates a templated string based on the provided
    73  // template body and data.
    74  func ExecuteTemplate(text string, data interface{}) (string, error) {
    75  	buff := bytes.Buffer{}
    76  	tmpl, err := template.New("template").Parse(text)
    77  	if err != nil {
    78  		return buff.String(), err
    79  	}
    80  	err = tmpl.Execute(&buff, data)
    81  	return buff.String(), err
    82  }
    83  
    84  // ValidationContext is used for validating templates and pages
    85  type ValidationContext struct {
    86  	FromAddress string
    87  	BaseURL     string
    88  }
    89  
    90  func (vc ValidationContext) getFromAddress() string {
    91  	return vc.FromAddress
    92  }
    93  
    94  func (vc ValidationContext) getBaseURL() string {
    95  	return vc.BaseURL
    96  }
    97  
    98  // ValidateTemplate ensures that the provided text in the page or template
    99  // uses the supported template variables correctly.
   100  func ValidateTemplate(text string) error {
   101  	vc := ValidationContext{
   102  		FromAddress: "foo@bar.com",
   103  		BaseURL:     "http://example.com",
   104  	}
   105  	td := Result{
   106  		BaseRecipient: BaseRecipient{
   107  			Email:     "foo@bar.com",
   108  			FirstName: "Foo",
   109  			LastName:  "Bar",
   110  			Position:  "Test",
   111  		},
   112  		RId: "123456",
   113  	}
   114  	ptx, err := NewPhishingTemplateContext(vc, td.BaseRecipient, td.RId)
   115  	if err != nil {
   116  		return err
   117  	}
   118  	_, err = ExecuteTemplate(text, ptx)
   119  	if err != nil {
   120  		return err
   121  	}
   122  	return nil
   123  }