0510 15:15 gtest邮件可发送 创建session类 记录全局链接会话 时间轮记录session超时。
邮件验证码 可以发送 c端test 没写 验证验证码注册还未完成
This commit is contained in:
@@ -33,7 +33,7 @@ int main(int argc, char **argv) {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
auto request = new Request(mp::MP_REQUEST_REGISTER, 783556037, "Aa316216");
|
||||
auto request = new Request(mp::MP_REQUEST_LOGIN, mp::MP_REQUEST_LOGIN_ACCOUNT, "783556037", "Aa316216");
|
||||
auto packet = request->operator()();
|
||||
bufferevent_write(bev, packet.c_str(), packet.size());
|
||||
|
||||
|
||||
@@ -5,19 +5,23 @@ aux_source_directory(pool/mem DIR_MEM_POOL)
|
||||
aux_source_directory(pool/object DIR_OBJECT_POOL)
|
||||
aux_source_directory(mmm DIR_MMM)
|
||||
aux_source_directory(tools DIR_TOOLS)
|
||||
aux_source_directory(smtp DIR_EMAIL)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/libevent)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/mp)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/ini)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/cpp_email)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/rapidjson)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/mysql++)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/mysql++/mysql)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include/smtp)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/MDB/imm_mysqldb)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/MS/works)
|
||||
message("CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/include/libevent")
|
||||
|
||||
link_directories(${CMAKE_SOURCE_DIR}/lib/libevent)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/lib/tbb)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/lib/smtp)
|
||||
|
||||
add_subdirectory(works)
|
||||
|
||||
@@ -30,6 +34,7 @@ add_executable(MS
|
||||
${DIR_MEM_POOL}
|
||||
${DIR_OBJECT_POOL}
|
||||
${DIR_TOOLS}
|
||||
${DIR_EMAIL}
|
||||
)
|
||||
|
||||
target_link_libraries(MS
|
||||
@@ -38,4 +43,5 @@ target_link_libraries(MS
|
||||
tbb
|
||||
imm_mysqldb
|
||||
MP
|
||||
curl
|
||||
)
|
||||
@@ -6,7 +6,8 @@
|
||||
#include "handler.h"
|
||||
#include "Response.h"
|
||||
|
||||
std::map<uint64_t, userinfo*> handler::user_fd;
|
||||
// handler 保有 session
|
||||
session* handler::g_session = new session();
|
||||
|
||||
/// resp im
|
||||
void handler::resp(const std::shared_ptr<agreement_request>& request,
|
||||
@@ -30,55 +31,20 @@ void handler::resp(const std::shared_ptr<agreement_request>& request,
|
||||
}
|
||||
}
|
||||
/// end resp im
|
||||
|
||||
void
|
||||
handler::send(const std::shared_ptr<agreement_request> &request, const std::shared_ptr<agreement_response> &response) {
|
||||
// 聊天消息包
|
||||
userinfo *user = user_fd.find(request->m_body.target())->second;
|
||||
|
||||
}
|
||||
|
||||
/// curr mem user curd
|
||||
void handler::add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request) {
|
||||
if (sri->sri_code() == mp::MP_LOGIN_SUCCESS) {
|
||||
auto ele = new userinfo();
|
||||
ele->bev = request->m_bev;
|
||||
sprintf(ele->ip, "%s", inet_ntoa(request->m_addr->sin_addr));
|
||||
|
||||
user_fd.insert({strtol(request->m_body.account().c_str(), nullptr, 0), ele});
|
||||
}
|
||||
}
|
||||
|
||||
void handler::remove_user(bufferevent *bev) {
|
||||
uint64_t target_ele;
|
||||
for (const auto &item: user_fd) {
|
||||
if (bev == item.second->bev) {
|
||||
target_ele = item.first;
|
||||
break;
|
||||
}
|
||||
// 聊天消息包
|
||||
void handler::send(const std::shared_ptr<agreement_request> &request, const std::shared_ptr<agreement_response> &response) {
|
||||
// 查询在线的用户信息
|
||||
auto ret = g_session->find_user_fd(request->m_body.target());
|
||||
// 用户信息结构体
|
||||
userinfo *user;
|
||||
if (ret.has_value()) {
|
||||
user = ret->second;
|
||||
}
|
||||
|
||||
user_fd.erase(target_ele);
|
||||
|
||||
}
|
||||
|
||||
void handler::remove_user(const std::shared_ptr<agreement_request>& request) {
|
||||
bufferevent_free(request->m_bev);
|
||||
user_fd.erase(strtol(request->m_body.account().c_str(), nullptr, 0));
|
||||
}
|
||||
|
||||
bool handler::is_user(const std::string& account) {
|
||||
if( user_fd.find(strtol(account.c_str(), nullptr, 0)) == user_fd.cend() ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<uint64_t, userinfo*>::iterator handler::find_user_fd(uint64_t account) {
|
||||
return user_fd.find(account);
|
||||
}
|
||||
/// end curr mem user curd
|
||||
|
||||
|
||||
void
|
||||
handler::ccp2p(const std::shared_ptr<agreement_request> &request, const std::shared_ptr<agreement_response> &response) {
|
||||
|
||||
@@ -88,3 +54,13 @@ handler::ccp2p(const std::shared_ptr<agreement_request> &request, const std::sha
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,33 +5,23 @@
|
||||
#ifndef IM2_HANDLER_H
|
||||
#define IM2_HANDLER_H
|
||||
|
||||
#include <optional>
|
||||
#include "agreement.h"
|
||||
|
||||
struct userinfo {
|
||||
bufferevent* bev;
|
||||
char ip[15];
|
||||
};
|
||||
#include "session.h"
|
||||
|
||||
|
||||
class handler {
|
||||
public:
|
||||
virtual void run(std::shared_ptr<agreement_request> request, std::shared_ptr<agreement_response> response) = 0;
|
||||
|
||||
// 通话操作
|
||||
public:
|
||||
// 用户不在线时应 删除 user fd 映射
|
||||
static void add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request);
|
||||
static void remove_user(const std::shared_ptr<agreement_request>& request);
|
||||
static void remove_user(bufferevent* bev);
|
||||
static bool is_user(const std::string& account);
|
||||
static std::map<uint64_t, userinfo*>::iterator find_user_fd(uint64_t account);
|
||||
|
||||
static void resp(const std::shared_ptr<agreement_request>& request, const std::shared_ptr<agreement_response>& response);
|
||||
static void send(const std::shared_ptr<agreement_request>& request, const std::shared_ptr<agreement_response>& response);
|
||||
|
||||
static void ccp2p(const std::shared_ptr<agreement_request>& request, const std::shared_ptr<agreement_response>& response);
|
||||
|
||||
protected:
|
||||
static std::map<uint64_t, userinfo*> user_fd;
|
||||
static session* g_session;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ mapping::mapping() {
|
||||
map.insert( std::pair<mp::MP_TYPE, handler*>(mp::MP_REQUEST_LOGOUT, userProve));
|
||||
|
||||
// 验证码
|
||||
auto peVerifCode = new PEVerifCode();
|
||||
auto peVerifCode = new PEVerifCodeController();
|
||||
map.insert( std::pair<mp::MP_TYPE, handler*>(mp::MP_REQUEST_PE_CODE, peVerifCode));
|
||||
|
||||
// 用户添加好友群组类操作
|
||||
|
||||
126
MS/mmm/session.cpp
Normal file
126
MS/mmm/session.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// Created by dongl on 23-5-10.
|
||||
//
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <thread>
|
||||
#include "session.h"
|
||||
|
||||
//std::map<uint64_t, userinfo*> session::user_fd;
|
||||
//std::map<bufferevent*, std::map<std::string, std::string>> session::session_map;
|
||||
|
||||
/// curr mem user curd user session
|
||||
void session::add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request) {
|
||||
if (sri->sri_code() == mp::MP_LOGIN_SUCCESS) {
|
||||
auto ele = new userinfo();
|
||||
ele->bev = request->m_bev;
|
||||
sprintf(ele->ip, "%s", inet_ntoa(request->m_addr->sin_addr));
|
||||
|
||||
user_fd.insert({strtol(request->m_body.account().c_str(), nullptr, 0), ele});
|
||||
}
|
||||
}
|
||||
|
||||
void session::remove_user(bufferevent *bev) {
|
||||
uint64_t target_ele;
|
||||
for (const auto &item: user_fd) {
|
||||
if (bev == item.second->bev) {
|
||||
target_ele = item.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
user_fd.erase(target_ele);
|
||||
}
|
||||
|
||||
void session::remove_user(const std::shared_ptr<agreement_request>& request) {
|
||||
bufferevent_free(request->m_bev);
|
||||
user_fd.erase(strtol(request->m_body.account().c_str(), nullptr, 0));
|
||||
}
|
||||
|
||||
bool session::is_user(const std::string& account) {
|
||||
if( user_fd.find(strtol(account.c_str(), nullptr, 0)) == user_fd.cend() ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<std::pair<uint64_t, userinfo*>> session::find_user_fd(uint64_t account) {
|
||||
auto ret = user_fd.find(account);
|
||||
if (ret != user_fd.cend()) {
|
||||
// return std::make_optional<std::pair<uint64_t, userinfo*>>(ret->first, ret->second);
|
||||
return {{ret->first, ret->second} };
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
/// user bev fd lik session
|
||||
// 给用户 添加会话信息
|
||||
void session::set_session(bufferevent* bev, const std::string &session_key, const std::string &session_value) {
|
||||
auto ret = session_map.find(bev);
|
||||
// 先看有没有 bev session 没有初始化并且添加一个 有取出来sub session 在添加
|
||||
if (ret != session_map.cend()) {
|
||||
std::map<std::string, std::string> sub_session;
|
||||
sub_session.insert({session_key, session_value});
|
||||
session_map.insert({bev, sub_session});
|
||||
} else {
|
||||
ret->second.insert({session_key, session_value});
|
||||
}
|
||||
|
||||
/// map 内部自动排序 添加 时间 要删除信息的链表
|
||||
// 添加时间轮 定时器
|
||||
time_t t = time(nullptr);
|
||||
auto retwheel = session_time_wheel.find(t);
|
||||
if (retwheel != session_time_wheel.cend()) {
|
||||
auto list = session_time_wheel.find(t)->second;
|
||||
list.emplace_back(bev, session_key);
|
||||
session_time_wheel.insert({t, list});
|
||||
} else {
|
||||
std::list<std::pair<bufferevent*/*bev*/, std::string/*key*/>> list;
|
||||
list.emplace_back(bev, session_key);
|
||||
session_time_wheel.insert({t, list});
|
||||
}
|
||||
}
|
||||
|
||||
// 给用户 查询会话信息
|
||||
std::optional<std::string> session::get_session(bufferevent* bev, const std::string &session_key) {
|
||||
auto sess = session_map.find(bev);
|
||||
std::map<std::string, std::string> sub_sess;
|
||||
if (sess != session_map.cend()) {
|
||||
auto ret = sess->second.find("session_key");
|
||||
if (ret != sub_sess.cend()) {
|
||||
return ret->second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void session::remove_session(bufferevent *bev, const std::string &session_key) {
|
||||
auto ret = session_map.find(bev);
|
||||
std::map<std::string, std::string> sub_sess;
|
||||
if (ret != session_map.cend()) {
|
||||
auto sub = ret->second.find(session_key);
|
||||
if (sub != sub_sess.cend()) {
|
||||
ret->second.erase(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 时间轮思路的 定时器
|
||||
void session::timing() {
|
||||
time_wheel.run([&]() {
|
||||
while (true) {
|
||||
if (!session_time_wheel.empty()) {
|
||||
auto wheel = session_time_wheel.begin();
|
||||
if (wheel->first > time(nullptr) + 300000) { // 5分钟
|
||||
// 超时5分钟就删除
|
||||
for (const auto &item: wheel->second) {
|
||||
remove_session(item.first, item.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
});
|
||||
}
|
||||
46
MS/mmm/session.h
Normal file
46
MS/mmm/session.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by dongl on 23-5-10.
|
||||
//
|
||||
|
||||
#ifndef IM2_SESSION_H
|
||||
#define IM2_SESSION_H
|
||||
|
||||
#include "event2/bufferevent.h"
|
||||
#include "agreement.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <oneapi/tbb/task_group.h>
|
||||
#include <list>
|
||||
|
||||
struct userinfo {
|
||||
bufferevent* bev;
|
||||
char ip[15];
|
||||
std::map<std::string, std::string> session; // 用户的 seesion;
|
||||
};
|
||||
|
||||
|
||||
class session {
|
||||
public:
|
||||
// 用户不在线时应 删除 user fd 映射
|
||||
void add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request);
|
||||
void remove_user(const std::shared_ptr<agreement_request>& request);
|
||||
void remove_user(bufferevent* bev);
|
||||
bool is_user(const std::string& account);
|
||||
std::optional<std::pair<uint64_t, userinfo*>> find_user_fd(uint64_t account);
|
||||
|
||||
void set_session(bufferevent* bev, const std::string& session_key, const std::string& session_value);
|
||||
std::optional<std::string> get_session(bufferevent* bev, const std::string& session_key);
|
||||
void remove_session(bufferevent* bev, const std::string& session_key);
|
||||
|
||||
void timing();
|
||||
|
||||
protected:
|
||||
tbb::task_group time_wheel; // 时间轮 线程池
|
||||
std::map<uint64_t, userinfo*> user_fd; // 用户的链接 暂时是一直链接 交给libevent 管理
|
||||
std::map<bufferevent*, std::map<std::string, std::string>> session_map; // 当前链接的 存在的 seesion;
|
||||
std::map<time_t, std::list< std::pair<bufferevent*/*bev*/, std::string/*key*/> > > session_time_wheel; // session 有效期 超时轮 映射
|
||||
};
|
||||
|
||||
|
||||
#endif //IM2_SESSION_H
|
||||
192
MS/smtp/smtp.cpp
Normal file
192
MS/smtp/smtp.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
#include "smtp.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace Jxiepc {
|
||||
|
||||
Smtp::Smtp(int port, std::string domain, std::string user, std::string pwd,
|
||||
std::string t_mail, std::string title, std::string content, std::string type)
|
||||
: m_port(port), m_domain(domain), m_user(user), m_password(pwd), m_tmail(t_mail),
|
||||
m_title(title), m_content(content), m_type(type) {
|
||||
|
||||
ret = init();
|
||||
if(ret < 0) {
|
||||
perror("init error");
|
||||
}
|
||||
}
|
||||
|
||||
Smtp::~Smtp() {
|
||||
close(m_sockfd);
|
||||
}
|
||||
|
||||
int Smtp::init() {
|
||||
if(make_connect() == -1) {
|
||||
return -1;
|
||||
}
|
||||
std::string str;
|
||||
|
||||
Recv();
|
||||
if(strstr(m_buf, "220") == nullptr) { return -1; }
|
||||
std::cout << "****: " << m_buf << std::endl;
|
||||
|
||||
Send("HELO " + m_user + "\r\n");
|
||||
Recv();
|
||||
if(strstr(m_buf, "250") == nullptr) { return -1; }
|
||||
|
||||
|
||||
Send("AUTH LOGIN\r\n");
|
||||
Recv();
|
||||
if(strstr(m_buf, "334") == nullptr) { return -1; }
|
||||
|
||||
str = m_user.substr(0, m_user.find('@', 0));
|
||||
str = enBase64(str.c_str());
|
||||
str += "\r\n";
|
||||
Send(str);
|
||||
Recv();
|
||||
if(strstr(m_buf, "334") == nullptr) { return -1; }
|
||||
|
||||
Send(enBase64(m_password.c_str()) + "\r\n");
|
||||
Recv();
|
||||
if(strstr(m_buf, "235") == nullptr) { return -1; }
|
||||
std::cout << "AUTH SUCCESS..." << std::endl;
|
||||
|
||||
Send("MAIL FROM: <" + m_user + ">\r\n");
|
||||
Recv();
|
||||
if(strstr(m_buf, "250") == nullptr) { return -1; }
|
||||
|
||||
Send("RCPT TO: <" + m_tmail+ ">\r\n");
|
||||
Recv();
|
||||
if(strstr(m_buf, "250") == nullptr) { return -1; }
|
||||
|
||||
Send("DATA\r\n");
|
||||
Recv();
|
||||
|
||||
str = "From: " + m_user + "\r\n";
|
||||
str += "To: " + m_tmail + "\r\n";
|
||||
str += "Subject: " + m_title + "\r\n";
|
||||
str += "Content-Type: multipart/mixed;boundary=qwertyuiop\r\n";
|
||||
str += "\r\n--qwertyuiop\r\n";
|
||||
|
||||
if(m_type == "html"){
|
||||
str += "content-type:text/html;charset=utf-8\r\n"; //html类型
|
||||
}else{
|
||||
str += "Content-Type: text/plain;charset=utf-8\r\n"; //文本类型
|
||||
}
|
||||
|
||||
Send(str);
|
||||
str = "\r\n" + m_content + "\r\n";
|
||||
str += "\r\n--qwertyuiop--\r\n.\r\n";
|
||||
Send(str);
|
||||
Recv();
|
||||
if(strstr(m_buf, "250") == nullptr) { return -1; }
|
||||
std::cout << "send success..." << std::endl;
|
||||
|
||||
|
||||
Send("QUIT\r\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Smtp::make_connect() {
|
||||
m_sockfd = Socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
hostent *host_info = gethostbyname(m_domain.c_str());
|
||||
if(host_info == nullptr){
|
||||
perror("gethostbyname error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(host_info->h_addrtype != AF_INET) {
|
||||
perror("AF_INET error");
|
||||
return -1;
|
||||
}
|
||||
char buf[128];
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = *((unsigned long*)host_info->h_addr_list[0]);
|
||||
addr.sin_port = htons(m_port);
|
||||
|
||||
Connect(m_sockfd, (struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Smtp::Connect(int fd, const struct sockaddr *sa, socklen_t salen) {
|
||||
if(connect(fd, sa, salen) == -1) {
|
||||
perror("connect error");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int Smtp::Socket(int family, int type, int protocol) {
|
||||
int sockfd;
|
||||
if((sockfd = socket(family, type, protocol)) == -1) {
|
||||
perror("socket error");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
ssize_t Smtp::Send(const std::string& str) {
|
||||
ssize_t n;
|
||||
std::cout << str;
|
||||
if((n = send(m_sockfd, str.c_str(), str.length(), 0)) == -1) {
|
||||
perror("write error");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t Smtp::Recv() {
|
||||
ssize_t n;
|
||||
m_buf[0] = '\0';
|
||||
if((n == recv(m_sockfd, m_buf, 0xFFF, 0)) == -1) {
|
||||
perror("recv error");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
std::string Smtp::enBase64(const std::string& str)
|
||||
{
|
||||
std::string base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int str_len = str.length();
|
||||
std::string res="";
|
||||
for (int strp=0; strp<str_len/3*3; strp+=3)
|
||||
{
|
||||
res+=base64_table[str[strp]>>2];
|
||||
res+=base64_table[(str[strp]&0x3)<<4 | (str[strp+1])>>4];
|
||||
res+=base64_table[(str[strp+1]&0xf)<<2 | (str[strp+2])>>6];
|
||||
res+=base64_table[(str[strp+2])&0x3f];
|
||||
}
|
||||
if (str_len%3==1)
|
||||
{
|
||||
int pos=str_len/3 * 3;
|
||||
res += base64_table[str[pos]>>2];
|
||||
res += base64_table[(str[pos]&0x3)<<4];
|
||||
res += "=";
|
||||
res += "=";
|
||||
}
|
||||
else if (str_len%3==2)
|
||||
{
|
||||
int pos=str_len/3 * 3;
|
||||
res += base64_table[str[pos]>>2];
|
||||
res += base64_table[(str[pos]&0x3)<<4 | (str[pos+1])>>4];
|
||||
res += base64_table[(str[pos+1]&0xf)<<2];
|
||||
res += "=";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Smtp::getRet() const {
|
||||
if(ret < 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Created by dongl on 23-5-8.
|
||||
//
|
||||
|
||||
#include "PEVerifCode.h"
|
||||
#include <experimental/random>
|
||||
|
||||
void PEVerifCode::run(std::shared_ptr<agreement_request> request, std::shared_ptr<agreement_response> response) {
|
||||
std::string code;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
code.push_back((char )std::experimental::randint(33, 126));
|
||||
}
|
||||
|
||||
code;
|
||||
auto sri = new mp::sri();
|
||||
|
||||
|
||||
sri->set_sri_code(mp::MP_PE_CODE_SUCCESS);
|
||||
sri->set_sri_msg("验证码已发送");
|
||||
|
||||
response->set(sri, request->m_bev);
|
||||
delete sri;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// Created by dongl on 23-5-8.
|
||||
//
|
||||
|
||||
#ifndef IM2_PEVERIFCODE_H
|
||||
#define IM2_PEVERIFCODE_H
|
||||
|
||||
|
||||
#include "../../mmm/handler.h"
|
||||
|
||||
class PEVerifCode : public handler{
|
||||
public:
|
||||
void run(std::shared_ptr<agreement_request> request, std::shared_ptr<agreement_response> response) override;
|
||||
};
|
||||
|
||||
|
||||
#endif //IM2_PEVERIFCODE_H
|
||||
33
MS/works/controller/PEVerifCodeController.cpp
Normal file
33
MS/works/controller/PEVerifCodeController.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by dongl on 23-5-8.
|
||||
//
|
||||
|
||||
#include "PEVerifCodeController.h"
|
||||
|
||||
void PEVerifCodeController::run(std::shared_ptr<agreement_request> request, std::shared_ptr<agreement_response> response) {
|
||||
auto sri = new mp::sri();
|
||||
// 请求验证码
|
||||
if (request->m_mph->mp_type() == mp::MP_REQUEST_PE_CODE) {
|
||||
// 生成验证码
|
||||
std::string code = peVerifCodeService.gen_code();
|
||||
// 发送验证码至邮
|
||||
bool state = peVerifCodeService.send_email(request->m_body.account(), code);
|
||||
// 设置session 字段
|
||||
g_session->set_session(request->m_bev, "code", code);
|
||||
|
||||
if (state) {
|
||||
sri->set_sri_code(mp::MP_PE_CODE_SUCCESS);
|
||||
sri->set_sri_msg("验证码已发送");
|
||||
} else {
|
||||
sri->set_sri_code(mp::MP_PE_CODE_FAIL);
|
||||
sri->set_sri_msg("未知问题,验证码获取失败");
|
||||
}
|
||||
}
|
||||
|
||||
else if (request->m_mph->mp_type() == mp::MP_RESPONSE_PE_CODE) {
|
||||
|
||||
}
|
||||
|
||||
response->set(sri, request->m_bev);
|
||||
delete sri;
|
||||
}
|
||||
23
MS/works/controller/PEVerifCodeController.h
Normal file
23
MS/works/controller/PEVerifCodeController.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by dongl on 23-5-8.
|
||||
//
|
||||
|
||||
#ifndef IM2_PEVERIFCODESERVICE_H
|
||||
#define IM2_PEVERIFCODE_H
|
||||
|
||||
|
||||
#include "../../mmm/handler.h"
|
||||
#include "service/PEVerifCodeService.h"
|
||||
|
||||
class PEVerifCodeController : public handler {
|
||||
public:
|
||||
void run(std::shared_ptr<agreement_request> request, std::shared_ptr<agreement_response> response) override;
|
||||
|
||||
private:
|
||||
PEVerifCodeService peVerifCodeService = PEVerifCodeService();
|
||||
static std::map<bufferevent*, std::string> session; // 客户端 fd 与 code 绑定的 session
|
||||
static std::map<uint64_t, bufferevent*> time_wheel; // 时间轮定时容器 看验证码超时的
|
||||
};
|
||||
|
||||
|
||||
#endif //IM2_PEVERIFCODESERVICE_H
|
||||
@@ -7,6 +7,6 @@
|
||||
|
||||
#include "UserProveController.h"
|
||||
#include "IMProveController.h"
|
||||
#include "PEVerifCode.h"
|
||||
#include "PEVerifCodeController.h"
|
||||
|
||||
#endif //IM2_WORKS_H
|
||||
|
||||
23
MS/works/service/PEVerifCodeService.cpp
Normal file
23
MS/works/service/PEVerifCodeService.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by dongl on 23-5-10.
|
||||
//
|
||||
|
||||
#include <experimental/random>
|
||||
#include "PEVerifCodeService.h"
|
||||
#include "send_email.h"
|
||||
|
||||
std::string PEVerifCodeService::gen_code() {
|
||||
|
||||
std::string code;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
code.push_back((char )std::experimental::randint(30, 39)); // 0-9
|
||||
}
|
||||
|
||||
emailcode = code;
|
||||
return code;
|
||||
}
|
||||
|
||||
bool PEVerifCodeService::send_email(const std::string &target_email, const std::string &code) {
|
||||
emailcode = code == "0" ? emailcode : code;
|
||||
return send_email_def(target_email, emailcode);
|
||||
}
|
||||
21
MS/works/service/PEVerifCodeService.h
Normal file
21
MS/works/service/PEVerifCodeService.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by dongl on 23-5-10.
|
||||
//
|
||||
|
||||
#ifndef IM2_PEVERIFCODESERVICE_H
|
||||
#define IM2_PEVERIFCODESERVICE_H
|
||||
|
||||
|
||||
#include "Service.h"
|
||||
|
||||
class PEVerifCodeService : public Service {
|
||||
public:
|
||||
std::string gen_code();
|
||||
bool send_email(const std::string& target_email, const std::string& code = "0");
|
||||
|
||||
private:
|
||||
std::string emailcode;
|
||||
};
|
||||
|
||||
|
||||
#endif //IM2_PEVERIFCODESERVICE_H
|
||||
@@ -24,7 +24,7 @@ mp::sri* UserService::login(mp::MP_SUB_TYPE subType, const std::string& account
|
||||
return sri;
|
||||
}
|
||||
|
||||
// 以account登陆
|
||||
// 登陆基函数
|
||||
void UserService::login_fun(const std::string& account, const std::string& password, const std::string& filed) {
|
||||
|
||||
// 判断密码
|
||||
|
||||
@@ -9,12 +9,19 @@ include_directories(${CMAKE_SOURCE_DIR}/include/rapidjson)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/MS)
|
||||
|
||||
link_directories(${CMAKE_SOURCE_DIR}/lib/gtest)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/lib/smtp)
|
||||
|
||||
add_executable(TEST main.cpp)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/MS/smtp DIR_EMAIL)
|
||||
|
||||
add_executable(TEST
|
||||
${DIR_EMAIL}
|
||||
main.cpp)
|
||||
|
||||
target_link_libraries(TEST
|
||||
works
|
||||
imm_mysqldb
|
||||
libgtest.a libgtest_main.a
|
||||
libgmock.a libgmock_main.a
|
||||
curl
|
||||
ssl
|
||||
)
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "works/db/po/PoJson.h"
|
||||
#include "works/db/linkDB.h"
|
||||
#include "works/db/UserFriendsDB.h"
|
||||
#include "works/db/UserDB.h"
|
||||
#include "smtp/send_email.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc,argv);
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ TEST(select_friends_all, select_friends_Test) {
|
||||
auto belong_grouping = member->value.GetObject().FindMember("belong_grouping");
|
||||
auto add_time = member->value.GetObject().FindMember("add_time");
|
||||
auto add_source = member->value.GetObject().FindMember("add_source");
|
||||
printf("%s - %s:%d, %s:%d, %s:%d ",member->name.GetString(),
|
||||
printf("%s - %s:%d, %s:%d, %s:%d ", member->name.GetString(),
|
||||
belong_grouping->name.GetString(), belong_grouping->value.GetInt(),
|
||||
add_time->name.GetString(), add_time->value.GetInt(),
|
||||
add_source->name.GetString(), add_source->value.GetInt());
|
||||
@@ -80,4 +80,21 @@ TEST(UserDB_select_user, UserDB_Ues_Test) {
|
||||
auto [state, po] = i.select_user(2725096176, "account");
|
||||
if (state)
|
||||
printf("%lu", po.account);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// "smtp.163.com",
|
||||
// "bxhuu1o1vvyviiij6w@163.com",
|
||||
// "IWXVJLUPMVFCFOBX",
|
||||
// "2725096176@qq.com",
|
||||
// "这是你的IM验证码",
|
||||
|
||||
//"<center>\n"
|
||||
// "<h2 style=\"background-color: #CCFFCC\"> 验证码: XP02EE </h2>\n"
|
||||
//"</center>"
|
||||
|
||||
|
||||
TEST(email_send, email_send__Test) {
|
||||
send_email_def("2725096176@qq.com", "AAKXT4");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
Body(mp::MP_SUB_TYPE subType, const std::string& account, const std::string& password) {
|
||||
body = new mp::body();
|
||||
|
||||
body->set_subcommand(subType);
|
||||
body->set_account(account);
|
||||
body->set_password(password);
|
||||
}
|
||||
|
||||
207
include/smtp/send_email.h
Normal file
207
include/smtp/send_email.h
Normal file
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// Created by dongl on 23-5-10.
|
||||
//
|
||||
|
||||
#ifndef IM2_SEND_EMAIL_H
|
||||
#define IM2_SEND_EMAIL_H
|
||||
|
||||
#include <string>
|
||||
#include "smtp.h"
|
||||
|
||||
#define DOMAIN "smtp.163.com" //smtp服务器域名
|
||||
#define PORT 25 //smtp服务器域名
|
||||
#define DEF_SEND_EMAIL "imbaseemail@163.com" //发件人的邮箱地址
|
||||
#define DEF_SEND_EMAIL_PASS "XIALXUWEOCDPIYAC" //发件人密码
|
||||
|
||||
#define CODE_HTML_TEMPLATE(code) get_code_template(code)
|
||||
|
||||
std::string get_code_template(const std::string& code);
|
||||
|
||||
bool send_email_def(const std::string& target_email, const std::string& code) {
|
||||
Jxiepc::Smtp smtp(
|
||||
PORT, //服务器端口(默认25)
|
||||
DOMAIN, //smtp服务器域名
|
||||
DEF_SEND_EMAIL, //发件人的邮箱地址
|
||||
DEF_SEND_EMAIL_PASS, //发件人密码
|
||||
target_email, //收件人
|
||||
code + " 是你的IM验证码", //主题
|
||||
CODE_HTML_TEMPLATE(code), //内容
|
||||
"html"
|
||||
);
|
||||
return smtp.getRet();
|
||||
}
|
||||
|
||||
bool send_email_def(const std::string& send_email, const std::string& password, const std::string& target_email, const std::string& code) {
|
||||
Jxiepc::Smtp smtp(
|
||||
PORT, //服务器端口(默认25)
|
||||
DOMAIN, //smtp服务器域名
|
||||
send_email, //发件人的邮箱地址
|
||||
password, //发件人密码
|
||||
target_email, //收件人
|
||||
code + " 是你的IM验证码", //主题
|
||||
CODE_HTML_TEMPLATE(code), //内容
|
||||
"html"
|
||||
);
|
||||
return smtp.getRet();
|
||||
}
|
||||
|
||||
|
||||
std::string get_code_template(const std::string& code) {
|
||||
|
||||
std::string emaialcode[code.size()];
|
||||
for (int i = 0; i < code.size(); ++i) {
|
||||
emaialcode[i] = code[i];
|
||||
}
|
||||
|
||||
return "<!DOCTYPE html>\n"
|
||||
"<html lang=\"en\" xmlns:th=\"http://www.thymeleaf.org\">\n"
|
||||
"<head>\n"
|
||||
" <meta charset=\"UTF-8\">\n"
|
||||
" <title>邮箱验证码</title>\n"
|
||||
" <style>\n"
|
||||
" table {\n"
|
||||
" width: 700px;\n"
|
||||
" margin: 0 auto;\n"
|
||||
" }\n"
|
||||
" #top {\n"
|
||||
" width: 700px;\n"
|
||||
" border-bottom: 1px solid #ccc;\n"
|
||||
" margin: 0 auto 30px;\n"
|
||||
" }\n"
|
||||
" #top table {\n"
|
||||
" font: 12px Tahoma, Arial, 宋体;\n"
|
||||
" height: 40px;\n"
|
||||
" }\n"
|
||||
" #content {\n"
|
||||
" width: 680px;\n"
|
||||
" padding: 0 10px;\n"
|
||||
" margin: 0 auto;\n"
|
||||
" }\n"
|
||||
" #content_top {\n"
|
||||
" line-height: 1.5;\n"
|
||||
" font-size: 14px;\n"
|
||||
" margin-bottom: 25px;\n"
|
||||
" color: #4d4d4d;\n"
|
||||
" }\n"
|
||||
" #content_top strong {\n"
|
||||
" display: block;\n"
|
||||
" margin-bottom: 15px;\n"
|
||||
" }\n"
|
||||
" #content_top strong span {\n"
|
||||
" color: #f60;\n"
|
||||
" font-size: 16px;\n"
|
||||
" }\n"
|
||||
" #verificationCode {\n"
|
||||
" color: #f60;\n"
|
||||
" font-size: 24px;\n"
|
||||
" }\n"
|
||||
" #content_bottom {\n"
|
||||
" margin-bottom: 30px;\n"
|
||||
" }\n"
|
||||
" #content_bottom small {\n"
|
||||
" display: block;\n"
|
||||
" margin-bottom: 20px;\n"
|
||||
" font-size: 12px;\n"
|
||||
" color: #747474;\n"
|
||||
" }\n"
|
||||
" #bottom {\n"
|
||||
" width: 700px;\n"
|
||||
" margin: 0 auto;\n"
|
||||
" }\n"
|
||||
" #bottom div {\n"
|
||||
" padding: 10px 10px 0;\n"
|
||||
" border-top: 1px solid #ccc;\n"
|
||||
" color: #747474;\n"
|
||||
" margin-bottom: 20px;\n"
|
||||
" line-height: 1.3em;\n"
|
||||
" font-size: 12px;\n"
|
||||
" }\n"
|
||||
" #content_top strong span {\n"
|
||||
" font-size: 18px;\n"
|
||||
" color: #FE4F70;\n"
|
||||
" }\n"
|
||||
" #sign {\n"
|
||||
" text-align: right;\n"
|
||||
" font-size: 18px;\n"
|
||||
" color: #FE4F70;\n"
|
||||
" font-weight: bold;\n"
|
||||
" }\n"
|
||||
" #verificationCode {\n"
|
||||
" height: 100px;\n"
|
||||
" width: 680px;\n"
|
||||
" text-align: center;\n"
|
||||
" margin: 30px 0;\n"
|
||||
" }\n"
|
||||
" #verificationCode div {\n"
|
||||
" height: 100px;\n"
|
||||
" width: 680px;\n"
|
||||
" }\n"
|
||||
" .button {\n"
|
||||
" color: #FE4F70;\n"
|
||||
" margin-left: 10px;\n"
|
||||
" height: 80px;\n"
|
||||
" width: 80px;\n"
|
||||
" resize: none;\n"
|
||||
" font-size: 42px;\n"
|
||||
" border: none;\n"
|
||||
" outline: none;\n"
|
||||
" padding: 10px 15px;\n"
|
||||
" background: #ededed;\n"
|
||||
" text-align: center;\n"
|
||||
" border-radius: 17px;\n"
|
||||
" box-shadow: 6px 6px 12px #cccccc,\n"
|
||||
" -6px -6px 12px #ffffff;\n"
|
||||
" }\n"
|
||||
" .button:hover {\n"
|
||||
" box-shadow: inset 6px 6px 4px #d1d1d1,\n"
|
||||
" inset -6px -6px 4px #ffffff;\n"
|
||||
" }\n"
|
||||
" </style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<table>\n"
|
||||
" <tbody>\n"
|
||||
" <tr>\n"
|
||||
" <td>\n"
|
||||
" <div id=\"top\">\n"
|
||||
" <table>\n"
|
||||
" <tbody><tr><td></td></tr></tbody>\n"
|
||||
" </table>\n"
|
||||
" </div>\n"
|
||||
" <div id=\"content\">\n"
|
||||
" <div id=\"content_top\">\n"
|
||||
" <strong>尊敬的用户:您好!</strong>\n"
|
||||
" <strong>\n"
|
||||
" 您正在进行<span>注册账号</span>操作,请在验证码中输入以下验证码完成操作:\n"
|
||||
" </strong>\n"
|
||||
" <div id=\"verificationCode\">\n"
|
||||
" <button class=\"button\">"+emaialcode[0]+"</button>\n"
|
||||
" <button class=\"button\">"+emaialcode[1]+"</button>\n"
|
||||
" <button class=\"button\">"+emaialcode[2]+"</button>\n"
|
||||
" <button class=\"button\">"+emaialcode[3]+"</button>\n"
|
||||
" <button class=\"button\">"+emaialcode[4]+"</button>\n"
|
||||
" <button class=\"button\">"+emaialcode[5]+"</button>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" <div id=\"content_bottom\">\n"
|
||||
" <small>\n"
|
||||
" 注意:此操作可能会修改您的密码、登录邮箱或绑定手机。如非本人操作,请及时登录并修改密码以保证帐户安全\n"
|
||||
" <br>(工作人员不会向你索取此验证码,请勿泄漏!)\n"
|
||||
" </small>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" <div id=\"bottom\">\n"
|
||||
" <div>\n"
|
||||
" <p>此为系统邮件,请勿回复<br>\n"
|
||||
" 请保管好您的邮箱,避免账号被他人盗用\n"
|
||||
" </p>\n"
|
||||
" <p id=\"sign\">——IM Base Email</p>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" </td>\n"
|
||||
" </tr>\n"
|
||||
" </tbody>\n"
|
||||
"</table>\n"
|
||||
"</body>\n";
|
||||
}
|
||||
#endif //IM2_SEND_EMAIL_H
|
||||
60
include/smtp/smtp.h
Normal file
60
include/smtp/smtp.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef __JXIEPC_SMTP_H__
|
||||
#define __JXIEPC_SMTP_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
#include <utility>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Jxiepc {
|
||||
|
||||
class Smtp {
|
||||
|
||||
public:
|
||||
Smtp(int port, std::string domain, std::string user, std::string pwd,
|
||||
std::string t_mail, std::string title, std::string content, std::string type);
|
||||
~Smtp();
|
||||
|
||||
int init();
|
||||
int make_connect();
|
||||
|
||||
bool getRet() const;
|
||||
|
||||
private:
|
||||
void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
|
||||
int Socket(int family, int type, int protocol);
|
||||
ssize_t Send(const std::string& str);
|
||||
ssize_t Recv();
|
||||
|
||||
static std::string enBase64(const std::string& src);
|
||||
private:
|
||||
int m_port;
|
||||
int m_sockfd;
|
||||
std::string m_domain;
|
||||
std::string m_user;
|
||||
std::string m_password;
|
||||
std::string m_tmail;
|
||||
std::string m_title;
|
||||
std::string m_content;
|
||||
std::string m_type;
|
||||
char m_buf[0xFFF];
|
||||
|
||||
int ret;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BIN
lib/smtp/libcurl.so
Executable file
BIN
lib/smtp/libcurl.so
Executable file
Binary file not shown.
Reference in New Issue
Block a user