Created
July 26, 2020 13:21
-
-
Save CzBiX/bd69c9e342e89c75b203b100d0cafa42 to your computer and use it in GitHub Desktop.
The tiny mail command write in golang.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/tls" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"net" | |
"net/smtp" | |
"os" | |
"os/user" | |
"strings" | |
) | |
const sslPort = 465 | |
func main() { | |
subject := flag.String("subject", "", "subject") | |
flag.Parse() | |
address := flag.Arg(0) | |
if address == "" { | |
panic("Invalid email address") | |
} | |
msg := getMessage(*subject) | |
err := sendMail(address, msg) | |
if err != nil { | |
panic(err) | |
} | |
} | |
func sendMail(to string, msg []byte) error { | |
mailname := getMailname() | |
from := fmt.Sprintf("%s@%s", getUsername(), mailname) | |
server, conn := getServerConn(to) | |
c, err := smtp.NewClient(conn, server) | |
if err != nil { | |
return err | |
} | |
defer c.Close() | |
if err = c.Hello(mailname); err != nil { | |
return err | |
} | |
if err = c.Mail(from); err != nil { | |
return err | |
} | |
if err = c.Rcpt(to); err != nil { | |
return err | |
} | |
w, err := c.Data() | |
if err != nil { | |
return err | |
} | |
_, err = w.Write(msg) | |
if err != nil { | |
return err | |
} | |
err = w.Close() | |
if err != nil { | |
return err | |
} | |
return c.Quit() | |
} | |
func getUsername() string { | |
user, err := user.Current() | |
if err != nil { | |
panic(err) | |
} | |
return user.Username | |
} | |
func getMailname() string { | |
data, err := ioutil.ReadFile("/etc/mailname") | |
if err != nil { | |
hostname, err := os.Hostname() | |
if err != nil { | |
panic(err) | |
} | |
return hostname | |
} | |
content := string(data) | |
return strings.TrimSpace(strings.SplitN(content, "\n", 1)[0]) | |
} | |
func getServerConn(address string) (string, *tls.Conn) { | |
server := strings.Split(address, "@")[1] | |
mxs, err := net.LookupMX(server) | |
if err != nil { | |
panic(err) | |
} | |
host := mxs[0].Host | |
tlsConfig := &tls.Config{ | |
ServerName: server, | |
} | |
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", host, sslPort), tlsConfig) | |
if err != nil { | |
panic(err) | |
} | |
return server, conn | |
} | |
func getMessage(subject string) []byte { | |
buf, err := ioutil.ReadAll(os.Stdin) | |
if err != nil { | |
panic(err) | |
} | |
if subject == "" { | |
return buf | |
} | |
h := fmt.Sprintf("Subject: %s\r\n\r\n", subject) | |
buf = append([]byte(h), buf...) | |
return buf | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment