用CBrother腳本實現smtp協議發送一份郵件

用CBrother腳本實現smtp協議發送一份郵件

以前用CBrother腳本寫了一個拯救「小霸王服務器」的程序,公司人用着都挺好用,可是有時候誰重啓了服務器其餘人不知道,形成了多人屢次重啓,每一個人都搶救一遍,你們一再要求我添加功能,有一我的重啓後給其餘人發一封郵件。html

靠,真是「飽暖思淫慾」,以前沒有這個重啓系統的時候,都得連到服務器上去重啓,哎。。。人啊。。。。。緩存

有「」祖傳背鍋俠「稱號的我也只能硬着頭皮去作了,因而用CBrother實現了smtp協議,能夠發送郵件了服務器

先來看看封裝的發郵件EMailSender類的用法:

//EMailSender是我封裝的郵件發送類,全局new一個
var mailSender = new EMailSender();
function main()
{
    //啓動郵件發送
    mailSender.start();

    //建立一個封郵件 Mail是我封裝的一個描述郵件內容的類
    var mail = new Mail();
    //設置發送者的郵箱 的 名稱 地址 密碼
    mail.setSender("zhangZsan","zhangZsan1122334@163.com","123456789");
    //設置收件人 多個收件人就添加多條  SEND_TO表示是接收人
    mail.addRecipient("boss","myboss_aaaa123@qq.com",SEND_TO);
    mail.addRecipient("erhuo","erhuo_aaaa123@qq.com",SEND_TO);
    //設置抄送郵箱 SEND_CC表示抄送
    mail.addRecipient("nvshen","nvshen_aaa123@163.com",SEND_CC);
    //設置祕密抄送 SEND_BCC表示祕密抄送
    mail.addRecipient("erdaye","erdaye_aaa123@qq.com",SEND_BCC);
    //設置右鍵標題
    mail.setTitle("服務器被重啓了");
    //設置右鍵內容
    mail.setValue("服務器被erhuo重啓了.");
    //發送郵件
    mailSender.sendMail(mail);

    //sendMail調用一次發一封,調用兩次發兩封

    while (1)
    {
        Sleep(1000);
    }
}

使用仍是很簡單了,對於封裝,我是認真的,哈哈。固然,這裏面的郵箱地址都是胡寫的,你不用去163試密碼了。。。。。多線程

再來看看實現代碼:

//包含cbrother的socket模塊
import CBSocket.code

//這些定義是發送郵件的步驟,能夠忽略不看
const MAIL_STEP_NORMAL = 0;
const MIAL_STEP_EHLO = 1;
const MAIL_STEP_LOGIN = 2;
const MAIL_STEP_ACCOUNT = 3;
const MAIL_STEP_PWD = 4;
const MAIL_STEP_FROM = 5;
const MAIL_STEP_DATA = 6;
const MAIL_STEP_QUIT = 7;
const MAIL_STEP_OVER = 8;

//郵件內容分割線,郵件格式協議裏要的,你能夠改爲本身的
const SPLIC_MAIL = "--_CBROTHER_MAIL_202020202020";

//收件人類型
const SEND_TO = 0;    //接收者
const SEND_CC = 1;    //抄送
const SEND_BCC = 2;    //祕密抄送

//郵件接收者類
class MailUser
{
    var Name;    //名字
    var Addr;    //郵箱地址
    var Type;    //類型
}

//描述一封右鍵
class Mail
{
    var _SmtpHost;    //smpt服務器地址
    var _Sender = new MailUser();      //發送者
    var _SendPwd;                      //發送者密碼
    var _Recipient = new Array();      //接收者列表
    var _MailTitle;                    //郵件標題
    var _MailValue;                    //郵件內容

    //設置發送者信息
    function setSender(senderName,senderAddr,senderPwd)
    {
        var strArr = strsplit(senderAddr,"@");
        if (strArr.size() != 2)
        {
            return false;
        }
        
        this._SmtpHost = "smtp." + strArr[1];
        this._SendPwd = senderPwd;

        _Sender.Name = senderName;
        _Sender.Addr = senderAddr;
        return true;
    }

