C + + implementation of sending message body and its attachments

Source: Internet
Author: User
Tags base64 strlen

This code I spent a whole day to write, if reproduced, please indicate the source, thank you.

the previous article has said how to send the message body, the principle I will no longer describe, to understand the students please come here to see!

http://blog.csdn.net/lishuhuakai/article/details/27503503

Many online mail attachments to the code can not be used, so I carefully wrote a, directly packaged into a class, the need for students can directly call this class to send mail, pure C + + code. (tested perfectly through the VS2013!)

nonsense not much to say, directly on the code!

Smtp.h

#ifndef __smtp_h__//Avoid duplication including #define __SMTP_H__ #include <iostream> #include <list> #include &LT;WINSOCK2.H&G
T

using namespace Std;
const int maxlen = 1024;

const int Max_file_len = 6000;

static const char base64char[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/";

struct FILEINFO/* Some information used to record files * * {char filename[128];/* file name/char filepath[256]; * File absolute path/};
	Class Csmtp {public:csmtp (void); CSMTP (int port, string srvdomain,//smtp server domain name string userName,//username string password,//password string targetemail,
Destination mail address string emailtitle,//Subject string content/content);
Public: ~csmtp (void);
Public:int Port;
	Public:string domain;
	string user;
	String Pass;
	String targetaddr;
	string title;
	string content;

* * To facilitate the addition of files, delete files God horse, use list container is most convenient, I believe we have learned in the data structure inside the * * list <fileinfo *> listfile;
	Public:char Buff[maxlen + 1];
	int Bufflen;	SOCKET sockclient; The socket of the client Public:bool createconn (); /* Create connection */bool Send (String &amP;message);

	BOOL Recv ();
	void Formatemailhead (string &email);//Format the message header to send int Login ();		BOOL Sendemailhead ();	    Send Message header information bool Sendtextbody ();	    Send text message//bool sendattachment ();
	Send attachment int sendattachment_ex ();
BOOL Sendend (); Public:void addattachment (string &filepath); Add attachment void DeleteAttachment (string &filepath); Delete attachment void deleteallattachment ();
	Delete all attachments void Setsrvdomain (string &domain);
	void Setusername (string &user);
	void SetPass (string &pass);
	void Settargetemail (string &targetaddr);
	void Setemailtitle (string &title);
	void SetContent (string &content);
	void Setport (int port);
	int sendemail_ex ();
/* Description of error code: 1. Error caused by network error 2. Username Error 3. File does not exist 0. Successful/char* Base64Encode (char const* origsigned, unsigned origlength);

}; #endif//!__smtp_h__


Smtp.cpp

#include "Smtp.h" #include <iostream> #include <fstream> using namespace std; #pragma comment (lib, "Ws2_32.lib")/* link ws2_32.lib dynamic link library * */*base64 using someone else's code, however, this is not the point, the point is that I finished my a better mail sending client * * * char* Csmtp::base64encode (char const* origsigned, unsigned origlength) {unsigned char const* orig = (unsigned char const*) orig Signed;

	In case any input bytes have the MSB set if (orig = = null) return null;
	unsigned const numorig24bitvalues = ORIGLENGTH/3;
	BOOL havepadding = origlength > Numorig24bitvalues * 3;
	BOOL HavePadding2 = Origlength = = Numorig24bitvalues * 3 + 2;
	unsigned const NUMRESULTBYTES = 4 * (numorig24bitvalues + havepadding); char* result = new Char[numresultbytes + 3];
	Allow for trailing '/0 '//Map per full group of 3 input bytes into 4 output base-64 characters:unsigned i;
		for (i = 0; i < numorig24bitvalues ++i) {result[4 * i + 0] = base64char[(orig[3 * i] >> 2) & 0x3F]; Result[4 * i + 1] = base64char[((orig[3 * i) & 0x3) << 4) | (ORIG[3 * i + 1] >> 4))
		& 0x3F]; Result[4 * i + 2] = base64char[(orig[3 * i + 1] << 2) | (ORIG[3 * i + 2] >> 6))
		& 0x3F];
	Result[4 * i + 3] = base64char[orig[3 * i + 2] & 0x3F];  //Now, take padding to account. (note:i = = numorig24bitvalues) if (havepadding) {result[4 * i + 0] = base64char[(orig[3 * i] >> 2) & 0x3F]
		; if (havePadding2) {result[4 * i + 1] = base64char[((orig[3 * i] & 0x3) << 4) | (ORIG[3 * i + 1] >> 4))
			& 0x3F];
		Result[4 * i + 2] = base64char[(orig[3 * i + 1] << 2) & 0x3F];
			else {result[4 * i + 1] = base64char[(orig[3 * i] & 0x3) << 4) & 0x3F];
		Result[4 * i + 2] = ' = ';
	} result[4 * i + 3] = ' = ';
	} Result[numresultbytes] = ';
