1. 程式人生 > 實用技巧 >用CBrother指令碼實現smtp協議傳送一份郵件

用CBrother指令碼實現smtp協議傳送一份郵件

用CBrother指令碼實現smtp協議傳送一份郵件

之前用CBrother指令碼寫了一個拯救“小霸王伺服器”的程式,公司人用著都挺好用,但是有時候誰重啟了伺服器其他人不知道,造成了多人多次重啟,每個人都搶救一遍,大家一再要求我新增功能,有一個人重啟後給其他人發一封郵件。

靠,真是“飽暖思淫慾”,之前沒有這個重啟系統的時候,都得連到伺服器上去重啟,哎。。。人啊。。。。。

有“”祖傳背鍋俠“稱號的我也只能硬著頭皮去做了,於是用CBrother實現了smtp協議,可以傳送郵件了

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

//EMailSender是我封裝的郵件傳送類,全域性new一個
var mailSender = new EMailSender();
function main()
{
//啟動郵件傳送
mailSender.start(); //建立一個封郵件 Mail是我封裝的一個描述郵件內容的類
var mail = new Mail();
//設定傳送者的郵箱 的 名稱 地址 密碼
mail.setSender("zhangZsan","[email protected]","123456789");
//設定收件人 多個收件人就新增多條 SEND_TO表示是接收人
mail.addRecipient("boss","[email protected]",SEND_TO);
mail.addRecipient("erhuo","[email protected]",SEND_TO);
//設定抄送郵箱 SEND_CC表示抄送
mail.addRecipient("nvshen","[email protected]",SEND_CC);
//設定祕密抄送 SEND_BCC表示祕密抄送
mail.addRecipient("erdaye","[email protected]",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等。

當運行了以後,接收方就收到了

如果給手機上裝上郵箱APP,允許後臺推送,手機也會收到提醒,這可能是成本最低的實時通知到手機上的方式了吧。