<commit_before>package sendgrid

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/smtp"
	"net/url"
	"path/filepath"
)

type SGClient struct {
	apiUser  string
	apiPwd   string
	apiUrl   string
	smtpUrl  string
	smtpPort string
	smtpAuth smtp.Auth
	// Client is the HTTP transport to use when making requests.
	// It will default to http.DefaultClient if nil.
	Client *http.Client
}

/*
apiUser - SG username
apiPwd - SG password
*/
func NewSendGridClient(apiUser, apiPwd string) SGClient {
	smtpUrl := "smtp.sendgrid.net"
	smtpPort := "587"
	apiUrl := "https://sendgrid.com/api/mail.send.json?"
	smtpAuth := smtp.PlainAuth("", apiUser, apiPwd, smtpUrl)
	return SGClient{
		apiUser:  apiUser,
		apiPwd:   apiPwd,
		apiUrl:   apiUrl,
		smtpUrl:  smtpUrl,
		smtpPort: smtpPort,
		smtpAuth: smtpAuth,
	}
}

/*
Send will try to use the WebAPI first. If it's a success then a nill will be returned.
Else, the SMTP API will be used as a fail over. If this happens regardless of what is the result
of the SMTP attempt, you will receive an array of errors.
If the length of the array is 1, then SMTP succeeded, else it also failed.
*/
func (sg *SGClient) Send(m Mail) []error {
	if apiError := sg.SendAPI(m); apiError != nil {
		var errors []error
		errors = append(errors, apiError)
		if smtpError := sg.SendSMTP(m); smtpError != nil {
			return append(errors, smtpError)
		} else {
			return errors
		}
	} else {
		return nil //sucess
	}
}

func (sg *SGClient) SendSMTP(m Mail) error {
	return smtp.SendMail(sg.smtpUrl+":"+sg.smtpPort, sg.smtpAuth, m.from, m.to, []byte(m.html))
}

func (sg *SGClient) SendAPI(m Mail) error {
	values := url.Values{}
	values.Set("api_user", sg.apiUser)
	values.Set("api_key", sg.apiPwd)
	values.Set("subject", m.subject)
	values.Set("html", m.html)
	values.Set("text", m.text)
	values.Set("from", m.from)
	headers, e := json.Marshal(m.headers)
	if e != nil {
		return fmt.Errorf("sendgrid.go: Error parsing JSON headers")
	}
	values.Set("headers", string(headers[:]))
	for i := 0; i < len(m.to); i++ {
		values.Set("to[]", m.to[i])
	}
	for i := 0; i < len(m.bcc); i++ {
		values.Set("bcc[]", m.bcc[i])
	}
	for i := 0; i < len(m.toname); i++ {
		values.Set("toname[]", m.toname[i])
	}
	for k, v := range m.files {
		values.Set("files["+k+"]", v)
	}
	if sg.Client == nil {
		sg.Client = http.DefaultClient
	}
	fmt.Print(values)
	r, e := sg.Client.PostForm(sg.apiUrl, values)
	defer r.Body.Close()
	if r.StatusCode == 200 && e == nil {
		return nil
	} else {
		body, _ := ioutil.ReadAll(r.Body)
		return fmt.Errorf("sendgrid.go: code:%d error:%v body:%s", r.StatusCode, e, body)
	}
}

type Mail struct {
	to       []string
	toname   []string
	subject  string
	html     string
	text     string
	from     string
	bcc      []string
	fromname string
	replyto  string
	date     string
	files    map[string]string
	headers  map[string]string
	//still missing some stuff
}

func NewMail() Mail {
	return Mail{}
}

/*
TODO: Validate email addressed with RegExp.
*/
func (m *Mail) AddTo(email string) {
	m.to = append(m.to, email)<commit_msg>Not doing regex anymore<commit_after>package sendgrid

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/smtp"
	"net/url"
	"path/filepath"
)