return result;
	} csmtp::csmtp (void) {this->content = "";
	This->port = 25;
	This->user = "";
	This->pass = "";
	THIS-&GT;TARGETADDR = "";
	This->title = ""; This->domain = "";
	WORD wversionrequested;
	Wsadata Wsadata;
	int err;
	wversionrequested = Makeword (2, 1);
	Err = WSAStartup (wversionrequested, &wsadata);

this->sockclient = 0;
	} csmtp::~csmtp (void) {deleteallattachment ();
	Closesocket (sockclient);
WSACleanup (); CSMTP::CSMTP (int port, string srvdomain, String userName, string password, string targetemail, String emailtitl
	E, string content) {this->content = content;
	This->port = port;
	This->user = UserName;
	This->pass = password;
	THIS-&GT;TARGETADDR = Targetemail;
	This->title = Emailtitle;

	This->domain = Srvdomain;
	WORD wversionrequested;
	Wsadata Wsadata;
	int err;
	wversionrequested = Makeword (2, 1);
	Err = WSAStartup (wversionrequested, &wsadata);
this->sockclient = 0;
	BOOL Csmtp::createconn () {//To prepare the socket object, initialize the environment socket sockclient = socket (af_inet, sock_stream, 0);//Create Socket Object
	Sockaddr_in addrsrv;
	hostent* phostent;  Phostent = gethostbyname (Domain.c_str ());
Get information about the domain name
	Addrsrv.sin_addr. S_un.	S_ADDR = * ((DWORD *) phostent->h_addr_list[0]);
	The IP address that gets the network byte order of the SMTP server addrsrv.sin_family = af_inet;
	Addrsrv.sin_port = htons (port);   int err = connect (sockclient, (sockaddr*) &addrsrv, sizeof (SOCKADDR));
		Send a request to the server if (Err!= 0) {return false;
	printf ("link failed \ n");
	} this->sockclient = Sockclient;
	if (false = = Recv ()) {return false;
return true;
	BOOL Csmtp::send (string &message) {int err = Send (sockclient, Message.c_str (), Message.length (), 0);
	if (err = = Socket_error) {return false;
	} string message01;
	cout << message.c_str () << Endl;
return true;
	BOOL Csmtp::recv () {memset (buff, 0, sizeof (char) * (MaxLen + 1)); int err = recv (sockclient, Buff, maxlen, 0);
	Receive data if (err = = Socket_error) {return false;
	} Buff[err] = ';
	cout << buff << Endl;
return true;
	int Csmtp::login () {string sendbuff;
	Sendbuff = "EHLO";
	Sendbuff + = user;

	Sendbuff + = "\ r \ n"; if (false = SEnd (Sendbuff) | |
	false = = RECV ())//Receive also send {return 1;/*1 means send failure due to network error */} sendbuff.empty ();
	Sendbuff = "AUTH login\r\n";
	if (false = Send (Sendbuff) | | false = RECV ())//Request Login {return 1;/*1 to send failure due to network error */} sendbuff.empty ();
	int pos = user.find (' @ ', 0); Sendbuff = User.substr (0, POS);
	Get user name char *ecode; /* Here incidentally, on the difference between the length function of the string class and the Strlen function in the C language, the strlen is calculated to be as long as the "'" and "String::length" () The function actually returns the size of the character array in the String class, and you can test it yourself, which is why I am not using string::length () for the following reasons * * Ecode = Base64Encode (Sendbuff.c_str (), strlen
	(Sendbuff.c_str ()));
	Sendbuff.empty ();
	Sendbuff = Ecode;
	Sendbuff + = "\ r \ n";

	Delete[]ecode; if (false = Send (Sendbuff) | | false = RECV ())//Send user name, and receive server return {1;/* error code 1 means send failed due to network error/} sendbuff.empty (
	);
	Ecode = Base64Encode (Pass.c_str (), strlen (Pass.c_str ()));
	Sendbuff = Ecode;
	Sendbuff + = "\ r \ n";

	Delete[]ecode; if (false = Send (Sendbuff) | | false = RECV ())//Send user password, and receive server return {1;/* error code 1 means send failed due to network error/} if (NULL!= St RSTR (Buff, "a") {return 2;/* error code 2 indicates a username error/} if (NULL!= strstr (Buff, "535"))/*535 is the authentication failed returns * * * 3;/* Error code 3 indicates the secret
Code Error */} return 0;
	BOOL Csmtp::sendemailhead ()//Send Message header information {string Sendbuff;
	Sendbuff = "MAIL from: <" + user + ">\r\n";
	if (false = Send (Sendbuff) | | false = RECV ()) {return false;/* indicates that the send failed due to a network error/} sendbuff.empty ();
	Sendbuff = "RCPT to: <" + targetaddr + ">\r\n";
	if (false = Send (Sendbuff) | | false = RECV ()) {return false;/* indicates that the send failed due to a network error/} sendbuff.empty ();
	Sendbuff = "data\r\n";
	if (false = Send (Sendbuff) | | false = RECV ()) {return false;//indicates that the send failed due to a network error} sendbuff.empty ();
	Formatemailhead (Sendbuff); if (false = Send (Sendbuff))///after sending the header, you do not have to call the receive function, because you do not have the \r\n.\r\n end, the server thinks you have not sent the data, so will not return what value {returns false;/* indicates that the send failed due to a network error
*/} return true;
	} void Csmtp::formatemailhead (String &email) {/* Format the content to be sent * * email = "From:";
	Email + + user;

	email + = "\ r \ n";
	Email + + "to:";
	email + + targetaddr; email + = "\r\n ";
	Email + + "Subject:";
	email + = title;

	email + = "\ r \ n";
	Email + + "mime-version:1.0";

	email + = "\ r \ n";
	Email + + "CONTENT-TYPE:MULTIPART/MIXED;BOUNDARY=QWERTYUIOP";
	email + = "\ r \ n";
email + = "\ r \ n";
	BOOL Csmtp::sendtextbody () * * Send Message Text */{string sendbuff;
	Sendbuff = "--qwertyuiop\r\n";
	Sendbuff + = "content-type:text/plain;";
	Sendbuff + + "charset=\" gb2312\ "\r\n\r\n";
	Sendbuff + + content;
	Sendbuff + = "\r\n\r\n";
Return Send (Sendbuff); int CSMTP::SENDATTACHMENT_EX ()/* Send attachment/{for (list<fileinfo *>::iterator piter = Listfile.begin (); Piter!= lis Tfile.end ();
		piter++) {cout << "attachment is sending ~~~~~" << Endl;
		cout << "Please be patient!" << Endl;
		String Sendbuff;
		Sendbuff = "--qwertyuiop\r\n";
		Sendbuff + = "content-type:application/octet-stream;\r\n";
		Sendbuff + + "name=\";
		Sendbuff + = (*piter)->filename;
		Sendbuff + = "" ";

		Sendbuff + = "\ r \ n";
	Sendbuff + = "content-transfer-encoding:base64\r\n";	Sendbuff + = "content-disposition:attachment;\r\n";
		Sendbuff + + "filename=\";
		Sendbuff + = (*piter)->filename;

		Sendbuff + = "" ";
		Sendbuff + = "\ r \ n";
		Sendbuff + = "\ r \ n";
		Send (Sendbuff);
		Ifstream IFS ((*piter)->filepath, ios::in | ios::binary);
		if (false = = Ifs.is_open ()) {return 4;/* error code 4 means file open error/} char Filebuff[max_file_len];
		Char *chsendbuff;
		memset (filebuff, 0, sizeof (filebuff));
			/* file using base64 encryption/while (Ifs.read (Filebuff, Max_file_len)) {//cout << ifs.gcount () << Endl;
			Chsendbuff = Base64Encode (Filebuff, Max_file_len);
			Chsendbuff[strlen (chsendbuff)] = ' \ r ';
			Chsendbuff[strlen (chsendbuff)] = ' \ n ';
			Send (Sockclient, Chsendbuff, strlen (Chsendbuff), 0);
		Delete[]chsendbuff;
		}//cout << Ifs.gcount () << Endl;
		Chsendbuff = Base64Encode (Filebuff, Ifs.gcount ());
		Chsendbuff[strlen (chsendbuff)] = ' \ r ';
		Chsendbuff[strlen (chsendbuff)] = ' \ n '; int err = Send (Sockclient, Chsendbuff, strlen (chsendbuff), 0);
			if (Err!= strlen (chsendbuff)) {cout file transfer Error! << Endl;
		return 1;
	} Delete[]chsendbuff;
return 0;
	BOOL Csmtp::sendend ()/* Send End message/{string Sendbuff;
	Sendbuff = "--qwertyuiop--";
	Sendbuff + = "\r\n.\r\n";
	if (false = Send (Sendbuff) | | false = = RECV ()) {return false;
	} cout << buff << Endl;
	Sendbuff.empty ();
	Sendbuff = "quit\r\n";
Return (Send (sendbuff) && Recv ());
	int csmtp::sendemail_ex () {if (false = Createconn ()) {return 1;
	}//recv (); int err = Login (); Login first if (Err!= 0) {return err;//error code must be returned} if (false = = Sendemailhead ())//Send Email header info {return 1;/* error code 1 is due to
	Network error/} if (false = = Sendtextbody ()) {return 1;/* error code 1 is due to network error */} err = SENDATTACHMENT_EX ();
	if (Err!= 0) {return err; } if (false = = Sendend ()) {return 1;/* error code 1 is due to network error/} return 0;
	/*0 said no error/} void Csmtp::addattachment (String &filepath)//Add attachment {FILEINFO *pfile = new FILEINFO; strcpy_s (Pfile->filepath, Filepath.c_str ());
	const char *p = FILEPATH.C_STR ();
	strcpy_s (Pfile->filename, p + filepath.find_last_of ("\") + 1);
Listfile.push_back (PFile);
	} void Csmtp::D eleteattachment (String &filepath)//delete attachment {list<fileinfo *>::iterator piter; for (Piter = Listfile.begin (); Piter!= listfile.end (); piter++) {if (strcmp (*piter)->filepath, Filepath.c_str ())
			= = 0) {FILEINFO *p = *piter;
			Listfile.remove (*piter);
			Delete p;
		Break } void Csmtp::D eleteallattachment ()/* Delete all Files */{for (list<fileinfo *>::iterator piter = Listfile.begin (); p
	Iter!= listfile.end ();)
		{FILEINFO *p = *piter;
		Piter = Listfile.erase (Piter);
	Delete p;

} void Csmtp::setsrvdomain (String &domain) {this->domain = domain;}

void Csmtp::setusername (String &user) {this->user = user;} void Csmtp::setpass (String &pass) {This->pass = pass;} void Csmtp::settargetemail (string &targetaddr) {thi S-&GT;TARGETADDR = TaRGETADDR;
	} void Csmtp::setemailtitle (String &title) {this->title = title;} void Csmtp::setcontent (String &content) {
this->content = content; } void Csmtp::setport (int port) {this->port = port;}

The test code is as follows:

main.cpp

#include "Smtp.h"
#include <iostream>
using namespace std;

int main ()
{

	csmtp smtp (								/*smtp port/
		"smtp.163.com",					/*SMTP server address * "
		it_is_just_a_" Test@163.com ",	* * Your email address * *"
		XXXXXXX ",					* * Email password/
		" it_is_just_a_test@126.com ",/	* Destination Email address * * "
		good!",							* * Theme *
		xxx classmate, hello. Please reply when you receive. "		* * * message body * *
		);
	/**
	//Add attachment note, \ must write \ \, because of the escape character
	string FilePath ("d:\\ course design report. doc");
	Smtp. AddAttachment (FilePath);
	SendEmail.cpp ";
	Smtp. AddAttachment (FilePath);

	int err;
	if (err = SMTP. SENDEMAIL_EX ())!= 0
	{
		if (err = = 1)
			cout << "Error 1: Due to network not unblocked, send failed!" << Endl;
		if (err = = 2)
			cout << "Error 2: Username error, please check!" << Endl;
		if (err = = 3)
			cout << "Error 3: User password error, please check!" << Endl;
		if (err = = 4)
			cout << "Error 4: Please check that the attachment directory is correct and that the file exists!" << Endl;
	}
	System ("pause");
	return 0;
}

Under VS2005, it is possible to have a Chinese-language catalogue or a Chinese name file not open, this time to resolve: the first sentence in two constructors plus: setlocale (lc_all, "chinese-simplified"), this sentence can be resolved.

In the VS2013 inside seemingly this program can run, Microsoft this wonderful flower. Do not say.

Please try not to use QQ mailbox landing, because I tried, seemingly not even on. QQ Mailbox server returned to tell you the requirements of a secure connection, with SSL what, Ah, QQ is a wonderful work.

Attach one of my projects: Https://github.com/lishuhuakai/Mail

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.