C + + implementation of sending the message body and its attachments

Source: Internet
Author: User
Tags base64 format message set socket

This code I spent a whole day to write, assuming reprint, please indicate the source, thank you!

The previous article has already talked about how to send the message body, the principle I will no longer narrate. To understand the students please come here to view!

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

e-mail attachments to send a lot of code can not be used, so I wrote a heart, directly encapsulated into a class, the need for students to directly call this class to send mail, pure C + + code. (In the VS2013 test the perfect pass!)

Don't say much nonsense. Directly on the code!

Smtp.h

#ifndef __smtp_h__//Avoid repeating include # define __smtp_h__#include <iostream> #include <list> #include <winsock2.h >using namespace Std;const int maxlen = 1024;const int max_file_len = 6000;static const char base64char[] = "Abcdefghij klmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/"; struct FILEINFO/* Used to log some information about a file */{char filename[128]; * * File name * /char filepath[256]; /* File absolute path */};class csmtp{public:csmtp (void); CSMTP (int port,string srvdomain,//smtpserver domain name string username,//usernamestring password,//passwordstring Targetemail,//Destination email address string emailtitle,//Subject string content//content);p ublic:~csmtp (void);p Ublic:int port;public:string Domain;string user;string pass;string targetaddr;string title;string content;/* in order to facilitate the inclusion of documents. Delete Files God horse's. Using the list container is most convenient, I believe everyone in the data structure has learned */list <fileinfo *> Listfile;public:char Buff[maxlen + 1];int Bufflen; Socket sockclient;//client sockets Public:bool createconn (); /* Create connection */bool Send (string &message), bool Recv (), void Formatemailhead (String &email),//Format message header to sendint Login (); bool Sendemailhead ();//Send message header message bool Sendtextbody ();    Send text message//bool sendattachment (); Send attachment int sendattachment_ex (); bool Sendend ();p ublic: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 2.username error caused by network error 3.password error 4. File does not exist 0. Success */ 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 with someone else's code, just, that's not the point, the point is I'm finished with a better mail sent client*/char* Csmtp::base64encode (char  const* origsigned, unsigned origlength) {unsigned char const* orig = (unsigned char const*) origsigned;  Bytes has the MSB setif (orig = = NULL) return null;unsigned const Numorig24bitvalues = Origlength/3;bool havepadding = Origlength > Numorig24bitvalues * 3;bool havePadding2 = origlength = numorig24bitvalues * 3 + 2;unsigned const numres Ultbytes = 4 * (numorig24bitvalues + havepadding); char* result = new Char[numresultbytes + 3]; Allow for trailing '/0 '//Map per full group of 3 input bytes to 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] &am P 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 (ha VEPADDING2) {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->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 emailTitle,string Content) {this->content = Content;this->port = Port;this->user = Username;this->pass = password;this-> 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 () {//Prepares the socket object for creation. Initialize the environment socket sockclient = socket (af_inet, sock_stream, 0); Set 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]);//Get SmtpServer IP address of the network byte order addrsrv.sin_family = Af_inet;addrsrv.sin_ Port = htons (port); int err = connect (sockclient, (sockaddr*) &amP;addrsrv, sizeof (SOCKADDR)); Send request to 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 ())//both receive and send {return 1;/*1 indicates send failed because of network error */}sendbuff.empty (); sendbuff = "AUTH login\r\n"; if (false = = Send (send Buff) | | false = = RECV ())//Request Login {return 1;/*1 indicates send failed because of network error */}sendbuff.empty (), int pos = user.find (' @ ', 0); sendbuff = user.substr (0 , POS); Get UsernamechAr *ecode;/* Here Incidentally, about the length function of the string class and the Strlen function in the C language difference, strlen the calculated lengths, only to the ' \ S ' character, and String::length () The function actually returns the size of the character array in the String class, and you can test it yourself. This is why I do not use String::length () for the following reasons */ecode = Base64Encode (Sendbuff.c_str (), strlen (Sendbuff.c_str ())), Sendbuff.empty ( ); Sendbuff = Ecode;sendbuff + = "\ r \ n";d elete[]ecode;if (false = = Send (Sendbuff) | | false = RECV ())//Send username and receive server The return {return 1;/* error code 1 indicates that the send failed because of a network error */}sendbuff.empty (); ecode = Base64Encode (Pass.c_str (), strlen (Pass.c_str ())); Sendbuff = Ecode;sendbuff + = "\ r \ n";d elete[]ecode;if (false = = Send (Sendbuff) | | false = = RECV ())//Send user password and receive server return {RE Turn 1; /* Error code 1 indicates that the send failed because of network error */}if (null! = STRSTR (Buff, "550")) {return 2;/* error code 2 means username error */}if (null! = STRSTR (Buff, "535") */* 535 is the return of authentication failed */{return 3;/* error code 3 means password error */}return 0;} BOOL Csmtp::sendemailhead ()//Send header message {string sendbuff;sendbuff = "Mail from: <" + user + ">\r\n"; if (false = = Send (s Endbuff) | | false = = Recv ()) {return false;/* indicates that the send failed because of a network error */}sendbuff.empty (); sendbuff = "RCPT to: < "+ targetaddr +" >\r\n "; if (false = = Send (Sendbuff) | | false = = RECV ()) {return false;/* Indicates send failed because of network error */}sendbuff.empty (); Sendbuff = "data\r\n"; if (false = = Send (Sendbuff) | | false = = RECV ()) {return false;//indicates send failed because of network error}sendbuff.empty (); Formatemailhead (Sendbuff); if (false = = Send (Sendbuff))//Do not call the receive function after sending the header, because you do not have the \r\n.\r\n end, the server think you did not finish the data, So no value is returned {return false;/* indicates that the send failed because of 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"; emai L + = "\ 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! = Listfile.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 indicates file open error */}char Filebuff[max_file_len];char *chsendbuff;memset (filebuff, 0, sizeof (filebuff)); */* file is transmitted 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);d Elete[]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 ()/* Sends the 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 return}if (false = = Sendemailhead ())//Send Email header message {return 1;/* error code 1 is due to network error */}if (fals E = = 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 means 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 (); PIter! = Listfile.end ();) {FILEINFO *p = *piter;piter = Listfile.erase (piter);d elete 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) {this->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;}

