diff --git a/MC/api/main.cpp b/MC/api/main.cpp index 5bdea8b..e82676e 100644 --- a/MC/api/main.cpp +++ b/MC/api/main.cpp @@ -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()); diff --git a/MS/CMakeLists.txt b/MS/CMakeLists.txt index 288263d..ff38c98 100644 --- a/MS/CMakeLists.txt +++ b/MS/CMakeLists.txt @@ -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 ) \ No newline at end of file diff --git a/MS/mmm/handler.cpp b/MS/mmm/handler.cpp index 39408dd..ef0cf57 100644 --- a/MS/mmm/handler.cpp +++ b/MS/mmm/handler.cpp @@ -6,7 +6,8 @@ #include "handler.h" #include "Response.h" -std::map handler::user_fd; +// handler 保有 session +session* handler::g_session = new session(); /// resp im void handler::resp(const std::shared_ptr& request, @@ -30,55 +31,20 @@ void handler::resp(const std::shared_ptr& request, } } /// end resp im - -void -handler::send(const std::shared_ptr &request, const std::shared_ptr &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& 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 &request, const std::shared_ptr &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& 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::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 &request, const std::shared_ptr &response) { @@ -88,3 +54,13 @@ handler::ccp2p(const std::shared_ptr &request, const std::sha + + + + + + + + + + diff --git a/MS/mmm/handler.h b/MS/mmm/handler.h index d6eaa3b..8db9ff9 100644 --- a/MS/mmm/handler.h +++ b/MS/mmm/handler.h @@ -5,33 +5,23 @@ #ifndef IM2_HANDLER_H #define IM2_HANDLER_H +#include #include "agreement.h" - -struct userinfo { - bufferevent* bev; - char ip[15]; -}; +#include "session.h" class handler { public: virtual void run(std::shared_ptr request, std::shared_ptr response) = 0; + // 通话操作 public: - // 用户不在线时应 删除 user fd 映射 - static void add_user(mp::sri* sri, std::shared_ptr& request); - static void remove_user(const std::shared_ptr& request); - static void remove_user(bufferevent* bev); - static bool is_user(const std::string& account); - static std::map::iterator find_user_fd(uint64_t account); - static void resp(const std::shared_ptr& request, const std::shared_ptr& response); static void send(const std::shared_ptr& request, const std::shared_ptr& response); - static void ccp2p(const std::shared_ptr& request, const std::shared_ptr& response); protected: - static std::map user_fd; + static session* g_session; }; diff --git a/MS/mmm/mapping.cpp b/MS/mmm/mapping.cpp index e992556..338466c 100644 --- a/MS/mmm/mapping.cpp +++ b/MS/mmm/mapping.cpp @@ -22,7 +22,7 @@ mapping::mapping() { map.insert( std::pair(mp::MP_REQUEST_LOGOUT, userProve)); // 验证码 - auto peVerifCode = new PEVerifCode(); + auto peVerifCode = new PEVerifCodeController(); map.insert( std::pair(mp::MP_REQUEST_PE_CODE, peVerifCode)); // 用户添加好友群组类操作 diff --git a/MS/mmm/session.cpp b/MS/mmm/session.cpp new file mode 100644 index 0000000..71d5d40 --- /dev/null +++ b/MS/mmm/session.cpp @@ -0,0 +1,126 @@ +// +// Created by dongl on 23-5-10. +// + +#include +#include +#include "session.h" + +//std::map session::user_fd; +//std::map> session::session_map; + +/// curr mem user curd user session +void session::add_user(mp::sri* sri, std::shared_ptr& 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& 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> session::find_user_fd(uint64_t account) { + auto ret = user_fd.find(account); + if (ret != user_fd.cend()) { +// return std::make_optional>(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 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> list; + list.emplace_back(bev, session_key); + session_time_wheel.insert({t, list}); + } +} + +// 给用户 查询会话信息 +std::optional session::get_session(bufferevent* bev, const std::string &session_key) { + auto sess = session_map.find(bev); + std::map 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 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)); + } + }); +} diff --git a/MS/mmm/session.h b/MS/mmm/session.h new file mode 100644 index 0000000..2abb71f --- /dev/null +++ b/MS/mmm/session.h @@ -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 +#include +#include +#include +#include + +struct userinfo { + bufferevent* bev; + char ip[15]; + std::map session; // 用户的 seesion; +}; + + +class session { +public: + // 用户不在线时应 删除 user fd 映射 + void add_user(mp::sri* sri, std::shared_ptr& request); + void remove_user(const std::shared_ptr& request); + void remove_user(bufferevent* bev); + bool is_user(const std::string& account); + std::optional> find_user_fd(uint64_t account); + + void set_session(bufferevent* bev, const std::string& session_key, const std::string& session_value); + std::optional 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 user_fd; // 用户的链接 暂时是一直链接 交给libevent 管理 + std::map> session_map; // 当前链接的 存在的 seesion; + std::map > > session_time_wheel; // session 有效期 超时轮 映射 +}; + + +#endif //IM2_SESSION_H diff --git a/MS/smtp/smtp.cpp b/MS/smtp/smtp.cpp new file mode 100644 index 0000000..f4ed0cd --- /dev/null +++ b/MS/smtp/smtp.cpp @@ -0,0 +1,192 @@ +#include "smtp.h" +#include + +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>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; + } + } + +} diff --git a/MS/works/controller/PEVerifCode.cpp b/MS/works/controller/PEVerifCode.cpp deleted file mode 100644 index 9eafa54..0000000 --- a/MS/works/controller/PEVerifCode.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Created by dongl on 23-5-8. -// - -#include "PEVerifCode.h" -#include - -void PEVerifCode::run(std::shared_ptr request, std::shared_ptr 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; -} diff --git a/MS/works/controller/PEVerifCode.h b/MS/works/controller/PEVerifCode.h deleted file mode 100644 index 3e60db7..0000000 --- a/MS/works/controller/PEVerifCode.h +++ /dev/null @@ -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 request, std::shared_ptr response) override; -}; - - -#endif //IM2_PEVERIFCODE_H diff --git a/MS/works/controller/PEVerifCodeController.cpp b/MS/works/controller/PEVerifCodeController.cpp new file mode 100644 index 0000000..ef3dcef --- /dev/null +++ b/MS/works/controller/PEVerifCodeController.cpp @@ -0,0 +1,33 @@ +// +// Created by dongl on 23-5-8. +// + +#include "PEVerifCodeController.h" + +void PEVerifCodeController::run(std::shared_ptr request, std::shared_ptr 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; +} diff --git a/MS/works/controller/PEVerifCodeController.h b/MS/works/controller/PEVerifCodeController.h new file mode 100644 index 0000000..0fad11e --- /dev/null +++ b/MS/works/controller/PEVerifCodeController.h @@ -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 request, std::shared_ptr response) override; + +private: + PEVerifCodeService peVerifCodeService = PEVerifCodeService(); + static std::map session; // 客户端 fd 与 code 绑定的 session + static std::map time_wheel; // 时间轮定时容器 看验证码超时的 +}; + + +#endif //IM2_PEVERIFCODESERVICE_H diff --git a/MS/works/controller/works.h b/MS/works/controller/works.h index d05644b..32b0739 100644 --- a/MS/works/controller/works.h +++ b/MS/works/controller/works.h @@ -7,6 +7,6 @@ #include "UserProveController.h" #include "IMProveController.h" -#include "PEVerifCode.h" +#include "PEVerifCodeController.h" #endif //IM2_WORKS_H diff --git a/MS/works/service/PEVerifCodeService.cpp b/MS/works/service/PEVerifCodeService.cpp new file mode 100644 index 0000000..a5089c3 --- /dev/null +++ b/MS/works/service/PEVerifCodeService.cpp @@ -0,0 +1,23 @@ +// +// Created by dongl on 23-5-10. +// + +#include +#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); +} diff --git a/MS/works/service/PEVerifCodeService.h b/MS/works/service/PEVerifCodeService.h new file mode 100644 index 0000000..7038ecb --- /dev/null +++ b/MS/works/service/PEVerifCodeService.h @@ -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 diff --git a/MS/works/service/UserService.cpp b/MS/works/service/UserService.cpp index c85f613..1e0e494 100644 --- a/MS/works/service/UserService.cpp +++ b/MS/works/service/UserService.cpp @@ -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) { // 判断密码 diff --git a/TEST/CMakeLists.txt b/TEST/CMakeLists.txt index 43930e4..b518307 100644 --- a/TEST/CMakeLists.txt +++ b/TEST/CMakeLists.txt @@ -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 ) \ No newline at end of file diff --git a/TEST/main.cpp b/TEST/main.cpp index df157e6..c02b3aa 100644 --- a/TEST/main.cpp +++ b/TEST/main.cpp @@ -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); -} \ No newline at end of file +} + + + +// "smtp.163.com", +// "bxhuu1o1vvyviiij6w@163.com", +// "IWXVJLUPMVFCFOBX", +// "2725096176@qq.com", +// "这是你的IM验证码", + +//"
\n" +// "

