5/26 邮件

main
zouxk 5 years ago
parent 40570af6db
commit dcc7c6f0d1

@ -0,0 +1,479 @@
/*
**CSendMail
**
**program by six_beauty
*/
//#include <afx.h>
#include "CSendMail.h"
#include "time.h"
#include <sstream>
#include <fstream>
#pragma comment(lib,"WSOCK32")
#pragma comment(lib, "ws2_32")
const std::string _AppOctStrmContent_encode_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//类的实现
CSendMail::CSendMail(void) { }
CSendMail::~CSendMail(void) {
clearReceiver();
DeleteAllPath();
}
//连接
bool CSendMail::Connent() {
//邮件信息设置判断
if (m_ServerName.empty() || m_UserName.empty() || m_UserPwd.empty()) {
m_logInfo.logInfo("Connect 失败,请先设置邮件登陆信息!");
return false;
}
if (!CReateSocket())//建立连接
{
m_logInfo.logInfo("建立连接失败!");
return false;
}
if (!Logon())//建立连接
{
m_logInfo.logInfo("登陆失败!");
return false;
}
return true;
}
//发送邮件的函数送
bool CSendMail::SendMail(const std::string mail_title, const std::string send_content) {
//参数赋值
m_MailTitle = mail_title;
m_TextBody = send_content;
if (m_SenderName.empty() || m_SenderAddr.empty() || m_Receivers.empty()) {
m_logInfo.logInfo("[SendMail]邮件参数设置错误,请检查邮件发送设置信息是否完整!");
return false;
}
if (!SendHead())//发送邮件头
{
m_logInfo.logInfo("发送邮件头失败!");
return false;
}
if (!SendTextBody())//发送邮件文本部分
{
return false;
}
if (!SendFileBody())//发送附件
{
return false;
}
if (!SendEnd())//结束邮件并关闭sock
{
return false;
}
return true;
}
////////////////////////////////////////////设置邮件信息/////////////////////////////////////////////////////////////////////
void CSendMail::setServerName(const std::string server_name) //smtp服务器地址
{
m_ServerName = server_name;
}
void CSendMail::setUserName(const std::string user_name) //邮箱用户名
{
m_UserName = user_name;
}
void CSendMail::setUserPwd(const std::string user_pwd) //邮箱用户密码
{
m_UserPwd = user_pwd;
}
void CSendMail::setSenderName(const std::string sender_name) //发送者的名字
{
m_SenderName = sender_name;
}
void CSendMail::setSenderAddress(const std::string sender_addr) //发送者的邮箱(mail form:)
{
m_SenderAddr = sender_addr;
}
void CSendMail::addReceiver(const std::string name, const std::string address) {
m_Receivers.insert(RECEIVERS::value_type(name, address));
}
void CSendMail::setReceiver(const std::string name, const std::string address) {
m_Receivers.clear();
m_Receivers.insert(RECEIVERS::value_type(name, address));
}
void CSendMail::clearReceiver() {
m_Receivers.clear();
}
void CSendMail::AddFilePath(std::string szFilePath)//添加附件路径
{
for (std::list<std::string>::iterator itrList = m_FilePathList.begin();itrList != m_FilePathList.end();++itrList) {
if (itrList->compare(szFilePath) == 0) {
//已经存在
return;
}
}
//还未加入
m_FilePathList.push_back(szFilePath);
}
void CSendMail::DeleteFilePath(std::string szFilePath)//删除附件路径
{
for (std::list<std::string>::iterator itrList = m_FilePathList.begin();itrList != m_FilePathList.end();) {
if (itrList->compare(szFilePath) == 0) {
itrList = m_FilePathList.erase(itrList);
} else {
itrList++;
}
}
}
void CSendMail::DeleteAllPath(void) {
m_FilePathList.clear();
}
////////////////////////////////////////////功能函数///////////////////////////////////////////////////////////////////
//实现CString的Replace
string& CSendMail::replace_all(string& str, const string& old_value, const string& new_value) {
while (true) {
string::size_type pos(0);
if ((pos = str.find(old_value)) != string::npos)
str.replace(pos, old_value.length(), new_value);
else
break;
}
return str;
}
//从附件的路径中获取文件名称
std::string CSendMail::GetFileName(std::string &szFilePath) {
replace_all(szFilePath, "/", "\\");
string szFileName = szFilePath.substr(szFilePath.rfind("\\") + 1, szFilePath.length());
return szFileName;
}
//以字符形式读入附件内容
std::string CSendMail::GetFileData(std::string szFilePath) {
std::string szBuffer;
if (szFilePath.empty()) {
m_logInfo.logInfo("[SendFileBody]Error:附件路径为空!");
return szBuffer;
}
ifstream ifFile(szFilePath.c_str(), ios::binary | ios::in);
if (!ifFile) {
m_logInfo.logInfo("[SendFileBody]Error:打开附件路径错误!");
return szBuffer;
}
ifFile.seekg(0, ios::beg);
std::ostringstream tmp;
tmp << ifFile.rdbuf();
szBuffer = tmp.str();
ifFile.close();
return szBuffer;
}
//把char类型转换成Base64类型
std::string CSendMail::Base64Encode(std::string in_str) {
std::string out_str;
unsigned char c1, c2, c3;
int i = 0;
int len = in_str.length();
while (i<len) {
// read the first byte
c1 = in_str[i++];
if (i == len) // pad with "="
{
out_str += _AppOctStrmContent_encode_chars[c1 >> 2];
out_str += _AppOctStrmContent_encode_chars[(c1 & 0x3) << 4];
out_str += "==";
break;
}
// read the second byte
c2 = in_str[i++];
if (i == len) // pad with "="
{
out_str += _AppOctStrmContent_encode_chars[c1 >> 2];
out_str += _AppOctStrmContent_encode_chars[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
out_str += _AppOctStrmContent_encode_chars[(c2 & 0xF) << 2];
out_str += "=";
break;
}
// read the third byte
c3 = in_str[i++];
// convert into four bytes string
out_str += _AppOctStrmContent_encode_chars[c1 >> 2];
out_str += _AppOctStrmContent_encode_chars[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
out_str += _AppOctStrmContent_encode_chars[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)];
out_str += _AppOctStrmContent_encode_chars[c3 & 0x3F];
}
return out_str;
}
int CSendMail::sendRequest(const std::string content, bool bout) {
int len_s = send(_socket, content.c_str(), content.length(), 0);
if (len_s < 0) {
m_logInfo.logInfo("[ERROR]SEND:%s", content.c_str());
return false;
}
//输出信息
if (bout) {
m_logInfo.logInfo("[INFO]SEND:%s", content.c_str());
}
return len_s;
}
bool CSendMail::rcvResponse(const std::string expected_response) {
int recv_bytes = 0;
char response_buffer[MAX_BUFFER_SIZE];
if ((recv_bytes = recv(_socket, response_buffer, MAX_BUFFER_SIZE, 0)) < 0) {
m_logInfo.logInfo("[ERROR]RECV:%s", expected_response.c_str());
return false;
}
//输出信息
std::string response(response_buffer, recv_bytes);
m_logInfo.logInfo("[INFO]RECV(%s):%s", expected_response.c_str(), response.c_str());
if (response.substr(0, 3) != expected_response) {
return false;
}
return true;
}
std::string CSendMail::prepareDate() {
char date_string[MAX_BUFFER_SIZE];
time_t seconds;
time(&seconds);
strftime(date_string, MAX_BUFFER_SIZE,
"%a, %d %b %y %H:%M:%S +0800",
localtime(&seconds)); // +0800 maybe hard code
return date_string;
}
////////////////////////////////////////////////工作函数//////////////////////////////////////////////////////////////////////
bool CSendMail::CReateSocket() {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
m_logInfo.logInfo("WSAStartup调用失败!");
return false;
}
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2) {
WSACleanup();
return false;
}
_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (_socket == INVALID_SOCKET) {
m_logInfo.logInfo("socket创建失败!");
return false;
}
sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVICE_PORT);//发邮件一般都是25端口
struct hostent *hp = gethostbyname(m_ServerName.c_str());//使用名称
if (hp == NULL) {
DWORD dwErrCode = GetLastError();
return false;
}
servaddr.sin_addr.s_addr = *(int*)(*hp->h_addr_list);
int ret = connect(_socket, (sockaddr*)&servaddr, sizeof(servaddr));//建立连接
if (ret == SOCKET_ERROR) {
DWORD dwErr = GetLastError();
return false;
}
if (!rcvResponse("220"))
return false;
return true;
}
bool CSendMail::Logon() {
char local_host[MAX_BUFFER_SIZE];
if (gethostname(local_host, MAX_BUFFER_SIZE) != 0) {
m_logInfo.logInfo("Get local host name error!");
return false;
}
std::string msg;
msg = "HELO ";
msg += std::string(local_host) + "\r\n";
sendRequest(msg);
if (!rcvResponse("250")) {
return false;
}
msg = "AUTH LOGIN\r\n";
sendRequest(msg);
if (!rcvResponse("334")) {
return false;
}
msg = Base64Encode(m_UserName) + "\r\n";
sendRequest(msg);
if (!rcvResponse("334")) {
return false;
}
msg = Base64Encode(m_UserPwd) + "\r\n";
sendRequest(msg);
if (!rcvResponse("235")) {
return false;
}
return true;//登录成功
}
///////////////////////////////////SendMail////////////////////////////////////////////////////
//发送邮件头
bool CSendMail::SendHead() {
std::string msg;
msg = "MAIL FROM:<";
msg += m_SenderAddr + ">\r\n";
sendRequest(msg);
if (!rcvResponse("250")) {
m_logInfo.logInfo("邮件地址错误:%s", m_SenderAddr.c_str());
return false;
}
//遍历获得receiver
for (RECEIVERS::iterator itrRec = m_Receivers.begin();itrRec != m_Receivers.end();itrRec++) {
msg = "RCPT TO: <";
msg += itrRec->second + ">\r\n";
sendRequest(msg);
if (!rcvResponse("250")) {
return false;
}
}
msg = "DATA\r\n";
sendRequest(msg);
if (!rcvResponse("354")) {
return false;
}
//发送Headers
msg = "From:\"" + m_SenderName + "\"<" + m_SenderAddr + ">\r\n";
//遍历receiver
msg += "To: ";
for (RECEIVERS::iterator itrRec = m_Receivers.begin();itrRec != m_Receivers.end();itrRec++) {
std::string szRecv;
szRecv = "\"" + itrRec->first + "\"<" + itrRec->second + ">, ";
msg += szRecv;
}
msg += "\r\n";
msg += "Date: ";
msg += prepareDate() + "\r\n";
msg += "Subject: ";
msg += m_MailTitle + "\r\n";
msg += "X-Mailer: six_beauty \r\n";
msg += "MIME-Version: 1.0\r\n";
msg += "Content-type: multipart/mixed; boundary=\"INVT\"\r\n\r\n";
msg += "\r\n";
sendRequest(msg);
return true;
}
bool CSendMail::SendTextBody() {
std::string msg;
msg = "--INVT\r\nContent-Type: text/plain;\r\n charset=\"gb2312\"\r\n\r\n";
msg += m_TextBody;
msg += "\r\n\r\n";
int len_s = sendRequest(msg, true);
if (len_s != msg.length()) {
m_logInfo.logInfo("发送邮件正文出错,应该发送长度(%d实际发送长度%d", msg.length(), len_s);
return false;
}
return true;
}
bool CSendMail::SendFileBody() {
std::string msg;
//遍历发送附件文件
for (std::list<std::string>::iterator itrList = m_FilePathList.begin();itrList != m_FilePathList.end();itrList++) {
std::string filePath = *itrList;
std::string fileName = GetFileName(filePath);
std::string szContent = GetFileData(filePath);
msg = "--INVT\r\nContent-Type: application/octet-stream;\r\n name=\"";
msg += fileName;
msg += "\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment;\r\n filename=\"";
msg += fileName;
msg += "\"\r\n\r\n";
sendRequest(msg, true);
int npos = 0, len = szContent.length();
while (npos<len) {
std::string szBuffer = Base64Encode(szContent.substr(npos, min(len - npos, 3000)));
szBuffer += "\r\n";
sendRequest(szBuffer);
npos += min(len - npos, 3000);
}
}
return true;
}
bool CSendMail::SendEnd() {
std::string msg;
msg = "--INVT--\r\n.\r\n";
sendRequest(msg, true);
msg = "QUIT\r\n";
sendRequest(msg, true);
closesocket(_socket);
WSACleanup();
return true;
}

