Documentation ¶
Index ¶
- Constants
- func ClientCreate(config Config) (err error)
- func NewParsedTemplate(contentType TemplateBufferContentType, context Context) parsedTemplate
- type ClientWrapper
- type Config
- type Context
- type Email
- func (e *Email) AddPart(part Part) (err error)
- func (e *Email) AddParts(parts ...Part) (err error)
- func (e *Email) Close() (err error)
- func (e *Email) From() string
- func (e *Email) Read() *bytes.Buffer
- func (e *Email) ReadBuffered() *bufio.Reader
- func (e *Email) Size() int64
- func (e *Email) Write() (err error)
- func (e *Email) WriteTo(w io.Writer) (n int64, err error)
- type FinishedContext
- type MeasureContext
- func (m *MeasureContext) AdditionalParts() ([]Part, error)
- func (m *MeasureContext) DeletedDevelopersWithGames() []*models.TrendingDev
- func (m *MeasureContext) Execute() *Template
- func (m *MeasureContext) Funcs() template.FuncMap
- func (m *MeasureContext) HasWatched() bool
- func (m *MeasureContext) Path() TemplatePath
- func (m *MeasureContext) Template() *Template
- func (m *MeasureContext) WatchedDevelopersWithGames() []*models.TrendingDev
- func (m *MeasureContext) WatchedGames() []*models.Game
- func (m *MeasureContext) WatchedGamesWithDummyDevs() []*models.TrendingDev
- type Part
- type Profiling
- type Response
- type Template
- func (t *Template) Email() (email *Email, err error)
- func (t *Template) Execute() (output *Template)
- func (t *Template) PDF() (output *Template)
- func (t *Template) SendAsync() <-chan Response
- func (t *Template) SendAsyncAndConsume(consumer func(resp Response))
- func (t *Template) SendSync() Response
- func (t *Template) WriteFile(filename string) (err error)
- type TemplateBufferContentType
- type TemplateConfig
- type TemplateMailer
- type TemplatePath
Examples ¶
Constants ¶
const ( // ProfilingNew profiles the NewEmail procedure. ProfilingNew profilingKey = "NEW" // ProfilingAddPart profiles the Email.AddPart method. ProfilingAddPart profilingKey = "ADD_PART" // ProfilingWrite profiles the Email.Write method. ProfilingWrite profilingKey = "WRITE" // ProfilingSMTPClientCreation profiles the creation of the SMTP client in TemplateMailer.Send. ProfilingSMTPClientCreation profilingKey = "SMTP_CLIENT_CREATION" // ProfilingTLSStarted profiles the time it takes for TLS to be started in TemplateMailer.Send. ProfilingTLSStarted profilingKey = "TLS_STARTED" // ProfilingAuthAdded profiles the time it takes for AUTH to be added in TemplateMailer.Send. ProfilingAuthAdded profilingKey = "AUTH_ADDED" // ProfilingMailCommand profiles the time it takes to push the MAIL command in TemplateMailer.Send. ProfilingMailCommand profilingKey = "MAIL_COMMAND" // ProfilingRcptCommand profiles the time it takes to push a single RCPT command in TemplateMailer.Send. ProfilingRcptCommand profilingKey = "RCPT_COMMAND" // ProfilingDataCommand profiles the time it takes to push the DATA command in TemplateMailer.Send. ProfilingDataCommand profilingKey = "DATA_COMMAND" // ProfilingDataClose profiles the time it takes to close the DATA command after writing all data to the SMTP server // connection in TemplateMailer.Send. ProfilingDataClose profilingKey = "DATA_CLOSE" // ProfilingWriteTo profiles the Email.WriteTo method. ProfilingWriteTo profilingKey = "WRITE_TO" // ProfilingClose profiles the Email.Close method. ProfilingClose profilingKey = "CLOSE" )
const ( // PixelsToMM is the conversion constant for converting pixels to MM at a 96 DPI. PixelsToMM = 0.264583333 PDFDPI = 96 )
Variables ¶
This section is empty.
Functions ¶
func ClientCreate ¶
func NewParsedTemplate ¶
func NewParsedTemplate(contentType TemplateBufferContentType, context Context) parsedTemplate
Types ¶
type ClientWrapper ¶
type ClientWrapper struct {
// contains filtered or unexported fields
}
func (*ClientWrapper) Auth ¶
func (c *ClientWrapper) Auth() smtp.Auth
func (*ClientWrapper) Config ¶
func (c *ClientWrapper) Config() Config
func (*ClientWrapper) Send ¶
func (c *ClientWrapper) Send(email *Email) (err error)
func (*ClientWrapper) SendAsync ¶
func (c *ClientWrapper) SendAsync(template *Template) <-chan Response
func (*ClientWrapper) SendSync ¶
func (c *ClientWrapper) SendSync(template *Template) Response
type Config ¶
type Config interface { EmailDebug() bool EmailHost() string EmailPort() int EmailAddress() string EmailFrom() string EmailFromName() string EmailPassword() string EmailTemplateConfigFor(path TemplatePath) TemplateConfig }
type Context ¶
type Context interface { // Path returns the TemplatePath that this Context is for. Path() TemplatePath // Template returns an un-executed Template that this Context can be used for. Template() *Template // Funcs returns the functions that should be bound to the template.Template before parsing the HTML/Text template // located in at the TemplatePath. Funcs() template.FuncMap // Execute executes the Context via Template.Execute. Execute() *Template // AdditionalParts returns any additional Part to add onto an Email. AdditionalParts() ([]Part, error) }
Context will be implemented by structures that are used to fill out a Template in Template.Execute.
type Email ¶
type Email struct { // Profiling is the Profiling instance used to measure the time-of-completion for all actions related to the Email. Profiling Profiling // FromAddress is the email address of the sender. FromAddress string // FromName is the name of the sender. FromName string // Subject is the subject of the Email. Subject string // Recipients are the email addresses for the recipients of this Email. Recipients []string // contains filtered or unexported fields }
Email represents an email MIME multipart file that can be sent using a TemplateMailer.
• First call NewEmail to construct a new Email instance.
• Then set the FromAddress, FromName, Subject, and Recipients fields.
• Add all the parts of the email using AddPart or AddParts. This will encode each Part using Part.Encoder and cache them to the disk.
• Then call Write, to cache the entire MIME multipart email to disk.
• You can then use either Read or ReadBuffered to read the entire MIME multipart email.
• Finally, call Close to close all the Part files and the Email file as well as to remove these files from the disk.
Note: the last three steps should all be performed by the TemplateMailer.Send method anyway.
func NewEmail ¶
NewEmail creates a new Email instance and creates a temporary file to hold the finished multipart request.
Example ¶
inTest = true defer func() { inTest = false }() var ( email *Email err error ) if email, err = NewEmail(); err != nil { fmt.Println(err) } email.Recipients = []string{"dest@dest.com"} email.Subject = "Hello world!" email.FromName = "Test" email.FromAddress = "test@test.com" defer email.Close() if err = agem.MergeErrors( email.AddPart(Part{Buffer: bytes.NewReader([]byte("Hello world!"))}), email.AddPart(Part{Buffer: bytes.NewReader([]byte("<h1>Hello world!</h1>"))}), email.AddPart(Part{ Buffer: bytes.NewReader([]byte("a,b,c\n1,2,3")), ContentType: "text/csv; charset=utf-8", Attachment: true, Filename: "test.csv", }), ); err != nil { fmt.Println(err) } if err = email.Write(); err != nil { fmt.Println(err) } fmt.Printf("Final email size: %d\n", email.Size()) fmt.Println(email.Profiling.String()) // Convert DOS line-endings to UNIX so that we can check the output. fmt.Println(strings.ReplaceAll(email.Read().String(), "\r\n", "\n"))
Output: Final email size: 463 Total duration: X 1: ADD_PART was called 3 time(s) with an overall time of X (XX.XX%) 2: NEW was called 1 time(s) with an overall time of X (XX.XX%) 3: WRITE was called 1 time(s) with an overall time of X (XX.XX%) MIME-Version: 1.0 Content-Type: multipart/alternative; boundary=BOUNDARY From: Test <test@test.com> To: dest@dest.com Subject: Hello world! --BOUNDARY Content-Type: text/plain; charset=utf-8 Hello world! --BOUNDARY Content-Type: text/html; charset=utf-8 <h1>Hello world!</h1> --BOUNDARY Content-Disposition: attachment; filename=test.csv Content-Transfer-Encoding: base64 Content-Type: text/csv; charset=utf-8 YSxiLGMKMSwyLDM= --BOUNDARY--
func (*Email) AddPart ¶
AddPart will add a Part with a Part.Buffer to the Email. This will encode the Part to its required encoding and cache the Part intermittently to the disk.
func (*Email) From ¶
From returns the FromName and FromAddress in the format that the email header requires.
func (*Email) Read ¶
Read will return a bytes.Buffer containing all of the final MIME multipart email request.
func (*Email) ReadBuffered ¶
ReadBuffered will return a bufio.Reader for the final MIME multipart email request.
func (*Email) Size ¶
Size is the size of the final Email in bytes. This is equal to the size of the temporary file used to store the email within.
type FinishedContext ¶
type FinishedContext struct { BatchSize int DiscoveryTweets int Started time.Time Finished time.Time Result *models.ScoutResult }
func (*FinishedContext) AdditionalParts ¶
func (f *FinishedContext) AdditionalParts() ([]Part, error)
func (*FinishedContext) Execute ¶
func (f *FinishedContext) Execute() *Template
func (*FinishedContext) Funcs ¶
func (f *FinishedContext) Funcs() template.FuncMap
func (*FinishedContext) Path ¶
func (f *FinishedContext) Path() TemplatePath
func (*FinishedContext) Template ¶
func (f *FinishedContext) Template() *Template
type MeasureContext ¶
type MeasureContext struct { Start time.Time End time.Time TrendingDevs []*models.TrendingDev TopSteamApps []*models.SteamApp DevelopersBeingDeleted []*models.TrendingDev WatchedDevelopers []*models.TrendingDev WatchedSteamApps []*models.SteamApp Config Config }
MeasureContext is a Context that contains the data required to fill out the Measure HTML template.
func (*MeasureContext) AdditionalParts ¶
func (m *MeasureContext) AdditionalParts() ([]Part, error)
func (*MeasureContext) DeletedDevelopersWithGames ¶
func (m *MeasureContext) DeletedDevelopersWithGames() []*models.TrendingDev
DeletedDevelopersWithGames filters out all models.TrendingDev in DevelopersBeingDeleted with no models.Game related to them.
func (*MeasureContext) Execute ¶
func (m *MeasureContext) Execute() *Template
func (*MeasureContext) Funcs ¶
func (m *MeasureContext) Funcs() template.FuncMap
func (*MeasureContext) HasWatched ¶
func (m *MeasureContext) HasWatched() bool
HasWatched returns true when there are WatchedDevelopers or WatchedSteamApps.
func (*MeasureContext) Path ¶
func (m *MeasureContext) Path() TemplatePath
func (*MeasureContext) Template ¶
func (m *MeasureContext) Template() *Template
func (*MeasureContext) WatchedDevelopersWithGames ¶
func (m *MeasureContext) WatchedDevelopersWithGames() []*models.TrendingDev
WatchedDevelopersWithGames filters out all models.TrendingDev in WatchedDevelopers that don't contain a models.Developer.
func (*MeasureContext) WatchedGames ¶
func (m *MeasureContext) WatchedGames() []*models.Game
WatchedGames filters out all models.TrendingDev in WatchedDevelopers that contain a models.Developer.
func (*MeasureContext) WatchedGamesWithDummyDevs ¶
func (m *MeasureContext) WatchedGamesWithDummyDevs() []*models.TrendingDev
type Part ¶
type Part struct { Buffer *bytes.Reader // ContentType can be provided, but if it is the empty string then it will be found from the first 512 bytes of the // Buffer using http.DetectContentType. ContentType string // Attachment should be set to true if the Part should be added as an attachment. If this is set then Filename // should also be set. Attachment bool // Filename is the filename of the attachment. Filename string // DropIfBig will drop the attachment from the email if its base64 encoded version larger than 25MB. DropIfBig bool // contains filtered or unexported fields }
Part stores the information for a single part of an Email. When passing a Part to Email.AddPart Buffer should be set so that the Part can be intermittently cached to a file.
func (*Part) ContentTypeSlug ¶
ContentTypeSlug returns the slugified version of the ContentType that can be used within the names of the temporary file created for the Part.
func (*Part) Encoder ¶
func (p *Part) Encoder() (io.WriteCloser, error)
Encoder returns an io.WriteCloser for the Part's buffer. If the Part is an Attachment, then the encoder returned will be a base64 encoder, anything else will be encoded as plain-text.
func (*Part) Headers ¶
func (p *Part) Headers() textproto.MIMEHeader
Headers returns the textproto.MIMEHeader for the Part by using the ContentType.
type Profiling ¶
Profiling stores all the profiling that has been done for an Email.
type Template ¶
type Template struct { // Path is the TemplatePath where the Template was loaded from. Path TemplatePath // Template is the parsed template.Template or textTemplate.Template, loaded from the Path, which is also loaded up // with the functions returned by Context.Funcs method for the Context for this Template. Template parsedTemplate // Config is the TemplateConfig for this template. Config TemplateConfig // Buffer is a bytes.Reader that contains the parsed output for the results produced by Template.Execute and // Template.PDF. This is overwritten each time. Buffer bytes.Reader // Error is the error returned by any of the chained methods. Error error // ContentType is the current TemplateBufferContentType of the Buffer. ContentType TemplateBufferContentType // Context is the Context that this Template will/has used to generate HTML or Text from the TemplatePath. Context Context }
Template is a chainable structure that represents an instantiated HTML template that is read from the given Path. It is worth noting that the chainable methods return copies of the original Template.
func (*Template) Email ¶
Email returns the filled Email instance that can be sent using the email Client.
• If the given Template has an error set in Template.Error then this error will be wrapped and returned.
• If the given Template has a ContentType of Text, then the sent email will have a plain-text body.
• If the given Template has a ContentType of HTML, then the sent email will have an HTML body, a plain-text body obtained from html2text.FromString, and the HTML will be added as an attachment.
• If the given Template has a ContentType of PDF, then the sent email will have an HTML body obtained by executing a brand-new template with the Template.Context, a plain-text body obtained from html2text.FromString, and the PDF will be added as an attachment.
• If the given Template does not have a ContentType that is either Text, HTML or PDF, then an error will be returned.
Any additional Part returned by Context.AdditionalParts will also be added.
func (*Template) Execute ¶
Execute will call Template.Template.Execute with the given Template.Context. Template.Error is set if:
• The Template already contains an error.
• The Template.ContentType is not NotExecuted.
• The resulting value of Context.Path does not match the Template.Path.
• An error occurs whilst calling the Execute method on Template.Template.
If Template.Execute can run without setting the Template.Error then Template.ContentType is set to HTML or Text depending on the TemplateBufferContentType returned by Template.Template.ExecutedContentType.
func (*Template) PDF ¶
PDF will convert a Template with the ContentType HTML to a PDF. Template.Error is set if:
• The Template already contains an error.
• The Template.ContentType is not HTML.
• An error occurred in any of the functions used to generate the PDF.
If Template.PDF can run without setting the Template.Error then Template.ContentType is set to PDF. PDF will calculate the size of the generated PDF by opening the HTML in a headless playwright browser, then fetch the height and width (in pixels) of the first element to use the .container class on the page. These values are then converted to MM by using the PixelsToMM conversion constant, which assumes that the PDF DPI is 96.
func (*Template) SendAsync ¶
SendAsync the Template using the default TemplateMailer (Client) with ClientWrapper.SendAsync.
func (*Template) SendAsyncAndConsume ¶
SendAsyncAndConsume will send the Template using the default TemplateMailer (Client) with Template.SendAsync and will consume the response using the given function. If a Response is never returned from Template.SendAsync, then the consumer function will never be run.
type TemplateBufferContentType ¶
type TemplateBufferContentType int
TemplateBufferContentType is an enum representing the possible content-types of the Template.Buffer.
const ( // NotExecuted is the TemplateBufferContentType that is initially given to a Template constructed by // TemplatePath.Template. NotExecuted TemplateBufferContentType = iota // Text is set after the Template.Execute method is called successfully on a Text Template. Text templates cannot be // converted to HTML or PDF. Text // HTML is set after the Template.Execute method is called successfully on an HTML Template. HTML // PDF is set after the Template.PDF method is called successfully. PDF )
func (TemplateBufferContentType) String ¶
func (ct TemplateBufferContentType) String() string
String returns the formal name of the TemplateBufferContentType.
type TemplateConfig ¶
type TemplateConfig interface { TemplateMaxImageWidth() int TemplateMaxImageHeight() int TemplateDebugTo() []string TemplateTo() []string TemplateSendRetries() int TemplateSendBackoff() (time.Duration, error) TemplateSubject() string TemplateAttachmentName() string TemplateHTML2TextOptions() html2text.Options TemplatePlainOnly() bool TemplateSendDay() time.Weekday }
type TemplateMailer ¶
type TemplateMailer interface { Send(email *Email) (err error) SendAsync(template *Template) <-chan Response SendSync(template *Template) Response Auth() smtp.Auth Config() Config }
var Client TemplateMailer
type TemplatePath ¶
type TemplatePath string
TemplatePath represents the path of an HTML template in the repo. Each template that is going to be converted to PDF, must contain an element that implements a .container class. This is used to calculate the width of the final generated PDF.
const ( Measure TemplatePath = templateDir + "measure.html" Started TemplatePath = templateDir + "started.txt" Error TemplatePath = templateDir + "error.txt" Finished TemplatePath = templateDir + "finished.txt" )
func TemplatePathFromName ¶
func TemplatePathFromName(name string) TemplatePath
TemplatePathFromName returns the TemplatePath of the given name.
func (TemplatePath) Name ¶
func (tt TemplatePath) Name() string
Name returns the name of the TemplatePath that is synonymous to the name of the enum constant.
func (TemplatePath) Path ¶
func (tt TemplatePath) Path() string
Path returns the string value of the TemplatePath.