用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","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等。
当运行了以后,接收方就收到了


如果给手机上装上邮箱APP,允许后台推送,手机也会收到提醒,这可能是成本最低的实时通知到手机上的方式了吧。
用CBrother脚本实现smtp协议发送一份邮件的更多相关文章
- C#使用SMTP协议发送验证码到QQ邮箱
C#使用SMTP协议发送验证码到QQ邮箱 在程序设计中,发送验证码是常见的一个功能,用户在注册账号时或忘记密码后,通常需要发送验证码到手机短信或邮箱来验证身份,此篇博客介绍在C#中如何使用SMTP协议 ...
- C# WinForm 使用SMTP协议发送QQ邮箱验证码
文章来自:https://blog.csdn.net/IT_xiao_guang_guang/article/details/104336604 前言 在程序设计中,发送验证码是常见的一个功能,用 ...
- PHP+socket+SMTP、POP3协议发送、接收邮件
.实现SMTP协议的类dsmtp.cls.php:<?php , $webname=).); } } .实现POP3协议的类dpop3.cls.php: <? ...
- python3:利用SMTP协议发送QQ邮件+附件
转载请表明出处:https://www.cnblogs.com/shapeL/p/9115887.html 1.发送QQ邮件,首先必须知道QQ邮箱的SMTP服务器 http://service.mai ...
- SMTP协议解读以及如何使用SMTP协议发送电子邮件
电子邮件协议中POP3协议用于接收邮件,SMTP协议用于发送邮件.SMTP的全称为Simple Mail Transfer Protocol,也就是简单邮件传输协议,字如其名. 相较于POP3而言 ...
- 基于SMTP协议的CMD命令邮件发送
网上有不少的这类的文章,以是参照这些文章后,自己实际运行的结果.系统使用的是WIN7 旗舰版. 1.打开CMD命令后,连接到SMTP服务器,如连接到QQ的SMTP服务,输入命令 telnet smtp ...
- python3之模块SMTP协议客户端与email邮件MIME对象
转载自https://www.cnblogs.com/zhangxinqi/p/9113859.html 阅读目录 1.smtplib模块的常用类与方法 2.处理邮件MIME 3.实例 (1)使用HT ...
- JavaMail使用SMTP协议发送电子邮件(详解)
Properties props = new Properties(); props.setProperty("mail.transport.protocol", "sm ...
- 发送邮件(遵循smtp协议即简单的邮件发送协议)
HandleSendEmail.aspx逻辑 protected void Page_Load(object sender,EventArgs e) { foreach(var item in Req ...
随机推荐
- Android学习笔记基于回调的事件处理
流程: 常见的回调方法: 代码示例: @Override public boolean onTouchEvent(MotionEvent event) { Toast.makeText(getAppl ...
- Mybatis框架-CRUD
1 2 3 传统dao开发实现CRUD 3.1 传统dao开发实现crud 使用 Mybatis 开发 Dao,通常有两个方法,即原始 Dao开发方式和 Mapper 接口代理开发方式.而 ...
- Redis源码阅读一:简单动态字符串SDS
源码阅读基于Redis4.0.9 SDS介绍 redis 127.0.0.1:6379> SET dbname redis OK redis 127.0.0.1:6379> GET dbn ...
- .NET Core Hangfire周期性作业调度问题
前言 四月中旬Hangfire团队发布了1.7.11版本,在使用周期性作业调度过程中发现一个问题,这个问题应该一直未解决,故做此记录,希望遇到的童鞋根据项目业务而避开这个问题. 周期性作业调度 我们依 ...
- Perl入门(二)Perl的流程控制
Perl是一种粘性语言,如果你有其他语言的基础的话,你会发现他的流程控制完全和你所知的一模一样. 简单说一下他们的区别: Perl的elsif在其他语言里头可能表示为else if Perl的last ...
- 使用spring-test时报错
java.lang.NoClassDefFoundError: org/springframework/core/annotation/MergedAnnotations$SearchStrategy ...
- 如何在一个HTML文件中嵌套另一个HTML文件并且可以进行切换HTML文件
使用iframe 要点:a标签+iframe A标签的target属性 iframe 的id与name属性 示例: <!DOCTYPE html> <html> <hea ...
- 前端基础:HTTP 协议详解
参考:https://kb.cnblogs.com/page/130970/#httpmeessagestructe HTTP协议是无状态的 http协议是无状态的,同一个客户端的这次请求和上次请求是 ...
- vs2010调试运行时弹出对话框:系统找不到指定文件
很多时候,我们会将一些低版本IDE编译过的项目,搬迁到VS2010 ,那么会存在很多编译,调试问题.[1] 编译成功了.可是无法调试 . . 显示 无法启动程序“...........\t ...
- 接口&&多态&&构造函数&&关键字
day06 抽象类的局限性(与接口的区别) 抽象类可以定义非抽象方法,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;jdk1.8之后接口可以包含默认方法. 一个类只能继承一个直接父类 ...