这是几年以前,写的一个用于 gogs 服务进行推送通知到邮件的程序。那时候还不会写GO
程序,于是用C++写的,麻烦得很。用GO
来写同样的程序要省事多了。
代码
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Util/ServerApplication.h>
#include <Poco/StreamCopier.h>
#include <Poco/Util/IniFileConfiguration.h>
#include <Poco/URI.h>
#include <Poco/StringTokenizer.h>
#include <Poco/JSON/Parser.h>
#include <Poco/JSON/Object.h>
#include <Poco/Dynamic/Var.h>
#include <Poco/Net/MailMessage.h>
#include <Poco/Net/StringPartSource.h>
#include <Poco/Net/SMTPClientSession.h>
#include <Poco/Net/SecureSMTPClientSession.h>
#include <Poco/Exception.h>
#include <iostream>
using namespace Poco;
using namespace Poco::Net;
using namespace Poco::Util;
using namespace Poco::JSON;
static std::string mailuser,mailpasswd;
class HelloRequestHandler: public HTTPRequestHandler
{
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
Application& app = Application::instance();
try{
std::istream& is = request.stream();
std::string body;
StreamCopier::copyToString(is,body);
Poco::Net::HTTPResponse::HTTPStatus status = Poco::Net::HTTPResponse::HTTP_NOT_FOUND;
Poco::URI uri(request.getURI());
if(uri.getPath() != "/release"){
throw status;
}
std::string query = uri.getQuery();
if(query.find("NotifyParty") != 0){
throw status;
}
Poco::StringTokenizer tok(query.substr(sizeof("NotifyParty")),";",1);
std::vector<std::string> notifyParty(tok.begin(),tok.end());
Poco::Net::MailMessage message;
Poco::JSON::Parser jsonparser;
Poco::Dynamic::Var result = jsonparser.parse(body);
Object::Ptr rootObj = result.extract<Object::Ptr>();
Object::Ptr releaseObj = rootObj->getObject("release");
Object::Ptr repositoryObj = rootObj->getObject("repository");
Object::Ptr authorObj = releaseObj->getObject("author");
// 获取邮件标题
std::string mailSubject = "版本发布:" + repositoryObj->getValue<std::string>("name")
+ " " + releaseObj->getValue<std::string>("name");
message.setSubject(mailSubject);
// 获取创建时间
std::string mailDatetime = releaseObj->getValue<std::string>("created_at");
Poco::DateTime dt; int tzd; /*tzd 用于获取时区差值*/
Poco::DateTimeParser::parse(Poco::DateTimeFormat::ISO8601_FORMAT, mailDatetime, dt, tzd);
message.setDate(dt.timestamp() - Poco::Timespan(tzd,0));
mailDatetime = Poco::DateTimeFormatter::format(dt.timestamp(),"%Y年%m月%d日 %H:%M:%S");
// 获取发布内容
std::string mailbody;
mailbody.append("
项 目:").append(repositoryObj->getValue<std::string>("name"));
mailbody.append("
描 述:").append(repositoryObj->getValue<std::string>("description"));
mailbody.append("
版本标题:").append(releaseObj->getValue<std::string>("name"));
mailbody.append("
版本标签:").append(releaseObj->getValue<std::string>("tag_name"));
mailbody.append("
版本描述:").append(releaseObj->getValue<std::string>("body"));
mailbody.append("
发布时间:").append(mailDatetime);
mailbody.append("
发布作者:").append(authorObj->getValue<std::string>("full_name"));
mailbody.append("
访问地址:").append(repositoryObj->getValue<std::string>("html_url"));
message.setContentType("text/html;charset=utf-8");
message.addContent(new Poco::Net::StringPartSource(mailbody));
//message.setContent(mailbody);
message.setSender(mailuser);
for(auto& r: notifyParty) {
message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, r));
}
//app.logger().information("开始登录");
// 发送邮件
//Poco::Net::SMTPClientSession smtpSession("smtp.exmail.qq.com");
Poco::Net::SecureSMTPClientSession smtpSession("smtp.exmail.qq.com");
smtpSession.open();
// smtpSession.login(Poco::Net::SMTPClientSession::LoginMethod::AUTH_LOGIN, mailuser, mailpasswd);
smtpSession.login();
smtpSession.startTLS();
smtpSession.login(Poco::Net::SMTPClientSession::LoginMethod::AUTH_LOGIN, mailuser, mailpasswd);
//app.logger().information("开始发送邮件");
smtpSession.sendMessage(message);
// app.logger().information("发送邮件完成");
smtpSession.close();
}
catch (Poco::Exception& e) {
app.logger().error("Poco Exception(%s)
", e.displayText());
}
catch (std::exception& e) {
app.logger().error("std Exception(%s)
", e.what());
}
catch(Poco::Net::HTTPResponse::HTTPStatus s){
response.setStatusAndReason(s);
response.send();
return;
}
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK);
response.send();
}
};
class HelloRequestHandlerFactory: public HTTPRequestHandlerFactory
{
HTTPRequestHandler* createRequestHandler(const HTTPServerRequest&)
{
return new HelloRequestHandler;
}
};
class WebServerApp: public ServerApplication
{
void initialize(Application& self)
{
loadConfiguration();
ServerApplication::initialize(self);
}
int main(const std::vector<std::string>&)
{
try{
// 读取gogs配置
AutoPtr<IniFileConfiguration> pConf(new IniFileConfiguration("./custom/conf/app.ini"));
mailuser = pConf->getString("mailer.USER");
mailpasswd = pConf->getString("mailer.PASSWD");
logger().information("Email User is %s",mailuser);
logger().information("Email Password is %s",mailpasswd);
UInt16 port = static_cast<UInt16>(config().getUInt("port", 3001));
HTTPServer srv(new HelloRequestHandlerFactory, port);
srv.start();
logger().information("HTTP Server started on port %hu.", port);
waitForTerminationRequest();
logger().information("Stopping HTTP Server...");
srv.stop();
return Application::EXIT_OK;
}
catch (Poco::Exception& e) {
logger().error("Poco Exception(%s)
", e.displayText());
}
catch (std::exception& e) {
logger().error("std Exception(%s)
", e.what());
}
catch (...) {
logger().error("Unknown Exception");
}
return Application::EXIT_OK;
}
};
POCO_SERVER_MAIN(WebServerApp)
Makefile
CXX=g++
LIBS= -lPocoNetSSL -lPocoNet -lPocoJSON -lPocoUtil -lPocoFoundation -lpthread
all:SendMail
SendMail:SendMail.cpp
$(CXX) -o $@ -std=c++11 $^ $(LIBS) -Wl,-rpath=/usr/local/lib
clean:
rm SendMail