@ -0,0 +1,94 @@
/*
**CSendMail
**
**program by six_beauty
*/
#pragma once
#include <string>
#include <list>
#include <map>
#include "LogInfo.h"
#include <winsock2.h>
//类型定义
const int MAX_BUFFER_SIZE = 255; //send和recv的缓存buffer的size
const int SERVICE_PORT = 25; //端口
typedef std::map<std::string, std::string> RECEIVERS;
//CSendMail类
class CSendMail {
public:
CSendMail();
~CSendMail();
//////////////////////////////////////设置邮件信息/////////////////////////////////////////////////////////////////////////////////
/////////////////////////connent///////////////////////////////////
void setServerName(const std::string server_name); //smtp服务器地址
void setUserName(const std::string user_name); //邮箱用户名
void setUserPwd(const std::string user_pwd); //邮箱用户密码
/////////////////////////SendMail//////////////////////////////////
void setSenderName(const std::string sender_name); //发送者的名字
void setSenderAddress(const std::string sender_addr); //发送者的邮箱(mail form:)
//邮件接收者
void setReceiver(const std::string name, const std::string address); //先clear再add
void addReceiver(const std::string name, const std::string address); //增加邮件接收者name是收件人名字mail是地址
void clearReceiver(); //情况邮件接收者
//添加附件
void AddFilePath(std::string szFilePath); //添加附件路径到附件列表中一般的smtp服务器处理附件不超过50MB
void DeleteFilePath(std::string szFilePath); //删除附件路径,如果有的话
void DeleteAllPath(); //删除全部附件的路径
/////////////////////////////////////发送邮件//////////////////////////////////////////////////////////////////////////////////////
//连接
bool Connent();
//邮件发送
bool SendMail(const std::string mail_title, const std::string send_content); //发送邮件的函数
private:
//功能函数
inline std::string& replace_all(string& str, const string& old_value, const string& new_value); //其实就是CString的Replace
std::string GetFileName(std::string&szFilePath); //从附件的路径中获取文件名称
std::string GetFileData(std::string szFilePath); //以字符形式读入附件内容
std::string Base64Encode(std::string in_str); //把char类型转换成Base64类型
//获取时间
std::string prepareDate();
//通信recv和send的封装
int sendRequest(const std::string content, bool bout = false); //返回发送了多少字节
bool rcvResponse(const std::string expected_response); //返回接收的结果和expected_response是否相同
//工作函数
bool CReateSocket(); //建立socket连接
bool Logon(); //登录邮箱,主要进行发邮件前的准备工作
bool SendHead(); //发送邮件头
bool SendTextBody(); //发送邮件文本正文
bool SendFileBody(); //发送邮件附件
bool SendEnd(); //发送邮件结尾
SOCKET _socket;
LogInfo m_logInfo;
/////////////////////////邮件信息///////////////////////////////////
/////////////////////////connent///////////////////////////////////
std::string m_ServerName; //smtp服务器地址
std::string m_UserName; //邮箱用户
std::string m_UserPwd; //邮箱用户密
/////////////////////////SendMail//////////////////////////////////
std::string m_SenderName; //发送者的名
std::string m_SenderAddr; //发送者的邮箱(mail form:)
std::string m_MailTitle; //邮件标题(subject)
std::string m_TextBody; //邮件正文
RECEIVERS m_Receivers; //邮件接收者name,email_address)
std::list<std::string> m_FilePathList; //附件路径_list
/////////////////////////邮件信息///////////////////////////////////
};