    //添加接收者
    function addRecipient(name,addr,type)
    {
        foreach (k,v : _Recipient)
        {
            if (v.Addr == addr)
            {
                v.Name = name;
                v.Type = type;
                return;                
            }  
        }

        var r = new MailUser();
        r.Addr = addr;
        r.Name = name;
        r.Type = type;
        _Recipient.add(r);
    }

    //設置右鍵標題
    function setTitle(title)
    {
        this._MailTitle = title;        
    }

    //設置右鍵內容
    function setValue(value)
    {
        this._MailValue = value;        
    }
}

//右鍵發送過程當中須要的一些數據
class MailBuf
{
    var _mail;        //郵件 Mail類對象
    var _byteArray = new ByteArray();    //數據緩存
    var _step = MAIL_STEP_NORMAL;        //右鍵發送的步驟
    var _socketid;                        //這封優先的socketid
    var _recvsendidx = 0;                //發送接收者過程當中的一個臨時變量
}

//這個類是郵件發送的smtp協議的主要實現
class EMailSender
{
    var _tcpModule = new TcpModule();    //tcp模塊
    var _Lock = new Lock();              //多線程互斥鎖
    var _mailMap = new Map();            //存儲郵件的map

    //啓動郵件服務
    function start()
    {
        _tcpModule.setTcpAction(this);
        _tcpModule.start();
    }

    //發送一封郵件
    function sendMail(mail)
    {
        //鏈接對方smtp服務器
        var socketid = _tcpModule.connect(mail._SmtpHost,25);
        print "connect " + mail._SmtpHost + " "  +socketid;
        if (socketid == 0)
        {
            print "socketid == 0";
            return;            
        }
        
        //鏈接成功後將socketid和mail綁定,這裏多線程有可能OnConnect回調先執行
        _Lock.lock();
        var mailbuf = _mailMap.get(socketid);
        if (mailbuf == null)
        {
            mailbuf = new MailBuf();
            mailbuf._socketid = socketid;
            _mailMap.add(socketid,mailbuf);
        }
        _Lock.unlock();

        mailbuf._mail = mail;
    }

    //鏈接上服務器
    function OnConnect(sock)
    {
        print "onconnect " + sock;
        _Lock.lock();
        var mailbuf = _mailMap.get(sock);
        if (mailbuf == null)
        {
            mailbuf = new MailBuf();
            mailbuf._socketid = socketid;
            _mailMap.add(socketid,mailbuf);
        }
        _Lock.unlock();

        if (mailbuf == null)
        {
            print "OnConnect mail is null";
            _tcpModule.closeSocket(sock);
            return;
        }
    }

    //和服務器鏈接斷開
    function OnClose(sock)
    {
        print "onclose " + sock;
        _Lock.lock();
        _mailMap.remove(sock);
        _Lock.unlock();
    }

    //收到數據
    function OnRecv(sock,byteArray,len)
    {
        _Lock.lock();
        var mailbuf = _mailMap.get(sock);
        _Lock.unlock();

        if (mailbuf == null)
        {
            print "recv mail is null";
            _tcpModule.closeSocket(sock);
            return true;
        }

        mailbuf._byteArray.writeBytes(byteArray,len);        
        print "r:" + mailbuf._byteArray.getReadPos();
        print "w:" + mailbuf._byteArray.getWritePos();
        MakeMail(mailbuf);
        return true;
    }

    //從數據裏獲取一行,\r\n結束
    function GetLine(byteArray)
    {
        var rpos = byteArray.getReadPos();
        var wpos = byteArray.getWritePos();

        //print "rpos:" + rpos + " wpos:" + wpos;

        var res;
        for (var i = rpos; i < wpos ; i++)
        {
            if (byteArray.getByte(i) == '\r')
            {
                if (i + 1 < wpos)
                {
                    if (byteArray.getByte(i) == '\n')
                    {
                        res = byteArray.readString(i - rpos);
                        byteArray.copy(byteArray,0,i + 2,wpos - i - 2);
                        byteArray.setReadPos(0);
                        byteArray.setWritePos(wpos - i - 2);
                        break;
                    }
                }
                else
                {
                    return null;
                }
            }
            else if (byteArray.getByte(i) == '\n')
            {
                res = byteArray.readString(i - rpos);
                byteArray.copy(byteArray,0,i + 1,wpos - i - 1);
                byteArray.setReadPos(0);
                byteArray.setWritePos(wpos - i - 1);
                break;
            }
        }

        //print "end rpos:" + byteArray.getReadPos() + " wpos:" + byteArray.getWritePos();
        return res;
    }

