smtp version:2
来源:互联网 发布:涉密检查软件 编辑:程序博客网 时间:2024/06/07 10:13
重新实现了一下smtp,加入一些错误检查,可以发送附件.
头文件:
#ifndef SMTP_H#define SMTP_H#include<iostream>#include<utility>#include<stdexcept>#include<sstream>#include"boost/asio.hpp"#include"boost/format.hpp"#include<boost/algorithm/string.hpp>#include"logging.h"#include"MIME/base64.h"namespace email {using namespace std;using namespace boost;using namespace boost::asio;using namespace logging;#define CR "\r"#define LF "\n"#define CRLF "\r\n"class smtp{ typedef pair<int, string> response;public: void test(); smtp(io_service& i,const string host, const string port = "smtp"); ~smtp(); void Set_DebugLevel(bool value); response Quit(); response Noop(); response Helo(const string username); response Ehlo(const string username); response Login(const string username,const string password); response SendMail(const string from_addr, const list<string> to_addrs_list, const string msg); response SendMail(const string from_addr, const list<string> to_addrs_list, istream& input);private: string _Host; string _Port; string _Myaddr; bool _DebugLevel; io_service& _Serivce; ip::tcp::socket _Sock; asio::streambuf _Streambuf; response Connect(); string Get_Line(); response Get_Reply(); void Put_Cmd(const string cmd, const string endline = CRLF); response Do_Cmd(string const cmd); response Data(const string msg);};}#endif // SMTP_H
实现:
#include "smtp.h"namespace email {smtp::smtp(io_service &i, const string host, const string port) :_Serivce(i),_Sock(i){ _Host = host; _Port = port; response rsp = Connect (); if (rsp.first != 220) throw std::runtime_error("Connect error"); if (_DebugLevel) logger().debug ("Connect succeed");}smtp::~smtp (){ Quit();}smtp::response smtp::Connect(){ /* * 迭代测试服务器 */ ip::tcp::resolver Rsv(_Serivce); ip::tcp::resolver::query query(_Host, _Port); ip::tcp::resolver::iterator Iter; ip::tcp::resolver::iterator EndIter; boost::system::error_code err; for(Iter = Rsv.resolve(query); Iter != EndIter; ++Iter){ _Sock.connect (*Iter,err); if (!err) break; _Sock.close (); } if(err) throw runtime_error("Connect error"); return Get_Reply();}void smtp::Set_DebugLevel(bool value){ /* * 设置调试级别 */ _DebugLevel = value;}smtp::response smtp::Quit (){ return Do_Cmd ("QUIT");}smtp::response smtp::Noop (){ return Do_Cmd ("NOOP");}smtp::response smtp::Helo (const string username){ auto resp = Do_Cmd ("HELO " + username); if (resp.first != 250) throw runtime_error("HELO error"); return resp;}smtp::response smtp::Ehlo (const string username){ auto resp = Do_Cmd ("EHLO " +username); if (resp.first != 250) return resp; logger().info (resp.second); return resp;}smtp::response smtp::Login (const string username, const string password){ auto reply = Ehlo (username); if (!contains(reply.second,"AUTH LOGIN")) throw std::runtime_error("AUTH LOGIN:nonsupport"); reply = Do_Cmd ("AUTH LOGIN"); if (reply.first != 334) throw std::runtime_error("AUTH LOGIN error:"); reply = Do_Cmd(encode_base64 (username)); if (reply.first != 334) throw std::runtime_error("AUTH LOGIN error:"); reply = Do_Cmd(encode_base64 (password)); if (reply.first != 235 && reply.first != 503) /* * 235 == 'Authentication successful' * 503 == 'Error: already authenticated' */ throw std::runtime_error("AUTH LOGIN error:"); _Myaddr = username; return reply;}smtp::responsesmtp::SendMail (const string from_addr, const list<string> to_addrs_list, const string msg){ /* *mail FROM: 开始* */ auto reply = Do_Cmd (str(format("mail FROM:<%s") % from_addr)); if (reply.first != 250) if (reply.first == 412) throw std::runtime_error("rcpt TO error: SMTPSenderRefused"); /* * mail FROM: 成功,rcpt TO:开始 */ for (auto iter = to_addrs_list.begin (); iter != to_addrs_list.end (); ++iter){ reply = Do_Cmd (str(format("rcpt TO:<%s>") % *iter)); if (reply.first != 250 && reply.first != 251){ if (reply.first == 412) throw std::runtime_error("rcpt TO error: RecipientsRefused"); } } /* * rcpt TO:成功,DATA:开始 */ return Data(msg);}smtp::response smtp::SendMail (const string from_addr, const list<string> to_addrs_list, istream& input){ /* * 可从文件或标准输出读,方便使用 */ string msg; while(input){ string buf; std::getline(input,buf); msg.append (buf + "\n"); //getline返回的行里没有"\n" } return SendMail (from_addr,to_addrs_list,msg);}string smtp::Get_Line(){ /* *服务器返回的行可能会有'\n'或'\r\n',页getline会把'\n'去掉. * 因此只要检查是否有'\r',有侧去掉; */ size_t n = read_until(_Sock, _Streambuf, '\n'); std::istream is(&_Streambuf); std::string line; std::getline(is, line); /* * getline会 */ if (boost::iends_with(line, CR)) line.pop_back (); return line;}smtp::response smtp::Get_Reply(){ int code; string msg; while(true){ string line(Get_Line ()); stringstream sst(line); try{ sst >> code; msg.append (line.data () + 4); if (line[3] == ' ') break; } catch (std::exception e){ throw std::runtime_error("Get_reply errror"); } } if (_DebugLevel) logger().debug (str(format("*Get_Reply:*: %d %s") %code %msg)); return response ({code,msg});}void smtp::Put_Cmd(const string cmd, const string endline){ /* * 发送命令,行结束符endline默认是'\r\n' */ string line = cmd + endline; size_t n = write(_Sock,buffer(line.data (),line.size ())); assert(n == line.size ()); if (_DebugLevel) logger().debug ("*Put_Cmd*: " + cmd);}smtp::response smtp::Do_Cmd(const string cmd){ Put_Cmd(cmd); return Get_Reply();}smtp::response smtp::Data(const string msg){ auto reply = Do_Cmd ("DATA"); if (reply.first != 354) throw std::runtime_error("DATA error"); /* * DATA成功,开始发送内容 */ stringstream sst(msg); while(sst){ string line; std::getline(sst,line); if (boost::istarts_with(line, LF)) line.erase (line.begin ()); if (boost::iends_with(line, CR)) line.pop_back (); Put_Cmd (line); } reply = Do_Cmd ("."); if (reply.first != 250) if (reply.first != 421) throw std::runtime_error("SendMail error"); /* * 内容发达成功 */ return reply;}}
下一步:写一个邮件的生成器和解释器
0 0
- smtp version:2
- SMTP
- SMTP
- SMTP
- smtp
- smtp
- smtp
- SMTP
- SMTP
- smtp
- smtp
- laravel5.2邮件发送smtp
- 解决2个smtp的问题: SMTP Error: Could not connect to SMTP host.
- RIP Version 2
- Freshman-version 2
- Subverting PatchGuard Version 2
- PHP Version 5.1.2
- RFC2328 - OSPF Version 2
- Coursera上Andrew Ng机器学习课程总结(二)
- 【USACO3.4.2】美国血统
- 精美的聊天界面
- 学习笔记:Foundation(1)---NSRange结构体、NSPoint结构体
- html表单
- smtp version:2
- 短语、句柄、素短语、最左素短语
- 22.在创业公司中的成长
- 【Android】关于android开发,环境部署的一些小问题
- 【重学《C++Primer第四版》】第五章、表达式
- C++继承关系中的动态内存分配
- 文章标题
- C++11中值得关注的几大变化
- 可伸缩矢量图形(SVG)样式的设置