@ -0,0 +1,25 @@
#include<iostream>
#include<stdarg.h>
using namespace std;
const int BUF_SIZE = 4096;
//实现输出类
class LogInfo {
public:
LogInfo() { };
~LogInfo() { };
void logInfo(char *szFormat, ...) {
char szBuf[BUF_SIZE] = { };
va_list args; //第一步
va_start(args, szFormat); //第二步
_vsnprintf(szBuf, BUF_SIZE, szFormat, args); //第三步
va_end(args); //第四步
//在这是实现输出方式
std::cout << szBuf << endl;
return;
}
};

@ -0,0 +1,38 @@
#include "util.h"
int jd_get_target(EPM_action_message_t msg) {
POM_AM__set_application_bypass(true);
tag_t root_task, *attachments;
int att_cnt;
stringstream ss;
EPM_ask_root_task(msg.task, &root_task);
EPM_ask_attachments(root_task, EPM_target_attachment, &att_cnt, &attachments);
for (int i = 0;i < att_cnt;i++) {
char *item_id, *item_revision_id;
if (isTypeOf(attachments[i], "ItemRevision")) {
AOM_ask_value_string(attachments[i], "item_id", &item_id);
AOM_ask_value_string(attachments[i], "item_revision_id", &item_revision_id);
ss << item_id;
ss << "/";
ss << item_revision_id;
ss << ",";
}
}
string temp = ss.str().substr(0, ss.str().length() - 1);
//AOM_lock(root_task);
//AOM_set_value_string(root_task, "jd2_task_target", temp.c_str());
//AOM_save(root_task);
//AOM_unlock(root_task);
POM_AM__set_application_bypass(false);
ofstream out;
stringstream file_location;
file_location << getenv("temp");
file_location << "\\";
file_location << "jd2_task_target.txt";
out.open(file_location.str().c_str(), ios::out | ios::trunc);
out << temp.c_str() << endl;
out.close();
return 0;
}

