github.com/noname1007/gophish@v0.9.0/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, err := url.Parse(templateURL)
    49  	if err != nil {
    50  		return PhishingTemplateContext{}, err
    51  	}
    52  	baseURL.Path = ""
    53  	baseURL.RawQuery = ""
    54  
    55  	phishURL, _ := url.Parse(templateURL)
    56  	q := phishURL.Query()
    57  	q.Set(RecipientParameter, rid)
    58  	phishURL.RawQuery = q.Encode()
    59  
    60  	trackingURL, _ := url.Parse(templateURL)
    61  	trackingURL.Path = path.Join(trackingURL.Path, "/track")
    62  	trackingURL.RawQuery = q.Encode()
    63  
    64  	return PhishingTemplateContext{
    65  		BaseRecipient: r,
    66  		BaseURL:       baseURL.String(),
    67  		URL:           phishURL.String(),
    68  		TrackingURL:   trackingURL.String(),
    69  		Tracker:       "<img alt='' style='display: none' src='" + trackingURL.String() + "'/>",
    70  		From:          fn,
    71  		RId:           rid,
    72  	}, nil
    73  }
    74  
    75  // ExecuteTemplate creates a templated string based on the provided
    76  // template body and data.
    77  func ExecuteTemplate(text string, data interface{}) (string, error) {
    78  	buff := bytes.Buffer{}
    79  	tmpl, err := template.New("template").Parse(text)
    80  	if err != nil {
    81  		return buff.String(), err
    82  	}
    83  	err = tmpl.Execute(&buff, data)
    84  	return buff.String(), err
    85  }
    86  
    87  // ValidationContext is used for validating templates and pages
    88  type ValidationContext struct {
    89  	FromAddress string
    90  	BaseURL     string
    91  }
    92  
    93  func (vc ValidationContext) getFromAddress() string {
    94  	return vc.FromAddress
    95  }
    96  
    97  func (vc ValidationContext) getBaseURL() string {
    98  	return vc.BaseURL
    99  }
   100  
   101  // ValidateTemplate ensures that the provided text in the page or template
   102  // uses the supported template variables correctly.
   103  func ValidateTemplate(text string) error {
   104  	vc := ValidationContext{
   105  		FromAddress: "foo@bar.com",
   106  		BaseURL:     "http://example.com",
   107  	}
   108  	td := Result{
   109  		BaseRecipient: BaseRecipient{
   110  			Email:     "foo@bar.com",
   111  			FirstName: "Foo",
   112  			LastName:  "Bar",
   113  			Position:  "Test",
   114  		},
   115  		RId: "123456",
   116  	}
   117  	ptx, err := NewPhishingTemplateContext(vc, td.BaseRecipient, td.RId)
   118  	if err != nil {
   119  		return err
   120  	}
   121  	_, err = ExecuteTemplate(text, ptx)
   122  	if err != nil {
   123  		return err
   124  	}
   125  	return nil
   126  }