验证码: XP02EE

\n" +//"
" + + +TEST(email_send, email_send__Test) { + send_email_def("2725096176@qq.com", "AAKXT4"); +} diff --git a/include/mp/Body.h b/include/mp/Body.h index e9d8f67..cd6d834 100644 --- a/include/mp/Body.h +++ b/include/mp/Body.h @@ -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); } diff --git a/include/smtp/send_email.h b/include/smtp/send_email.h new file mode 100644 index 0000000..d43e654 --- /dev/null +++ b/include/smtp/send_email.h @@ -0,0 +1,207 @@ +// +// Created by dongl on 23-5-10. +// + +#ifndef IM2_SEND_EMAIL_H +#define IM2_SEND_EMAIL_H + +#include +#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 "\n" + "\n" + "\n" + " \n" + " 邮箱验证码\n" + " \n" + "\n" + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + " \n" + " \n" + "
\n" + "
\n" + "
\n" + "
\n" + " 尊敬的用户:您好!\n" + " \n" + " 您正在进行注册账号操作,请在验证码中输入以下验证码完成操作:\n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "
\n" + " \n" + " 注意:此操作可能会修改您的密码、登录邮箱或绑定手机。如非本人操作,请及时登录并修改密码以保证帐户安全\n" + "
(工作人员不会向你索取此验证码,请勿泄漏!)\n" + "
\n" + "
\n" + "
\n" + "
\n" + "
\n" + "

此为系统邮件,请勿回复
\n" + " 请保管好您的邮箱,避免账号被他人盗用\n" + "

\n" + "

——IM Base Email

\n" + "
\n" + "
\n" + "
\n" + "\n"; +} +#endif //IM2_SEND_EMAIL_H diff --git a/include/smtp/smtp.h b/include/smtp/smtp.h new file mode 100644 index 0000000..f5643c8 --- /dev/null +++ b/include/smtp/smtp.h @@ -0,0 +1,60 @@ +#ifndef __JXIEPC_SMTP_H__ +#define __JXIEPC_SMTP_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + diff --git a/lib/smtp/libcurl.so b/lib/smtp/libcurl.so new file mode 100755 index 0000000..6e8d778 Binary files /dev/null and b/lib/smtp/libcurl.so differ