    //驗證服務器返回數據是否正確
    function RecvValue(mailbuf,str)
    {
        var value = GetLine(mailbuf._byteArray);
        if (value == null)
        {
            return 0;            
        }

        print value;
        //print strlen(value);

        var len = strlen(str);
        var lenvalue = strlen(value);
        if (lenvalue < len)
        {
            return 2;            
        }

        var getstr = strget(value,0,len);
        if (str != getstr)
        {
            return 2;            
        }
        return 1;
    }    
    
    //EHLO有特殊性,單數寫一個函數
    function RecvEHLO(mailbuf,str)
    {
        while (true)
        {
            var value = GetLine(mailbuf._byteArray);
            if (value == null)
            {
                return 0;            
            }

            print value;
            //print strlen(value);

            var len = strlen(str);
            var lenvalue = strlen(value);
            if (lenvalue < len)
            {
                return 2;            
            }

            var getstr = strget(value,0,len);
            if (str != getstr)
            {
                return 2;            
            }

            if (strget(value,3,4) == " ")
            {
                return 1;                             
            }          
        }

        return 0;
    }

    //這裏面主要就是smtp協議部分了,要看懂須要去學習一下
    function MakeMail(mailbuf)
    {
        switch (mailbuf._step)
        {
            case MAIL_STEP_NORMAL:
            {
                var res = RecvValue(mailbuf,"220");
                if(res == 2)
                {
                    print "MAIL_STEP_NORMAL mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = "EHLO " +   mailbuf._mail._SmtpHost + "\r\n";
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MIAL_STEP_EHLO;
                }

                break;
            }
            case MIAL_STEP_EHLO:
            {
                var res = RecvEHLO(mailbuf,"250");
                if(res == 2)
                {
                    print "MIAL_STEP_EHLO mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = "AUTH LOGIN\r\n";
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_LOGIN;
                }
                break;
            }
            case MAIL_STEP_LOGIN:
            {
                var res = RecvValue(mailbuf,"334");
                if(res == 2)
                {
                    print "MAIL_STEP_LOGIN mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = base64_encode(mailbuf._mail._Sender.Addr) + "\r\n";
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_ACCOUNT;    
                }
                break;
            }
            case MAIL_STEP_ACCOUNT:
            {
                var res = RecvValue(mailbuf,"334");
                if(res == 2)
                {
                    print "MAIL_STEP_ACCOUNT mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = base64_encode(mailbuf._mail._SendPwd) + "\r\n";
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_PWD;    
                }
                break;
            }
            case MAIL_STEP_PWD:
            {
                var res = RecvValue(mailbuf,"235");
                if(res == 2)
                {
                    print "MAIL_STEP_PWD mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = "MAIL FROM: <" + mailbuf._mail._Sender.Addr + ">\r\n";
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_FROM;    
                }                   
                break;
            }
            case MAIL_STEP_FROM:
            {
                var res = RecvValue(mailbuf,"250");
                if(res == 2)
                {
                    print "MAIL_STEP_FROM mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    if (mailbuf._recvsendidx < mailbuf._mail._Recipient.size())
                    {
                        var mailsend = "RCPT TO: <" + mailbuf._mail._Recipient[mailbuf._recvsendidx++].Addr + ">\r\n";
                        print mailsend;
                        this._tcpModule.sendData(mailbuf._socketid,mailsend);
                        mailbuf._step = MAIL_STEP_FROM;
                    }
                    else
                    {
                        var mailsend = "DATA\r\n";
                        print mailsend;
                        this._tcpModule.sendData(mailbuf._socketid,mailsend);
                        mailbuf._step = MAIL_STEP_DATA;
                    }
                }
                break;
            }
            case MAIL_STEP_DATA:
            {
                var res = RecvValue(mailbuf,"354");
                if(res == 2)
                {
                    print "MAIL_STEP_DATA mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = MakeMailHead(mailbuf);
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);

                    mailsend = MakeMailValue(mailbuf);
                    print mailsend;
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_QUIT;
                }
                break;
            }
            case MAIL_STEP_QUIT:
            {
                var res = RecvValue(mailbuf,"250");
                if(res == 2)
                {
                    print "MAIL_STEP_QUIT mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }

                if (res == 1)
                {
                    var mailsend = "QUIT\r\n";
                    this._tcpModule.sendData(mailbuf._socketid,mailsend);
                    mailbuf._step = MAIL_STEP_OVER;
                }

                break;
            }
            case MAIL_STEP_OVER:
            {
                var res = RecvValue(mailbuf,"221");
                if(res == 2)
                {
                    print "MAIL_STEP_OVER mail send err!" + mailbuf._mail._SmtpHost;
                    break;
                }              

                if (res == 1)
                {
                    this._tcpModule.closeSocket(mailbuf._socketid);
                    print "mail send success:" + mailbuf._mail._SmtpHost;
                }  
                break;
            }
            default:
            {
                break;
            }
        }
    }

