用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协议发送一份邮件的更多相关文章

  1. C#使用SMTP协议发送验证码到QQ邮箱

    C#使用SMTP协议发送验证码到QQ邮箱 在程序设计中,发送验证码是常见的一个功能,用户在注册账号时或忘记密码后,通常需要发送验证码到手机短信或邮箱来验证身份,此篇博客介绍在C#中如何使用SMTP协议 ...

  2. C# WinForm 使用SMTP协议发送QQ邮箱验证码

    文章来自:https://blog.csdn.net/IT_xiao_guang_guang/article/details/104336604 前言   在程序设计中,发送验证码是常见的一个功能,用 ...

  3. PHP+socket+SMTP、POP3协议发送、接收邮件

    .实现SMTP协议的类dsmtp.cls.php:<?php            , $webname=).);     } } .实现POP3协议的类dpop3.cls.php: <? ...

  4. python3:利用SMTP协议发送QQ邮件+附件

    转载请表明出处:https://www.cnblogs.com/shapeL/p/9115887.html 1.发送QQ邮件,首先必须知道QQ邮箱的SMTP服务器 http://service.mai ...

  5. SMTP协议解读以及如何使用SMTP协议发送电子邮件

    电子邮件协议中POP3协议用于接收邮件,SMTP协议用于发送邮件.SMTP的全称为Simple Mail Transfer Protocol,也就是简单邮件传输协议,字如其名.   相较于POP3而言 ...

  6. 基于SMTP协议的CMD命令邮件发送

    网上有不少的这类的文章,以是参照这些文章后,自己实际运行的结果.系统使用的是WIN7 旗舰版. 1.打开CMD命令后,连接到SMTP服务器,如连接到QQ的SMTP服务,输入命令 telnet smtp ...

  7. python3之模块SMTP协议客户端与email邮件MIME对象

    转载自https://www.cnblogs.com/zhangxinqi/p/9113859.html 阅读目录 1.smtplib模块的常用类与方法 2.处理邮件MIME 3.实例 (1)使用HT ...

  8. JavaMail使用SMTP协议发送电子邮件(详解)

    Properties props = new Properties(); props.setProperty("mail.transport.protocol", "sm ...

  9. 发送邮件(遵循smtp协议即简单的邮件发送协议)

    HandleSendEmail.aspx逻辑 protected void Page_Load(object sender,EventArgs e) { foreach(var item in Req ...

随机推荐

  1. 获取系统的IP地址

    获取linux主机的IP地址 问题描述 在很多软件配置过程中,都需要设置ID信息,通常我选择使用系统配置的eth0网卡的IP地址信息,比如salt-minion-id,在通过cobbler批量安装操作 ...

  2. 安卓开发,Service 服务

    Service 服务 是一种应用组件,可长时间后台运行,不提供用户界面.如音乐播放器/下载程序.不能自己运行. 使用Service的方式: (一)startService(): 调用者和服务之间没有联 ...

  3. C++ 公有继承、保护继承和私有继承的对比

    在c++的继承控制中,有三种不同的控制权限,分别是public.protected和private.定义派生类时,若不显示加上这三个关键字,就会使用默认的方式,用struct定义的类是默认public ...

  4. C# CLosedXML四句代码搞定DataTable数据导出到Excel

    最近用到DataTable导出到Excel,网上看了一下,都不怎么好使,逛了下GitHub一下完美解决了 用到的.net库CLosedXML,这个库用于读取,处理和写入Excel 2007+(.xls ...

  5. Tensorflow入门学习笔记汇总

    一.环境准备 1.安装python:下载地址https://www.python.org/downloads/windows/下载并安装(推荐python3) 2.安装对应python版本的库:htt ...

  6. 最短路之Floyd

    #include<bits/stdc++.h>using namespace std;const int maxn = 300+10;int n,m,f[maxn][maxn],t; in ...

  7. Cannot resolve symbol window

    参照官网执行如下代码的时候,报了Cannot resolve symbol window错误. val windowedCounts = words.groupBy( window($"ti ...

  8. cbitmap 获取RGB

    CBitMap的用法   MFC提供了位图处理的基础类CBitmap,可以完成位图(bmp图像)的创建.图像数据的获取等功能.虽然功能比较少,但是在对位图进行一些简单的处理时,CBitmap类还是可以 ...

  9. .net core docker容器编排部署(linux)

    环境准备 需要一个linux操作系统:我这里用的是ubuntu 18.04,安装步骤就不说了,网上很多教程,当然也可以私信我. 既然需要用到docker,那么就安装个docker,apt instal ...

  10. 为DLL文件添加强名称

    程序在编译时出现类似 "错误 1 程序集生成失败 -- 引用的程序集“XXXXXXXXXX”没有强名称" 这样的错误,是因为它不是强名称的,则需要进行以下操作: 例如:com.so ...