<commit_before>// Package gopostal - Supports Sending Text and HTML based emails.  Send email as plain text or html.
package gopostal

/*

Send email as plain text or html
Add attachments - in progress
Send with cc or bcc recipients
Built in config for Gmail, Sendgrid

TODO: handle custom mail headers

Based on work from:
* github.com/ungerik/go-mail
* github.com/marcw/ezmail

*/

import (
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"net/mail"
	"net/smtp"
	"strings"
	"time"
)

// Mailer represents a mail sender object
type Mailer struct {
	Identity string
	Username string
	Password string
	Host     string
	Port     string
}

// NewMailer returns an instance of Mailer with the passed in connnection configuration options
func NewMailer(identity, username, password, host, port string) *Mailer {
	return &Mailer{Identity: identity, Username: username, Password: password, Host: host, Port: port}
}

// NewGmailMailer is a shortcut constructor for a Mailer with a gmail connection
func NewGmailMailer(username, password string) *Mailer {
	return &Mailer{Identity: "", Username: username, Password: password, Host: "smtp.gmail.com", Port: "587"}
}

// NewSendGridMailer is a shortcut constructor for a Mailer with a sendgrid connection
func NewSendGridMailer(username, password string) *Mailer {
	return &Mailer{Identity: "", Username: username, Password: password, Host: "smtp.sendgrid.net", Port: "25"}
}

// SendMail sends email to the to address populating the from, body and htmlbody provided
func (m *Mailer) SendMail(to, from, subject, body, htmlBody string) error {
	msg := m.NewMessage(to, from, subject, body, htmlBody)
	return m.Send(*msg)
}

// Send will send the given Message
func (m *Mailer) Send(msg Message) error {
	// validate the Message object
	if verr := msg.validate(); verr != nil {
		return verr
	}

	auth := smtp.PlainAuth(m.Identity, m.Username, m.Password, m.Host)
	content := msg.Bytes()
	host := m.Host + ":" + m.Port

	err := smtp.SendMail(
		host,
		auth,
		msg.From.Address,
		msg.recipients(),
		content,
	)

	if err != nil {
		return err
	}

	return nil
}

// Message represents an email message containing the sender to, the from, cc and bcc recipients and all content for the message including text and html body content
type Message struct {
	From     mail.Address
	To       []mail.Address
	cc       []mail.Address
	bcc      []mail.Address
	Subject  string
	TextBody string
	IsText   bool
	HtmlBody string
	IsHtml   bool
	Headers  map[string]string
}

// NewMessage returns a new Message object build with the to, from, subject, body and html body provided
func (m *Mailer) NewMessage(to, from, subject, body, htmlBody string) *Message {
	isText := body != ""
	isHtml := htmlBody != ""

	toAddr := convertStringToAddress(to)
	fromAddr := convertStringToAddress(from)

	return &Message{
		To:       []mail.Address{toAddr},
		From:     fromAddr,
		Subject:  subject,
		HtmlBody: htmlBody,
		IsHtml:   isHtml,
		TextBody: body,
		IsText:   isText,
		Headers:  make(map[string]string),
	}
}

// convertStringToAddress formats an address string building a mail.Address object and returning it
func convertStringToAddress(address string) mail.Address {
	arr := strings.Split(address, " ")
	if len(arr) == 2 {
		return mail.Address{arr[0], arr[1]}
	} else {
		return mail.Address{address, address}
	}
}
<commit_msg>Fixing based on lint feedback<commit_after>// Package gopostal - Supports Sending Text and HTML based emails.  Send email as plain text or html.
package gopostal

/*

Send email as plain text or html
Add attachments - in progress
Send with cc or bcc recipients
Built in config for Gmail, Sendgrid

TODO: handle custom mail headers

Based on work from:
* github.com/ungerik/go-mail
* github.com/marcw/ezmail

*/

import (
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"net/mail"
	"net/smtp"
	"strings"
	"time"
)

// Mailer represents a mail sender object
type Mailer struct {
	Identity string
	Username string
	Password string
	Host     string
	Port     string
}

// NewMailer returns an instance of Mailer with the passed in connnection configuration options
func NewMailer(identity, username, password, host, port string) *Mailer {
	return &Mailer{Identity: identity, Username: username, Password: password, Host: host, Port: port}
}

// NewGmailMailer is a shortcut constructor for a Mailer with a gmail connection
func NewGmailMailer(username, password string) *Mailer {
	return &Mailer{Identity: "", Username: username, Password: password, Host: "smtp.gmail.com", Port: "587"}
}

// NewSendGridMailer is a shortcut constructor for a Mailer with a sendgrid connection
func NewSendGridMailer(username, password string) *Mailer {
	return &Mailer{Identity: "", Username: username, Password: password, Host: "smtp.sendgrid.net", Port: "25"}
}

// SendMail sends email to the to address populating the from, body and htmlbody provided
func (m *Mailer) SendMail(to, from, subject, body, htmlBody string) error {
	msg := m.NewMessage(to, from, subject, body, htmlBody)
	return m.Send(*msg)
}

// Send will send the given Message
func (m *Mailer) Send(msg Message) error {
	// validate the Message object
	if verr := msg.validate(); verr != nil {
		return verr
	}

	auth := smtp.PlainAuth(m.Identity, m.Username, m.Password, m.Host)
	content := msg.Bytes()
	host := m.Host + ":" + m.Port

	err := smtp.SendMail(
		host,
		auth,
		msg.From.Address,
		msg.recipients(),
		content,
	)

	if err != nil {
		return err
	}

	return nil
}

// Message represents an email message containing the sender to, the from, cc and bcc recipients and all content for the message including text and html body content
type Message struct {
	From     mail.Address
	To       []mail.Address
	cc       []mail.Address
	bcc      []mail.Address
	Subject  string
	TextBody string
	IsText   bool
	HtmlBody string
	IsHtml   bool
	Headers  map[string]string
}

// NewMessage returns a new Message object build with the to, from, subject, body and html body provided
func (m *Mailer) NewMessage(to, from, subject, body, htmlBody string) *Message {
	isText := body != ""
	isHtml := htmlBody != ""

	toAddr := convertStringToAddress(to)
	fromAddr := convertStringToAddress(from)

	return &Message{
		To:       []mail.Address{toAddr},
		From:     fromAddr,
		Subject:  subject,
		HtmlBody: htmlBody,
		IsHtml:   isHtml,
		TextBody: body,
		IsText:   isText,
		Headers:  make(map[string]string),
	}
}

// convertStringToAddress formats an address string building a mail.Address object and returning it
func convertStringToAddress(address string) mail.Address {
	arr := strings.Split(address, " ")
	if len(arr) == 2 {
		return mail.Address{arr[0], arr[1]}
	}

	return mail.Address{address, address}
}

{'fraction_non_alphanumeric': 0.10187667560321716, 'fraction_numerical': 0.002680965147453083, 'mean_word_length': 3.9851521900519673, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3886878', 'n_tokens_mistral': 2198, 'n_tokens_neox': 2113, 'n_words': 759}