mirror of
https://github.com/wiggin77/mailrelay.git
synced 2025-08-13 00:47:04 +02:00
recv & send
This commit is contained in:
123
client.go
Normal file
123
client.go
Normal file
@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/smtp"
|
||||
"net/textproto"
|
||||
|
||||
"github.com/flashmob/go-guerrilla/mail"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type closeable interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// sendMail sends the contents of the envelope to a SMTP server.
|
||||
func sendMail(e *mail.Envelope, config *mailRelayConfig) error {
|
||||
server := fmt.Sprintf("%s:%d", config.Server, config.Port)
|
||||
to := getTo(e)
|
||||
|
||||
var msg bytes.Buffer
|
||||
msg.Write(e.Data.Bytes())
|
||||
msg.WriteString("\r\n")
|
||||
|
||||
fmt.Println("==== Starting email send ====")
|
||||
defer fmt.Println("==== Finished email send ====")
|
||||
var err error
|
||||
var conn *tls.Conn
|
||||
var client *smtp.Client
|
||||
var writer io.WriteCloser
|
||||
|
||||
tlsconfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
ServerName: config.Server,
|
||||
}
|
||||
|
||||
if conn, err = tls.Dial("tcp", server, tlsconfig); err != nil {
|
||||
return errors.Wrap(err, "dial error")
|
||||
}
|
||||
|
||||
if client, err = smtp.NewClient(conn, config.Server); err != nil {
|
||||
close(conn, "conn")
|
||||
return errors.Wrap(err, "newclient error")
|
||||
}
|
||||
shouldCloseClient := true
|
||||
defer func(shouldClose *bool) {
|
||||
if *shouldClose {
|
||||
close(client, "client")
|
||||
}
|
||||
}(&shouldCloseClient)
|
||||
|
||||
auth := smtp.PlainAuth("", config.Username, config.Password, config.Server)
|
||||
if err = client.Auth(auth); err != nil {
|
||||
return errors.Wrap(err, "auth error")
|
||||
}
|
||||
|
||||
if err = client.Mail(e.MailFrom.String()); err != nil {
|
||||
return errors.Wrap(err, "mail error")
|
||||
}
|
||||
|
||||
for _, addy := range to {
|
||||
if err = client.Rcpt(addy); err != nil {
|
||||
return errors.Wrap(err, "rcpt error")
|
||||
}
|
||||
}
|
||||
|
||||
if writer, err = client.Data(); err != nil {
|
||||
return errors.Wrap(err, "data error")
|
||||
}
|
||||
_, err = writer.Write(msg.Bytes())
|
||||
close(writer, "writer")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "write error")
|
||||
}
|
||||
|
||||
if err = client.Quit(); isQuitError(err) {
|
||||
return errors.Wrap(err, "quit error")
|
||||
}
|
||||
// We only need to close client if some other error prevented us
|
||||
// from getting to `client.Quit`
|
||||
shouldCloseClient = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func close(c closeable, what string) {
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("!!!!! Error closing %s: %v\n", what, err)
|
||||
}
|
||||
}
|
||||
|
||||
func isQuitError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
e, ok := err.(*textproto.Error)
|
||||
if ok {
|
||||
// SMTP codes 221 or 250 are acceptable here
|
||||
if e.Code == 221 || e.Code == 250 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// getTo returns the array of email addresses in the envelope.
|
||||
func getTo(e *mail.Envelope) []string {
|
||||
var ret []string
|
||||
for _, addy := range e.RcptTo {
|
||||
ret = append(ret, addy.String())
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func display(b []byte) {
|
||||
s := string(b)
|
||||
fmt.Println("################################")
|
||||
fmt.Printf("%s\n", s)
|
||||
fmt.Println("################################")
|
||||
}
|
Reference in New Issue
Block a user