背景
由于在公司使用的邮箱容量比较小,在电脑上安装的收信的客户端没有设置在接收邮件之后删除服务器上的邮件,导致服务器的邮件容量不经意就快用尽了,因为我的邮箱经常要收到很多邮件,也不是业务繁忙,就是很多jira的通知邮件一下子就占满了,所以就研究了下如何登录公司的邮箱web页面,如何删除收件箱的所有邮件。
公司使用的邮箱系统是Winmail,它的官网是:Winmail官网
代码实现
整体的代码思路比较简单:
删除邮件大致逻辑
1、访问公司邮箱系统web页面:mail.xxxx.com
2、通过页面的sessid获取验证码,手动输入验证码,保存下来
3、获取一个key,和本地的密码一起使用AES加密获得加密后的密码
4、调用登录接口,返回一个tokenid和sessid
5、访问主页,不停地请求第一页的收件箱,每次请求都会查看收件箱的邮件数目是否为0,如果为0,
代表已经全部删除收件箱的邮件
6、对第一页的每一封邮件拿到对应的item序号,调用删除接口删除即可,我这里是一封邮件一封邮件删除的。
使用的语言是:Go
使用的框架是:Colly框架。 不了解的可以去官网研究下,后面我可能会出一下Colly官方文档的中文翻译。
主要就是两个文件:
main.go
app.ini
放在同一级目录下面。
下面就放一下代码:
# main.go
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gocolly/colly"
"gopkg.in/ini.v1"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"os"
"strconv"
)
type KeyResponse struct {
Result string `json:"result"`
Key string `json:"key"`
}
type LoginResponse struct {
Result string `json:"result"`
TokenId string `json:"tokenid"`
SessionId string `json:"sessid"`
}
var loginSessionId = ""
var userName = ""
var password = ""
var isLogin = false
var total = "1"
func init(){
cfg, err := ini.Load("app.ini")
if err != nil {
fmt.Println("配置文件app.ini读取错误", err)
os.Exit(1)
}
userName = cfg.Section("base").Key("user").String()
password = cfg.Section("base").Key("pwd").String()
}
func main() {
c := colly.NewCollector(
colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36"),
)
c.OnHTML("input[name=sessid]", func(e *colly.HTMLElement) {
if !isLogin{
loginSessionId = e.Attr("value")
checkCodeUrl := fmt.Sprintf("http://mail.xxx.com/chkcode.php?sessid=%s&retid=%s",loginSessionId,
strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
c.Visit(checkCodeUrl)
}
})
c.OnRequest(func(request *colly.Request) {
fmt.Println("开始访问 >> ", request.URL)
})
c.OnResponse(func(response *colly.Response) {
path := response.Request.URL.Path
if path == "/chkcode.php"{
// 保存验证码图片
ioutil.WriteFile("查看当前验证码.png", response.Body, 0755)
var checkCode = ""
fmt.Println("请输入本地验证码图片钟的验证码:")
fmt.Scanln(&checkCode)
key := getKey(loginSessionId)
if key == ""{
fmt.Println("获取密钥失败")
return
}
pwd := "{wm_aes}" + encryptPwd(password,key)
tokenId,sessionId := login(loginSessionId,userName,pwd,checkCode)
if tokenId != ""{
//删除验证码
err := os.Remove("查看当前验证码.png")
if err == nil{
fmt.Println("验证码图片删除成功!")
}
isLogin = true
}
var requestData = make(map[string]string)
requestData["sessid"] = sessionId
requestData["act"] = "login"
requestData["f_user"] = userName
requestData["f_pass"] = password
requestData["f_checkcode"] = checkCode
requestData["f_lang"] = "ch_gb"
requestData["f_theme"] = "default"
c.Post(fmt.Sprintf("http://mail.xxx.com/main.php?token=%s&email=liuchangrong@xxx.com",
tokenId),requestData)
// 循环删除第一页,如果收件箱还有邮件的话
for ;total != "0"; {
DeleteMail(c, sessionId)
}
}
})
c.Visit("http://mail.xxx.com/")
}
// 登录接口
func login(sessionId, userName, password, checkCode string) (string,string){
loginUrl := "http://mail.xxx.com/login.php"
data := make(url.Values)
data["sessid"] = []string{sessionId}
data["f_user"] = []string{userName}
data["f_domain"] = []string{""}
data["f_pass"] = []string{password}
data["f_checkcode"] = []string{checkCode}
data["f_lang"] = []string{"ch_gb"}
data["f_theme"] = []string{"default"}
data["f_autologin"] = []string{"0"}
data["f_result"] = []string{"json"}
res, err := http.PostForm(loginUrl, data)
if err != nil {
fmt.Println("登录接口出错:", err)
return "",""
}
defer res.Body.Close()
body, _:= ioutil.ReadAll(res.Body)
var loginResponse = &LoginResponse{}
json.Unmarshal(body,&loginResponse)
return loginResponse.TokenId, loginResponse.SessionId
}
/**
获取key
*/
func getKey(sessionId string) string{
keyUrl := fmt.Sprintf("http://mail.xxx.com/index.php?act=key&retid=%s",
strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
data := make(url.Values)
data["sessid"] = []string{sessionId}
//把post表单发送给目标服务器
res, err := http.PostForm(keyUrl, data)
if err != nil {
fmt.Println("请求密钥出错:", err)
return ""
}
defer res.Body.Close()
body, _:= ioutil.ReadAll(res.Body)
var keyResponse = &KeyResponse{}
json.Unmarshal(body,&keyResponse)
return keyResponse.Key
}
// 加密密码
func encryptPwd(pwd,key string) string{
return AesEncrypt(pwd,key)
}
func AesEncrypt(orig string, key string) string {
// 转成字节数组
origData := []byte(orig)
md5 := fmt.Sprintf("%x", md5.Sum([]byte(key)))
k := []byte(md5)
// 分组秘钥
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 补全码
origData = ZeroPadding(origData, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
// 创建数组
created := make([]byte, len(origData))
// 加密
blockMode.CryptBlocks(created, origData)
return base64.StdEncoding.EncodeToString(created)
}
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padText := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padText...)
}
//删除邮件
func DeleteMail(collector *colly.Collector, sessionId string){
collector.OnHTML("font[color=red]", func(element *colly.HTMLElement) {
//计算收件箱是否还有邮件
var cnt = element.Text
total = cnt
})
// 一次只能删除一封邮件
collector.OnHTML("input[type=checkbox][name^='item_']", func(element *colly.HTMLElement) {
var requestData = make(map[string]string)
requestData[element.Attr("name")] = element.Attr("value")
requestData["sessid"] = sessionId
requestData["act"] = "msglist"
requestData["opt"] = "drop"
requestData["folder"] = "INBOX"
requestData["msgid"] = ""
requestData["pag"] = "1"
requestData["listcount"] = "10"
requestData["tofolder"] = ""
requestData["sortby"] = "date"
requestData["sortorder"] = "DESC"
requestData["nameto"] = ""
requestData["mailto"] = ""
requestData["listtype"] = ""
requestData["label"] = ""
requestData["search"] = ""
collector.Post("http://mail.xxx.com/main.php",requestData)
fmt.Println("---------删除了序号为"+element.Attr("value")+"的邮件--------")
})
// 请求第一页收件箱的邮件列表
var requestData = make(map[string]string)
requestData["sessid"] = sessionId
requestData["act"] = "msglist"
requestData["opt"] = "list"
requestData["folder"] = "INBOX"
requestData["search"] = ""
requestData["listtype"] = ""
requestData["label"] = ""
collector.Post("http://mail.xxx.com/main.php",requestData)
}
# app.ini
[base]
# 邮箱名
user=liuchangrong@xxx.com
# 邮箱密码
pwd=xxx
以上就是删除收件箱邮件代码的全部实现,程序一运行的话,收件箱的邮件就会全部删除,删除之前千万要知道后果啊,别把有用的邮件删除了哦。
如果有什么疑问或者建议的话,欢迎在评论区留言!
如果觉得文章写的不错的话,希望一键三连哦!感谢您的观看!