@ -0,0 +1,154 @@
#include "CSendMail.h"
#include "boost\algorithm\\string.hpp"
#include "util.h"
int jd_send_mail(EPM_action_message_t msg) {
POM_AM__set_application_bypass(true);
tag_t root_task, *attachments;
int att_cnt;
EPM_ask_root_task(msg.task, &root_task);
EPM_ask_attachments(root_task, EPM_target_attachment, &att_cnt, &attachments);
TC_argument_list_t *arguments = msg.arguments;
int arg_cnt = TC_number_of_arguments(arguments);
map<string, string> paras;
for (auto i = 0; i < arg_cnt; i++) {
char *temp_key, *temp_val;
ITK_ask_argument_named_value(TC_next_argument(arguments), &temp_key, &temp_val);
paras[temp_key] = temp_val;
}
stringstream mail_content;
if (att_cnt <= 0) {
return 0;
}
char target_str[2000];
vector<string> target_vec;
//AOM_ask_value_string(root_task, "jd2_task_target", &target_str);
ifstream in;
stringstream file_location;
file_location << getenv("temp");
file_location << "\\";
file_location << "jd2_task_target.txt";
in.open(file_location.str().c_str(), ios::in);
in >> target_str;
in.close();
printf("target_str====>%s\n", target_str);
split(target_str, ",", &target_vec);
for (int i = 0;i < target_vec.size();i++) {
mail_content << target_vec[i].c_str();
mail_content << " ";
mail_content << paras["mail_para"];
mail_content << "\r\n";
}
//tag_t win;
//BOM_create_window(&win);
//for (int i = 0;i < att_cnt;i++) {
// if (isTypeOf(attachments[i], "Form")) {
// int rel_cnt, *levels;
// tag_t *rels, rev = NULLTAG, form;
// char **relations;
// form = attachments[i];
// WSOM_where_referenced2(form, 1, &rel_cnt, &levels, &rels, &relations);
// for (int j = 0;j < rel_cnt;j++) {
// printf("relations:%s\n", relations[j]);
// if (tc_strcmp(relations[j], "IMAN_master_form") == 0) {
// rev = rels[j];
// }
// }
// if (rev == NULLTAG) {
// printf("revision get error\n");
// continue;
// }
// char *item_id;
// AOM_ask_value_string(rev, "item_id", &item_id);
// char *rev_id;
// AOM_ask_value_string(rev, "item_revision_id", &rev_id);
// mail_content << item_id;
// mail_content << "/";
// mail_content << rev_id;
// mail_content << " ";
// mail_content << paras["mail_para"];
// mail_content << "\r\n";
// } else if (isTypeOf(attachments[i], "PSBOMViewRevision")) {
// tag_t top_line, rev;
// char *id;
// BOM_set_window_top_line_bvr(win, attachments[i], &top_line);
// if (top_line == NULLTAG)
// continue;
// AOM_ask_value_tag(top_line, "bl_line_object", &rev);
// if (rev == NULLTAG)
// continue;
// AOM_ask_value_string(rev, "item_id", &id);
// char *rev_id;
// AOM_ask_value_string(rev, "item_revision_id", &rev_id);
// mail_content << id;
// mail_content << "/";
// mail_content << rev_id;
// mail_content << " ";
// mail_content << paras["mail_para"];
// mail_content << "\r\n";
// }
//}
//BOM_close_window(win);
POM_AM__set_application_bypass(false);
vector<string> address, to_name, from_pref;
stringstream mail_body;
tag_t owning;
char *from_user, **pref_values;
int pref_cnt, from_index = -1;
split(paras["mail_address"], ",", &address);
AOM_ask_value_tag(root_task, "owning_user", &owning);
AOM_ask_value_string(owning, "object_string", &from_user);
PREF_ask_char_values("jd2_user_mail_account", &pref_cnt, &pref_values);
printf("from_user:%s\n", from_user);
for (int i = 0;i < pref_cnt;i++) {
split(pref_values[i], ":", &from_pref);
printf("pref:%s\n", pref_values[i]);
//if (tc_strcmp(from_user, from_pref[0].c_str()) == 0) {
// break;
//}
//from_pref.clear();
}
if (from_pref.size() == 0) {
printf("没有找到对应用户邮箱\n");
return 0;
}
CSendMail sMailer;
// freopen("F://mailfile//out.txt","w+",stdout);
sMailer.setServerName("smtp.mxhichina.com"); //邮箱smtp,如"smtp.126.com"
sMailer.setUserName("lvmh@jide.cn"); //邮箱账号名,如"****@126.com"
sMailer.setUserPwd("lmh1995815."); //邮箱密码
sMailer.setSenderName(from_user); //发件人名字
sMailer.setSenderAddress("lvmh@jide.cn"); //发送邮箱地址,填你账号的地址,上面的邮箱账号名"****@126.com"
mail_content << "\r\n";
mail_content << "from: ";
mail_content << from_user;
mail_content << "\r\n";
mail_content << "email: ";
mail_content << from_pref[1];
mail_content << "\r\n";
for (int i = 0; i < address.size(); i++) {
split(address[i], "@", &to_name);
sMailer.addReceiver(to_name[0].c_str(), address[i].c_str()); //添加邮件接收者
to_name.clear();
}
if (sMailer.Connent()) { //每次发邮件前都需要connect
if (sMailer.SendMail("SAP更改", mail_content.str().c_str())) //第一个字符串是邮件标题,第二个是邮件内容
cout << "邮件发送成功!\n";
}
return 0;
}
Loading…
Cancel
Save