    function MimeCode(basestr)
    {
        return "=?utf-8?b?" + base64_encode(basestr) + "?=";
    }

    function MakeMailHead(mailbuf)
    {
        var myTime = new Time(time() - 28800);
        var head = "Date: " + myTime.strftime("%a, %d %b %Y %H:%M:%S GMT") + "\r\n";
        
        head += "From: \"" + MimeCode(mailbuf._mail._Sender.Name) + "\" <" + mailbuf._mail._Sender.Addr + ">\r\n";
        head += "To: ";

        var ccmsg = "Cc: ";
        var ccflag = 0;
        var bccmsg = "Bcc: ";
        var bccflag = 0;
        for (var i = 0; i < mailbuf._mail._Recipient.size() ; i++)
        {
            var sender = mailbuf._mail._Recipient[i];
            if (sender.Type == SEND_TO)
            {
                if (i != 0)
                {
                    head += ",";
                }

                head += "\"" + MimeCode(sender.Name) + "\" <" + sender.Addr + ">";
            }
            else if (sender.Type == SEND_CC)
            {
                if (ccflag++ != 0)
                {
                    ccmsg += ",";
                }

                ccmsg += "\"" + MimeCode(sender.Name) + "\" <" + sender.Addr + ">";
            }
            else
            {
                if (bccflag++ != 0)
                {
                    bccmsg += ",";
                }

                bccmsg += "\"" + MimeCode(sender.Name) + "\" <" + sender.Addr + ">";
            }
        }

        head += "\r\n";

        if (ccmsg != "Cc: ")
        {
            head += ccmsg + "\r\n";            
        }

        if (bccmsg != "Bcc: ")
        {
            head += bccmsg + "\r\n";            
        }

        head += "Subject: " + MimeCode(mailbuf._mail._MailTitle) + "\r\n";

        head += "MIME-Version: 1.0\r\n";
        head += "Content-type: multipart/mixed; boundary=\"" + SPLIC_MAIL + "\"\r\n";
        head += "\r\n";

        return head;
    }

    function MakeMailValue(mailbuf)
    {
        var valuemsg = "--" + SPLIC_MAIL + "\r\n";
        valuemsg += "Content-Type: text/html; charset=utf-8\r\n";
        valuemsg += "Content-Transfer-Encoding: base64\r\n\r\n";
        valuemsg += base64_encode(mailbuf._mail._MailValue) + "\r\n";
        valuemsg += "\r\n--" + SPLIC_MAIL + "--\r\n" + ".\r\n";
        return valuemsg;
    }
}

我自認爲封裝的仍是比較簡單的,固然若是你要用這個代碼發郵件,那麼你本身的郵箱必須開啓smtp受權,如何開啓,不一樣廠商提供的郵箱方式都不同,通常都是登陸到郵箱裏設置一個東西具體你能夠百度一下本身的郵箱,好比搜索:163郵箱如何開啓smtp,qq郵箱如何開啓smtp等。socket

當運行了之後,接收方就收到了tcp

 

 

 

 若是給手機上裝上郵箱APP,容許後臺推送,手機也會收到提醒,這多是成本最低的實時通知到手機上的方式了吧。函數

相關文章
相關標籤/搜索