type SGClient struct {
	apiUser  string
	apiPwd   string
	apiUrl   string
	smtpUrl  string
	smtpPort string
	smtpAuth smtp.Auth
	// Client is the HTTP transport to use when making requests.
	// It will default to http.DefaultClient if nil.
	Client *http.Client
}

/*
apiUser - SG username
apiPwd - <PASSWORD>
*/
func NewSendGridClient(apiUser, apiPwd string) SGClient {
	smtpUrl := "smtp.sendgrid.net"
	smtpPort := "587"
	apiUrl := "https://sendgrid.com/api/mail.send.json?"
	smtpAuth := smtp.PlainAuth("", apiUser, apiPwd, smtpUrl)
	return SGClient{
		apiUser:  apiUser,
		apiPwd:   apiPwd,
		apiUrl:   apiUrl,
		smtpUrl:  smtpUrl,
		smtpPort: smtpPort,
		smtpAuth: smtpAuth,
	}
}

/*
Send will try to use the WebAPI first. If it's a success then a nill will be returned.
Else, the SMTP API will be used as a fail over. If this happens regardless of what is the result
of the SMTP attempt, you will receive an array of errors.
If the length of the array is 1, then SMTP succeeded, else it also failed.
*/
func (sg *SGClient) Send(m Mail) []error {
	if apiError := sg.SendAPI(m); apiError != nil {
		var errors []error
		errors = append(errors, apiError)
		if smtpError := sg.SendSMTP(m); smtpError != nil {
			return append(errors, smtpError)
		} else {
			return errors
		}
	} else {
		return nil //sucess
	}
}

/*
SMTP interface. Still being developed. Use API instead.
*/
func (sg *SGClient) SendSMTP(m Mail) error {
	return smtp.SendMail(sg.smtpUrl+":"+sg.smtpPort, sg.smtpAuth, m.from, m.to, []byte(m.html))
}

/*
Sends email using SG web API
*/
func (sg *SGClient) SendAPI(m Mail) error {
	values := url.Values{}
	values.Set("api_user", sg.apiUser)
	values.Set("api_key", sg.apiPwd)
	values.Set("subject", m.subject)
	values.Set("html", m.html)
	values.Set("text", m.text)
	values.Set("from", m.from)
	headers, e := json.Marshal(m.headers)
	if e != nil {
		return fmt.Errorf("sendgrid.go: Error parsing JSON headers")
	}
	values.Set("headers", string(headers[:]))
	for i := 0; i < len(m.to); i++ {
		values.Set("to[]", m.to[i])
	}
	for i := 0; i < len(m.bcc); i++ {
		values.Set("bcc[]", m.bcc[i])
	}
	for i := 0; i < len(m.toname); i++ {
		values.Set("toname[]", m.toname[i])
	}
	for k, v := range m.files {
		values.Set("files["+k+"]", v)
	}
	if sg.Client == nil {
		sg.Client = http.DefaultClient
	}
	fmt.Print(values)
	r, e := sg.Client.PostForm(sg.apiUrl, values)
	defer r.Body.Close()
	if r.StatusCode == 200 && e == nil {
		return nil
	} else {
		body, _ := ioutil.ReadAll(r.Body)
		return fmt.Errorf("sendgrid.go: code:%d error:%v body:%s", r.StatusCode, e, body)
	}
}

type Mail struct {
	to       []string
	toname   []string
	subject  string
	html     string
	text     string
	from     string
	bcc      []string
	fromname string
	replyto  string
	date     string
	files    map[string]string
	headers  map[string]string
}

func NewMail() Mail {
	return Mail{}
}

func (m *Mail) AddTo(email string) {
	m.to = append(m.to, email)
{'fraction_non_alphanumeric': 0.14642396907216496, 'fraction_numerical': 0.003865979381443299, 'mean_word_length': 3.4992753623188406, 'pattern_counts': {'":': 2, '<': 10, '<?xml version=': 0, '>': 4, 'https://': 2, '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': '2717379', 'n_tokens_mistral': 2512, 'n_tokens_neox': 2386, 'n_words': 673}