test code such as the following:

Main.cpp

#include "Smtp.h" #include <iostream>using namespace Std;int main () {csmtp Smtp (25,/*smtpport*/"smtp.163.com",/* SmtpServer address */"[email protected]",/* Your email address */"XXXXXXX",/* email password*/"[email protected]",/* destination e-mail address */"good!",/* Theme * * " xxx classmate, hello. Receive please reply! */* Message body */);/**//When adding attachments note that \ must be written \ \ Due to the escape character string FilePath ("d:\\ course design report. doc"); SMTP. AddAttachment (FilePath); *//* can also call CSMTP::D eleteattachment function to delete attachments, and other functions, self-worth file bar!*///filepath = "c:\\users\\ Li Yihu \ \ Desktop\\sendemail.cpp ";//smtp. AddAttachment (filePath); int err;if (err = SMTP. SENDEMAIL_EX ())! = 0) {if (err = = 1) cout << "Error 1: Send failed due to network not unblocked!" << endl;if (err = 2) cout << "Error 2:usern Ame error, please check! "<< endl;if (err = 3) cout <<" Error 3: User password error, please check! "<< endl;if (Err = 4) cout <<" error 4: Please check the attachment folder is correct, and the file exists! "<< Endl;} System ("pause"); return 0;}

Under VS2005, it is very likely that a Chinese-language folder or a Chinese name file will not open. This time the solution: the first sentence in the two constructors Plus: setlocale (lc_all, "chinese-simplified"); This sentence can be solved!

In VS2013 it seems that this program can execute. Microsoft this wonderful flower!

Do not say!

Please try not to use QQ mailbox landing, because I tried. I can't seem to even. QQ Mailbox server returned to tell you to ask for a secure connection, with SSL or something. Hey. QQ is also a wonderful flower.

Attach one of my project:https://github.com/lishuhuakai/mail


C + + implementation of sending the message body and its attachments

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.