因为建了一个邮件系统 https://mail.scwy.net,于是要保证它的安全。写个代码来自动检测,原理是:让此系统的A邮箱自动发一个邮件到B邮箱,再在B邮箱里接收。再从B邮箱从发送,从A邮箱中收取。
以下代码暂时只有前部份,即A发B并检查。
package main
import (
"bytes"
"crypto/tls"
"fmt"
"net/smtp"
"os"
"path"
"time"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/spf13/viper"
)
const timeFormat = "Mon, 02 Jan 2006 15:04:05 -0700 (MST)"
var debug bool
func Debug(info ...interface{}) {
if debug {
info = append([]interface{}{time.Now().Format("2006-01-02 15:04:05")}, info...)
fmt.Println(info...)
}
}
func main() {
Debug("读取配置")
// 设置要读取的文件名和路径
viper.SetConfigFile(path.Base(os.Args[0]) + ".json")
viper.AddConfigPath(".")
// 读取配置文件
if err := viper.ReadInConfig(); err != nil {
fmt.Println("无法读取配置文件,配置文件与程序名保持一致:", err.Error())
return
}
// 输出解析后的结果
fromUser := viper.GetString("from_mail")
from_password := viper.GetString("from_password")
from_smtp_host := viper.GetString("from_smtp_host")
from_smtp_prot := viper.GetString("from_smtp_prot")
toUser := viper.GetString("to_mail")
toImap := viper.GetString("to_imap")
to_password := viper.GetString("to_password")
check_subject := viper.GetString("check_subject")
debug = viper.GetBool("debug")
Debug("发送...")
SendMail(fromUser, toUser, from_password, check_subject, from_smtp_host, from_smtp_prot)
Debug("等待...")
time.Sleep(20 * time.Second)
Debug("检查...")
ret := GetMail(fromUser, toUser, to_password, check_subject, toImap, 4)
if ret == false {
Debug("检测异常")
os.Exit(1)
} else {
Debug("检测正常")
}
}
// check_time 验证邮件的时间 check_subject 验证的标题
func GetMail(from_mail, to_mail, to_password, check_subject, to_imap_host string, check_time int) (ret bool) {
// 连接服务器
c, err := client.DialTLS(to_imap_host, nil)
if err != nil {
Debug(err.Error())
}
defer c.Logout()
// 登录认证
if err := c.Login(to_mail, to_password); err != nil {
Debug(err.Error())
}
// 选择邮箱文件夹
mbox, err := c.Select("INBOX", false)
if err != nil {
Debug(err.Error())
}
// 获取未读邮件列表
from := uint32(1)
to := mbox.Messages
seqset := new(imap.SeqSet)
seqset.AddRange(from, to)
messages := make(chan *imap.Message, 10)
done := make(chan error, 1)
go func() {
done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchBodyStructure}, messages)
}()
for msg := range messages {
t, _ := time.Parse(time.RFC822Z, msg.Envelope.Date.Format(time.RFC822Z))
// 打印邮件信息
if msg.Envelope.From[0].Address() == from_mail &&
time.Now().Sub(t) <= time.Duration(check_time)*time.Minute &&
msg.Envelope.Subject == check_subject {
//fmt.Printf("From: %s \t Subject: %s Time: %s \n", msg.Envelope.From[0].Address(), msg.Envelope.Subject, msg.Envelope.Date)
seqset := new(imap.SeqSet)
seqset.AddNum(msg.SeqNum)
err := c.Store(seqset, imap.FormatFlagsOp(imap.AddFlags, true), []interface{}{imap.DeletedFlag}, nil)
if err != nil {
Debug(err.Error())
}
// log.Printf("Deleted message %d", seqset)
// 永久删除已标记为删除的邮件
if err := c.Expunge(nil); err != nil {
Debug(err.Error())
}
ret = true
break
}
}
if err := <-done; err != nil {
Debug(err.Error())
}
return
}
func SendMail(from_mail, to_mail, from_password, check_subject, smtp_host, smtp_port string) {
// 连接 SMTP 服务器
auth := smtp.PlainAuth("", from_mail, from_password, smtp_host)
client, err := smtp.Dial(smtp_host + ":" + smtp_port)
if err != nil {
Debug("连接 SMTP 服务器失败:", err.Error())
os.Exit(1)
}
defer client.Close()
// 开启TLS加密
config := &tls.Config{InsecureSkipVerify: true}
if err = client.StartTLS(config); err != nil {
Debug("无法启用 TLS 加密:", err.Error())
os.Exit(1)
}
// 认证
if err = client.Auth(auth); err != nil {
Debug("SMTP 认证失败:", err.Error())
os.Exit(1)
}
// 设置发件人和收件人
if err = client.Mail(from_mail); err != nil {
Debug("设置发件人失败:", err.Error())
os.Exit(1)
}
if err = client.Rcpt(to_mail); err != nil {
Debug("设置收件人失败:", err.Error())
os.Exit(1)
}
// 构造邮件内容
var buffer bytes.Buffer
// 设置邮件头
headers := make(map[string]string)
headers["From"] = from_mail
headers["To"] = to_mail
headers["Subject"] = check_subject
for k, v := range headers {
fmt.Fprintf(&buffer, "%s: %s\r\n", k, v)
}
// 设置邮件正文
fmt.Fprintf(&buffer, "\r\n%s\r\n", check_subject) // 标题与内容一样
// 发送邮件
if err = smtp.SendMail(smtp_host+":"+smtp_port, auth, from_mail, []string{to_mail}, buffer.Bytes()); err != nil {
Debug("发送失败:", err.Error())
os.Exit(1)
}
Debug("发送成功")
}
配置文件
{
"from_mail": "ease@scwy.net",
"from_password": "123123123",
"from_smtp_host": "mail.scwy.net",
"from_smtp_prot": "587",
"to_mail": "scwy@qq.com",
"to_imap": "imap.qq.com:993",
"to_password": "asdfasdfasd",
"check_subject": "一个测试邮件",
"debug": "true"
}