Add emailclient
This commit is contained in:
		
							parent
							
								
									936d812e9c
								
							
						
					
					
						commit
						54c4652814
					
				|  | @ -0,0 +1,199 @@ | ||||||
|  | package emailclient | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net" | ||||||
|  | 	"net/mail" | ||||||
|  | 	"net/smtp" | ||||||
|  | 
 | ||||||
|  | 	log "github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // SMTPCredentials is a struc holding the information needed to connect to a SMTP server
 | ||||||
|  | type SMTPCredentials struct { | ||||||
|  | 	Host     string | ||||||
|  | 	Email    string | ||||||
|  | 	Password string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // emailClient is a struct holding the information requiered to send with SMTP
 | ||||||
|  | type emailClient struct { | ||||||
|  | 	client *smtp.Client | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EmailClient is the generic interface for all client sending emails
 | ||||||
|  | type EmailClient interface { | ||||||
|  | 	SendMsg(headers map[string]string, body string) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewSMTPClient (host, user, password) returns a SMTPClient
 | ||||||
|  | //
 | ||||||
|  | //	host is the SMTP server used to connect
 | ||||||
|  | //	port is the SMTP port used to connect
 | ||||||
|  | //	user is usually the email address use to connect to SMTP
 | ||||||
|  | //	password is the associated password
 | ||||||
|  | func NewSMTPClient(host string, port string, user string, password string) (EmailClient, error) { | ||||||
|  | 	var ec emailClient | ||||||
|  | 
 | ||||||
|  | 	log.Infof("user: (%s) pass: (%s)", user, password) | ||||||
|  | 
 | ||||||
|  | 	auth := smtp.PlainAuth("", user, password, host) | ||||||
|  | 
 | ||||||
|  | 	// TLS config
 | ||||||
|  | 	tlsconfig := &tls.Config{ | ||||||
|  | 		InsecureSkipVerify: false, | ||||||
|  | 		ServerName:         host, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Here is the key, you need to call tls.Dial instead of smtp.Dial
 | ||||||
|  | 	// for smtp servers running on 465 that require an ssl connection
 | ||||||
|  | 	// from the very beginning (no starttls)
 | ||||||
|  | 	var conn *tls.Conn | ||||||
|  | 	var c *smtp.Client | ||||||
|  | 	var err error | ||||||
|  | 	if port == "465" { | ||||||
|  | 		conn, err = tls.Dial("tcp", host+":"+port, tlsconfig) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("[sendMail] ERROR while dialing: " + err.Error()) | ||||||
|  | 			return ec, err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		c, err = smtp.NewClient(conn, host) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("[sendMail] ERROR while NewClient: " + err.Error()) | ||||||
|  | 			return ec, err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		c, err = smtp.Dial(host + ":" + port) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("[sendMail] ERROR while Dialing: " + err.Error()) | ||||||
|  | 			return ec, err | ||||||
|  | 		} | ||||||
|  | 		err = c.StartTLS(tlsconfig) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("[sendMail] ERROR while StartTLS: " + err.Error()) | ||||||
|  | 			return ec, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// defer c.Quit()
 | ||||||
|  | 	// defer c.Close()
 | ||||||
|  | 
 | ||||||
|  | 	ec.client = c | ||||||
|  | 
 | ||||||
|  | 	// Auth
 | ||||||
|  | 	if err = ec.client.Auth(auth); err != nil { | ||||||
|  | 		log.Error("[sendMail] ERROR while Auth: " + err.Error()) | ||||||
|  | 		return ec, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ec, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewGmailClient returns a GmailClient
 | ||||||
|  | func NewGmailClient(email, pass string) (EmailClient, error) { | ||||||
|  | 	var ec emailClient | ||||||
|  | 
 | ||||||
|  | 	// cred.Host = "smtp.gmail.com:587"
 | ||||||
|  | 	echost := "smtp.gmail.com:465" | ||||||
|  | 	if pass == "" { | ||||||
|  | 		log.Error("Email password missing") | ||||||
|  | 		return ec, errors.New("Email password missing") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	host, _, _ := net.SplitHostPort(echost) | ||||||
|  | 	auth := smtp.PlainAuth("", email, pass, host) | ||||||
|  | 
 | ||||||
|  | 	// TLS config
 | ||||||
|  | 	tlsconfig := &tls.Config{ | ||||||
|  | 		InsecureSkipVerify: true, | ||||||
|  | 		ServerName:         host, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Cavehat, you need to call tls.Dial instead of smtp.Dial
 | ||||||
|  | 	// for smtp servers running on 465 that require an ssl connection
 | ||||||
|  | 	// from the very beginning (no starttls)
 | ||||||
|  | 	conn, err := tls.Dial("tcp", echost, tlsconfig) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error(fmt.Sprintf("Dial error: " + err.Error())) | ||||||
|  | 		return ec, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	client, err := smtp.NewClient(conn, host) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error(fmt.Sprintf("NewClient error: " + err.Error())) | ||||||
|  | 		return ec, err | ||||||
|  | 	} | ||||||
|  | 	ec.client = client | ||||||
|  | 
 | ||||||
|  | 	// Auth
 | ||||||
|  | 	if err = ec.client.Auth(auth); err != nil { | ||||||
|  | 		log.Error(fmt.Sprintf("Auth error: %s (%s)", err, host)) | ||||||
|  | 		return ec, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ec, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SendMsg send a message (email) to rcpt which is in the 'headers' parameter ('To' key) and whose content is the 'body' parameter.
 | ||||||
|  | // Ohter keys of interest in headers are 'Subject' and 'MIME-version'
 | ||||||
|  | func (ec emailClient) SendMsg(headers map[string]string, body string) { | ||||||
|  | 	from := mail.Address{Name: "", Address: headers["From"]} | ||||||
|  | 	to := mail.Address{Name: "", Address: headers["To"]} | ||||||
|  | 
 | ||||||
|  | 	// headers["To"] = to.String()
 | ||||||
|  | 	if _, ok := headers["Subject"]; ok { | ||||||
|  | 		headers["Subject"] = "Subject unknown" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Printf("from = %s", headers["From"]) | ||||||
|  | 	log.Printf("to = %s", headers["To"]) | ||||||
|  | 	log.Printf("subj = %s", headers["Subject"]) | ||||||
|  | 
 | ||||||
|  | 	// Setup message
 | ||||||
|  | 	message := "" | ||||||
|  | 	for k, v := range headers { | ||||||
|  | 		message += fmt.Sprintf("%s: %s\r\n", k, v) | ||||||
|  | 	} | ||||||
|  | 	message += "\r\n" + body | ||||||
|  | 
 | ||||||
|  | 	c := ec.client | ||||||
|  | 
 | ||||||
|  | 	// To && From
 | ||||||
|  | 	if err := c.Mail(from.Address); err != nil { | ||||||
|  | 		log.Error("Can't set From: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := c.Rcpt(to.Address); err != nil { | ||||||
|  | 		log.Error("Can't set To: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Data
 | ||||||
|  | 	w, err := c.Data() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Can't set Data: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_, err = w.Write([]byte(message)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Can't write Data: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = w.Close() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Can't Close: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = c.Quit() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Can't Quit: " + err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	c.Close() | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue