ansh_kumar Ответов: 6

Отправка электронной почты с вложением с помощью libcurl


Я хочу отправить электронное письмо с вложением из c++ с помощью libcurl( http://curl.haxx.se/[^]).
Я могу успешно отправить электронное письмо с сервера gmail, но не знаю, как отправить его с вложением.
Код, который я использую, выглядит следующим образом:

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

#define FROM    "<xxxx@gmail.com>"
#define TO      "<xxxx@gmail.com>"

static const char *payload_text[] = {
  "To: " TO "\r\n",
  "From: " FROM "\r\n",
  "Subject: SMTP TLS example message\r\n",
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }

  data = payload_text[upload_ctx->lines_read];

  if(data) {
    size_t len = strlen(data);
    memcpy(ptr, data, len);
    upload_ctx->lines_read++;

    return len;
  }

  return 0;
}

int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct curl_slist *recipients = NULL;
  struct upload_status upload_ctx;

  upload_ctx.lines_read = 0;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_USERNAME, "xxxx");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "xxxx");
    curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
    curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
    curl_easy_setopt(curl, CURLOPT_CAINFO, "google.pem");
    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
    recipients = curl_slist_append(recipients, TO);
    //curl_easy_setopt(curl, CURLOPT_FILE, "edgE0DF.tmp"); 
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
    curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);

    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    curl_slist_free_all(recipients);

    curl_easy_cleanup(curl);
  }
  system("pause");
  return (int)res;
}


Любое предложение приветствуется.

6 Ответов

Рейтинг:
44

ansh_kumar

Приведенный ниже код использует Imagemagick++http://www.imagemagick.org/Magick++/[^] в base64 кодирования изображения.

#include <Magick++.h>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <string>

#define FROM    "<xxxx@gmail.com>"
#define TO      "<xxxx@gmail.com>"
#define FILENAME "pic.jpg"
 
static const int CHARS= 76;			//Sending 54 chararcters at a time with \r , \n and \0 it becomes 57 and its encoded length will be 76 by the formula string_length/3*4
static const int ADD_SIZE= 7;			// ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-ENCODING,CONETNT-DISPOSITION and \r\n
static const int SEND_BUF_SIZE= 54;
static char (*fileBuf)[CHARS] = NULL;
 
struct fileBuf_upload_status 
{
  int lines_read;
};
 
size_t read_file()
{
	Magick::Image img(FILENAME);
	Magick::Blob blob;
	img.write( &blob );
	std::string encoded_buf = blob.base64();
	
	size_t encoded_buf_len = encoded_buf.size();
	size_t len(0),buffer_size(0);
	int no_of_rows = (int)ceil((double)encoded_buf.size()/SEND_BUF_SIZE) ;
	int read(0);
	fileBuf = new char[ADD_SIZE + no_of_rows + 1][CHARS];	//Extra row for our special character to be used in conditional statements,here ""
											// ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-ENCODING,CONETNT-DISPOSITION and \r\n
 
	strcpy(fileBuf[len++],"To: " TO "\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;	// 1 for \0
	strcpy(fileBuf[len++],"From: " FROM "\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Subject: SMTP TLS example message\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Type: image/jpeg; name=\"" FILENAME "\"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Transfer-Encoding: base64\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Disposition: attachment; filename=\"" FILENAME "\"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	
	int pos = 0;
	std::string sub_encoded_buf;
	for (; len < no_of_rows + ADD_SIZE; ++len)
	{		
		if (pos*54 <= encoded_buf_len)
		{
			sub_encoded_buf = encoded_buf.substr(pos*54,54);
			pos++;
 		sub_encoded_buf += "\r\n";
		memcpy(fileBuf[len],sub_encoded_buf.c_str(),sub_encoded_buf.size());
                buffer_size += sub_encoded_buf.size() ;	// 1 for \0
		}
	}
        strcpy(fileBuf[len],"");

// The following code prints the structure of the email being sent.
//	
//	for (int i=0;i<no_of_rows + ADD_SIZE;++i)
//	{
//		printf("%s",fileBuf[i]);
//	}
	return buffer_size;
}
 

static size_t fileBuf_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
	struct fileBuf_upload_status *upload_ctx = (struct fileBuf_upload_status *)userp;
	const char *fdata;
 
	if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) 
	{
		return 0;
	}
 
	fdata = fileBuf[upload_ctx->lines_read];
 
	if(strcmp(fdata,"")) 
	{
		size_t len = strlen(fdata);
		memcpy(ptr, fdata, len);
		upload_ctx->lines_read++;
		return len;
	}
	return 0;
}
 
int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct curl_slist *recipients = NULL;
  struct fileBuf_upload_status file_upload_ctx;
  size_t file_size(0);
 
  file_upload_ctx.lines_read = 0;
 
  curl = curl_easy_init();
  file_size = read_file();
  if(curl) 
  {
    curl_easy_setopt(curl, CURLOPT_USERNAME, "xxxx");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "xxxx");
    curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
    curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
    //curl_easy_setopt(curl, CURLOPT_CAINFO, "google.pem");
    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
    recipients = curl_slist_append(recipients, TO);
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
 
	curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size); 
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, fileBuf_source);
    curl_easy_setopt(curl, CURLOPT_READDATA, &file_upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
 
    res = curl_easy_perform(curl);
 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
 
    curl_slist_free_all(recipients);
 
    curl_easy_cleanup(curl);
  }
  delete[] fileBuf;
  return (int)res;
}


Используйте следующую команду для компиляции
$ IM_CXXFLAGS=$(Magick++-config --cxxflags)
$ IM_LDFLAGS=$(Magick++-config --ldflags)
$ g++ $IM_CXXFLAGS $IM_LDFLAGS main.cpp -lcurl


deepak2431

Я не могу запустить этот код. Получение справочной ошибки для библиотеки магии. Можете ли вы помочь мне, пожалуйста?

Рейтинг:
32

ansh_kumar

После очень долгих наблюдений и экспериментов я наконец нашел решение.
Это будет слишком долго, чтобы дать подробную информацию о том, как этот код работает, поэтому я просто помещаю рабочий код:

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <math.h>

#define FROM    "<xxxx@gmail.com>"
#define TO      "<xxxx@gmail.com>"
#define FILENAME "pic.jpg"
 
static const int CHARS= 76;			//Sending 54 chararcters at a time with \r , \n and \0 it becomes 57 
static const int ADD_SIZE= 7;			// ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-ENCODING,CONETNT-DISPOSITION and \r\n
static const int SEND_BUF_SIZE= 54;
static char (*fileBuf)[CHARS] = NULL;
static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
static void encodeblock( char *in, char *out, int len )
{
    out[0] = (unsigned char) b64_table[ (int)(in[0] >> 2) ];
    out[1] = (unsigned char) b64_table[ (int)(((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) ];
    out[2] = (unsigned char) (len > 1 ? b64_table[ (int)(((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) ] : '=');
    out[3] = (unsigned char) (len > 2 ? b64_table[ (int)(in[2] & 0x3f) ] : '=');
}

void base64_encode(char *input_buf, char *output_buf)
{
	char in[3], out[4];
	size_t len = strlen(input_buf);
	
	*output_buf = 0;
	for (size_t i=0; i<len; )
	{
		int buf3_len = 0;
		for (int j=0; j<3; ++j)
		{
			in[j] = input_buf[i++];
			if (i > len)
				in[j] = 0;
			else
				buf3_len++;
		}
		if (len>0)
		{
			encodeblock(in,out,buf3_len);
			strncat(output_buf, out, 4);
		}
	}
}
 
struct fileBuf_upload_status 
{
  int lines_read;
};
 
size_t read_file()
{
	FILE* hFile=NULL;
	size_t fileSize(0),len(0),buffer_size(0);
 
	//opening the file
	hFile = fopen(FILENAME,"rb");
	if (hFile == NULL)
		throw "File Does not exist.";
 
	//get file size
	fseek(hFile,0,SEEK_END);
	fileSize = ftell(hFile);
	fseek(hFile,0,SEEK_SET);
 
	//Checking file size
	if(fileSize > 1*1024)
	{}
 
	int no_of_rows = fileSize/SEND_BUF_SIZE + 1;
	int read(0);
	fileBuf = new char[ADD_SIZE + no_of_rows + 1][CHARS];	//Extra row for our special character to be used in conditional statements,here ""
											// ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-ENCODING,CONETNT-DISPOSITION and \r\n
 
	strcpy(fileBuf[len++],"To: " TO "\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;	// 1 for \0
	strcpy(fileBuf[len++],"From: " FROM "\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Subject: SMTP TLS example message\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Type: application/x-msdownload; name=\"" FILENAME "\"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Transfer-Encoding: base64\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"Content-Disposition: attachment; filename=\"" FILENAME "\"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
	strcpy(fileBuf[len++],"\r\n");
	buffer_size += strlen(fileBuf[len-1]) + 1;
 
	char* temp_buf = new char[SEND_BUF_SIZE + 4];	//taking extra size of 4 bytes
	size_t e_size = ceil(SEND_BUF_SIZE/3)*4 + 4;
	char* encoded_buf = new char[e_size];
	*encoded_buf = 0;
	
	for (; len < no_of_rows + ADD_SIZE; ++len)
	{
		read = fread(temp_buf,sizeof(char),SEND_BUF_SIZE,hFile);
		temp_buf[read] ='\0';
		base64_encode(temp_buf,encoded_buf);
		strcat(encoded_buf,"\r\n");
		memcpy(fileBuf[len],encoded_buf,strlen(encoded_buf)+1);
                buffer_size += strlen(encoded_buf) + 1;	// 1 for \0
	}
	strcpy(fileBuf[len],"");
        delete[] temp_buf;
	delete[] encoded_buf;
	return buffer_size;
}
 
 /*
  The fileBuf_source() is a function which CURL calls when it need to obtain data that will be uploaded to the server. 
  Imagine that fileBuf_source() is something similar to fread(). When called it performs any voodoo-mumbo-jumbo that is needed, 
  but in the end uploadable data must be stored in *ptr buffer, which is curl's internal buffer. For your in-memory buffer 
  memcpy() will do just fine as body of fileBuf_source(), so you don't need real fread() at all.

size * nmemb tells you how big buffer curl has reserved for a single chunk of data. The last void* is a pointer which was 
set by CURLOPT_READDATA option - it's a do-what-ever-you-need-with-it kind of pointer, so it can point to a structure 
containing data which you're uploading and a some additional info e.g. current progress.
  */
static size_t fileBuf_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
	struct fileBuf_upload_status *upload_ctx = (struct fileBuf_upload_status *)userp;
	const char *fdata;
 
	if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) 
	{
		return 0;
	}
 
	fdata = fileBuf[upload_ctx->lines_read];
 
	if(strcmp(fdata,"")) 
	{
		size_t len = strlen(fdata);
		memcpy(ptr, fdata, len);
		upload_ctx->lines_read++;
		return len;
	}
	return 0;
}
 
int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct curl_slist *recipients = NULL;
  struct fileBuf_upload_status file_upload_ctx;
  size_t file_size(0);
 
  file_upload_ctx.lines_read = 0;
 
  curl = curl_easy_init();
  file_size = read_file();
  if(curl) 
  {
    curl_easy_setopt(curl, CURLOPT_USERNAME, "xxxx");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "xxxx");
    curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
    curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
    //curl_easy_setopt(curl, CURLOPT_CAINFO, "google.pem");
    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
    recipients = curl_slist_append(recipients, TO);
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
 
	curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size); 
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, fileBuf_source);
    curl_easy_setopt(curl, CURLOPT_READDATA, &file_upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
 
    res = curl_easy_perform(curl);
 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
 
    curl_slist_free_all(recipients);
 
    curl_easy_cleanup(curl);
  }
  delete[] fileBuf;
  return (int)res;
}


Member 11248359

Привет, могу я спросить, возможно ли прикрепление изображения для этого кода?

Я пробовал прикреплять изображения разных форматов (.jpg, .png). Ему действительно удалось отправить вложение с изображением. Но приемник не может открыть изображение. Надеюсь, вы сможете помочь. Спасибо

ansh_kumar

Не могли бы вы сказать мне размер файла, который вы пытаетесь отправить, возможно, пришлите мне файл изображения, который вы пытаетесь отправить по электронной почте.

Member 11248359

Я попытался отправить изображение, которое составляет около 40 КБ. Я попробовал использовать любые изображения, которые я сохраняю из google. Но это не работает.

ansh_kumar

На самом деле этот код предназначен только для отправки текстового файла, но я могу изменить его, чтобы отправить JPG-файл. Подожди до завтра, я приду с решением. :)

ansh_kumar

Я изменил код, чтобы отправить файл jpeg. Смотрите мое следующее Решение ниже.

Tran Toan

Привет @ansh_kumar!
Я тестировал код в части решения 2.
Но когда я отправляю текстовый файл, я могу получить и открыть его. Но что касается файла изображения, то я не могу открыть его, когда получил его по почте назначения.
Не могли бы вы помочь мне кое в чем?
Спасибо!!!

ansh_kumar

Можете ли вы дать мне файл, который вы пытаетесь отправить ?

Tran Toan

Спасибо за ваш ответ.
Я не знаю вашей электронной почты, какая у вас почта?
Это срочно для меня.
Спасибо

Tran Toan

@ansh_kumar
Я послал вам свое досье. Пожалуйста, проверьте это.
Спасибо!!!

ansh_kumar

Вы используете неправильный код.
Для отправки файла изображения используйте код над ним, который использует Imagemagick++.

Tran Toan

Проблема в том, что я уже пробовал скачать magick++.h раньше. Но я не могу найти доступную магию++. Вы можете прислать мне это?

Спасибо!!!

ansh_kumar

Я уже предоставил ссылку на официальный сайт. Сайт содержит исходный код и инструкции.

XKT

привет, @ansh_kumar, не могли бы вы дать мне статический lib-файл libcurl?

ansh_kumar

Какой у тебя адрес электронной почты?

XKT

xktproject@126.com
Так много спасибо.
И могу ли я отправить вложение gmail без магии?

Member 11615836

Проверьте решение 7, я исправил код для отправки любого типа файлов любого размера (большие файлы будут кодироваться дольше, кроме того, я не уверен, что существует ограничение на максимальный размер файла при отправке через SMTP)... Обновленный код требует только libCurl, он имеет свою собственную функцию кодирования Base64. Я надеюсь, что это поможет всем.

-CellToolz

dmaxime

Поскольку формат base64 также используется для передачи двоичных файлов, если вы хотите правильно запустить функцию encodeblock, вы должны рассматривать байты в буфере "in" как unsigned char, в противном случае, когда значение байта больше или равно 0x80, вы будете обращаться к таблице с отрицательным индексом. Функция base64_encode очень полезна для преобразования строк в base64, но если вы хотите кодировать двоичные данные, вы можете использовать такую функцию:

пустота bin_base64_encode(типа char *in_b, типа char *out_b, инт in_len)
{
статический int i, l;
для(i = 0, l = in_len / 3; i < l; i++)
encodeblock(&in_b[i * 3], &out_b[i * 4], 3);
if(i * 3 < in_len)
encodeblock(&in_b[i * 3], &out_b[i * 4], in_len - (i * 3));
}

С уважением.

Рейтинг:
2

Member 11615836

Я исправил этот код, чтобы вы могли отправлять вложения любого типа файлов. У меня нет проблем с отправкой JPG с разрешением 165kb @ 1280x1024. Я скомпилировал это в MSVS2010. Этот код нуждается только в библиотеке libCurl, у него есть своя собственная функция кодирования Base64, оно не требуется магия++.


/* C++ TLS SMTP eMail File Send example using libCurl. This code demonstrates how to use libCurl to connect to GMail's TLS SMTP
   Server and send an eMail with a Base64 encoded attachment. I've used Microsoft Visual Studio 2010 to compile this code. You'll
   need to download and install the C++ libCurl library for this to compile correctly. I've uploaded a ready to use compiled cURL
   library here: https://docs.google.com/uc?id=0BzOJ0-XuaQSTU3RHQkRfbVpmcnM&export=download Download this ZIP and extract the
   contents anywhere on your computer. Quick How-To on using MSVS2010 to compile this:
   1. Open Visual Studio 2010, click File -> New -> Project.
   2. On the left side select Visual C++ -> General -> Empty Project (Type in a Name and click OK)
   3. In the Solution Explorer window Right Click 'Source Files' folder and select Add -> New Item
   4. Select 'C++ File (.cpp)' (Type in a Name and click OK)
   5. Copy and Paste this code into the newly created .cpp file and Click Into the int Main() function
   6. Click Project menu -> 'ProjectName Properties' (at the bottom)
   7. On the left select Configuration Properties -> VC++ Directories
   8. On the Right select Include Directories and add libCurl's include directory
   9. On the Right select Library Directories and add libCurl's Library directory (Static-Debug folder)
  10. On the left select C/C++ -> Preprocessor and add 'CURL_STATICLIB' (no quotes) to the Preprocessor Definitions
  11. Now you are ready to Compile, Click Build -> Build Solution
*/
 
#include <iostream>
#include <conio.h>
#include <curl/curl.h>
 
#ifdef _DEBUG
        #pragma comment(lib, "libcurl_a_debug.lib") //cURL Debug build
#else
        #pragma comment(lib, "libcurl_a.lib")
#endif
 
#pragma warning(disable: 4996)  //Disable Function or Variable may be unsafe warning
 
#define FROM    "<xxxxx@gmail.com>"
#define TO      "<xxxxx@gmail.com>"
#define FILENAME "c:/1.rar"
 
static const int CHARS= 76;     //Sending 54 chararcters at a time with \r , \n and \0 it becomes 57
static const int ADD_SIZE= 7;   // ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-ENCODING,CONETNT-DISPOSITION and \r\n
static const int SEND_BUF_SIZE= 54;
static char (*fileBuf)[CHARS] = NULL;
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
using namespace std;
 
bool LARGEFILE = false; /*For Percent*/
int status = 0;   /*For Percent*/
int percent2 = 0; /*For Percent*/
int percent3 = 0; /*For Percent*/
int percent4 = 0; /*For Percent*/
int percent5 = 0; /*For Percent*/
void LargeFilePercent(int rowcount)
{
        //This is for displaying the percentage
        //while encoding larger files
        int percent = rowcount/100;
 
        if(LARGEFILE == true) {
                status++;
                percent2++;
                if(percent2 == 18) {
                        percent3++;
                        percent2 = 0;
                }
                if(percent3 == percent){
                        percent4++;
                        percent3 = 0;
                }
                if(percent4 == 10){
                        system("cls");
                        cout << "Larger Files take longer to encode, Please be patient." << endl
                             << "Otherwise push X to exit program now." << endl << endl
                             << "(Push Anykey to Continue)" << endl
                             << endl << "Encoding " FILENAME " please be patient..." << endl;
                        cout << percent5 << "%";
                        percent5 += 10;
                        percent4 = 0;
                }
                if(status == 10000) {
                        if(percent5 == 0){cout << " 0%"; percent5 = 10;}
                        cout << ".";
                        status = 0;
                }
        }
}
 
void encodeblock(unsigned char in[3], unsigned char out[4], int len)
{
    out[0] = cb64[ in[0] >> 2 ];
    out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
    out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
    out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}
 
void encode(FILE *infile, unsigned char *output_buf, int rowcount/*For Percent*/)
{
    unsigned char in[3], out[4];
        int i, len;
        *output_buf = 0;
 
    while(!feof(infile)) {
        len = 0;
        for(i = 0; i < 3; i++) {
            in[i] = (unsigned char) getc(infile);
            if(!feof(infile) ) {
                len++;
            }
            else {
                in[i] = 0;
            }
        }
        if(len) {
            encodeblock(in, out, len);
            strncat((char*)output_buf, (char*)out, 4);
        }
            LargeFilePercent(rowcount); //Display encoded file percent /*For Percent*/
        }
}
 
 
struct fileBuf_upload_status
{
  int lines_read;
};
 
size_t read_file()
{
        FILE* hFile=NULL;
        size_t fileSize(0),len(0),buffer_size(0);
        char key = ' ';
 
        //Open the file and make sure it exsits
        hFile = fopen(FILENAME,"rb");
        if(!hFile) {
                cout << "File not found!!!" << endl;
                _getch();
                exit (EXIT_FAILURE);
        }
 
        //Get filesize
        fseek(hFile,0,SEEK_END);
        fileSize = ftell(hFile);
        fseek(hFile,0,SEEK_SET);
   
        //Check Filesize, if larger then 256kb prompt user
        if(fileSize > 256000/*bytes*/){
                cout << "Larger Files take longer to encode, Please be patient." << endl
                     << "Otherwise push X to exit program now." << endl << endl
                     << "(Push Anykey to Continue)" << endl;
                key = _getch();
                if(tolower(key) == 'x')
                        exit (EXIT_SUCCESS);
                LARGEFILE = true; /*For Percent*/
        }
        cout << endl << "Encoding " FILENAME " please be patient..." << endl;
 
        //Calculate the number of rows in Base64 encoded string
        //also calculate the size of the new char to be created
        //for the base64 encode string
        int no_of_rows = fileSize/SEND_BUF_SIZE + 1;
        int charsize = (no_of_rows*72)+(no_of_rows*2);
 
        //Base64 encode image and create encoded_buf string
        unsigned char* b64encode = new unsigned char[charsize];
        *b64encode = 0;
        encode(hFile, b64encode, no_of_rows /*For Percent*/);
        string encoded_buf = (char*)b64encode;
 
        if(LARGEFILE == true) cout << endl << endl; /*For Percent*/
 
        //Create structure of email to be sent
        fileBuf = new char[ADD_SIZE + no_of_rows][CHARS];  //ADD_SIZE for TO,FROM,SUBJECT,CONTENT-TYPE,CONTENT-TRANSFER-
                                                           //ENCODING,CONETNT-DISPOSITION and \r\n
        strcpy(fileBuf[len++],"To: " TO "\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"From: " FROM "\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"Subject: SMTP TLS example message\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"Content-Type: application/x-msdownload; name=\"" FILENAME "\"\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"Content-Transfer-Encoding: base64\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"Content-Disposition: attachment; filename=\"" FILENAME "\"\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"\r\n");
        buffer_size += strlen(fileBuf[len-1]);
   
        //This part attaches the Base64 encoded string and
        //sets the Base64 linesize to 72 characters + \r\n
        int pos = 0;
        string sub_encoded_buf;
        for(int i = 0; i <= no_of_rows-1; i++)
        {
                sub_encoded_buf = encoded_buf.substr(pos*72,72);  //Reads 72 characters at a time
                sub_encoded_buf += "\r\n";                        //and appends \r\n at the end
                strcpy(fileBuf[len++], sub_encoded_buf.c_str());  //copy the 72 characters & \r\n to email
                buffer_size += sub_encoded_buf.size();            //now increase the buffer_size  
                pos++;                                            //finally increase pos by 1
        }
//////////////////////////////////////////////////////////////////////
// The following code prints the structure of the email being sent.//
//    printf("Images Base64 encoded string:\n\n\t\t\t std::string" //
//         "encoded_buf\n%s\n",encoded_buf.c_str());               //
//    printf("\n\t\t\tStructure of Email being sent:\n");          //
//      for (int i=0;i<no_of_rows + ADD_SIZE;++i){                 //
//            printf("%s",fileBuf[i]); }                           //
//      printf("\nbuffer size: %d\n",buffer_size);                 //
/////////////////////////////////////////////////////////////////////
//    /* Push X to Exit the program after viewing                  //
//       the structure of the email */                             //
//    printf("Push X to exit program now, otherwise continue\n");  //
//       key = _getch();                                           //
//       if(tolower(key) == 'x')   


CHill60

Всего на полтора года опоздал с тем, что выглядит как спам

Member 11615836

спам лол... Ну, а 2 решения выше этого оба не очень хорошо работали. По крайней мере, с моим решением вы действительно можете отправлять вложения любого типа и размера. Я решил опубликовать его, чтобы помочь другим, я знаю, что это опоздание на полтора года, но лучше поздно, чем никогда, верно? Я действительно не хотел, чтобы это было спамом, код действительно работает сейчас. Я надеюсь, что это поможет кому-то, кроме меня.

CHill60

С правками это больше не выглядит спамом. Я согласен, что это добавляет ценности

ansh_kumar

Работает ли код, когда вы компилируете его как релизную версию??

Member 11615836

Да, кажется, он отлично работает для меня, когда я компилирую его как релиз. Я был в состоянии, чтобы отправить файлы любого размера/типа. Дайте мне знать, если у вас возникнут какие-либо проблемы...

ansh_kumar

Метод base64, который вы используете, такой же, как и в решении 2. Кроме того, no_of_rows в цикле for В read_file вычисляется до кодирования файла, тогда как он должен быть вычислен после кодирования файла, чтобы весь закодированный текст был помещен в fileBuf. См. решение 3, как оно вычисляется после кодирования файла. Я думаю, что вам повезло с выбранным файлом.

Member 11615836

No luck here, it works with every file I've thrown at it regardless of type or size. At 72 characters per line (b64 encoded linesize) you can calculate the number of rows by dividing the filesize by 54 + 1. In solution 7 the number of rows needs to be calculated beforehand so you can determine how large to allocate the b64encode buffer before loading it with the encoded text. The only reason I pass no_of_rows to the encode function is for displaying the encoded file percentage. I've checked to make sure all the encoded text is properly placed into fileBuf. Solution 7 works flawlessly, I've tested it thoroughly... Actually compare it to the other solutions, there are key differences.

the1russ

Привет,
Я смог изменить ваш пример, чтобы включить несколько вложений в электронное письмо, но пытался сделать это быстрее, но без особого успеха. У меня есть пара вопросов…

1. Что касается SEND_BUF_SIZE = 54, то откуда берется “54”? Я пробовал большие числа, и рутина намного быстрее до самого конца, когда она выходит из строя.

2. при вычислении размера символа, используемого для кодированной строки base64, откуда берется число “72”? charsize = (no_of_rows*72)+(no_of_rows*2);

the1russ

не берите в голову. Я вижу, что 72-это размер строки в кодировке b64, и только что выяснил, что 72 происходит от 54*(4/3). 4/3 - это расширение кодированного двоичного кода.

Member 11099894

Привет, действительно ли нужно кодировать в base64?

Может ли кто-нибудь помочь мне отправить электронное письмо с текстом, а также вложением.

Этот код не может включать текст.

Пожалуйста, помогите мне как можно скорее..

А также помогите мне с тем, как отправить несколько вложений...!!!

Спасибо!!!

Lieven Samijn

Привет, ты нашел ответ на свой вопрос? Я смотрю точно так же (электронная почта с 5 jpg-изображениями, как att. до сих пор, используя этот пример, я могу отправить 1 изображение, но не могу узнать, как это работает, чтобы отправить 5 изображений в 1 письме. повтор действительно оценили.

Member 11134219

Я получаю проблему при компиляции вышеуказанного кода, получая фатальную ошибку: conio.h: нет такого файла или каталога #include <conio.h> кто-нибудь скажет мне, почему это так? и как это исправить?

ansh_kumar

Не включайте его. Его больше не существует.

Member 11134219

можем ли мы сделать TO,FROM,CC динамическими?

ansh_kumar

Конечно, можешь. Просто измените код соответствующим образом.

Member 11134219

можете ли вы помочь сделать его динамичным? Я попытался сделать это, но не смог сделать изменения.*Payload_text[] принимает только константу, которую я пытался предоставить в строке, но это не работает.

ansh_kumar

Поместите scanf перед `strcpy(fileBuf[len++],"To:" TO "\r\n");` теперь объедините две строки.

EdwardX2

Член 11615836 или кто-нибудь еще,
Я хотел бы использовать решение 7 для отправки PDF-файла, но у него нет тела сообщения.

Добавление строк в поле "создать структуру отправляемой электронной почты" приводит к ошибке.

Как я могу добавить текстовое сообщение?

Member 13274757

Вы нашли способ добавить сообщение ?

Рейтинг:
1

Member 11134219

Для динамической отправки электронной почты вы можете использовать следующий код c++ :

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <cstdlib>
#include <iostream>
#include <cstring>


	int flag=0;
	std::string TO;
	std::string FROM;
	std::string CC;
	std::string Date;
	std::string Message;
	

struct upload_status 
{
  int lines_read;
};

 size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
	
		
		std::string email;
		
		

	if(flag<1)
	{
	
		time_t rawtime;
		struct tm * timeinfo;

		time ( &rawtime );
		timeinfo = localtime ( &rawtime );
		std::string today = asctime (timeinfo);
		
		email ="Date: "+today+" \r\n"+"To: "+TO+"\r\n"+"From:"+FROM+"\r\n"+		 "Cc: "+CC+" \r\n"+		 "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"+		 "rfcpedant.example.org>\r\n"+		 "Subject: Sample subject\r\n"+		 "\r\n"+		 "Dear "+Message+" \r\n"+		r\n"+		 "\r\n"+		 "\r\n"+		 "This is a computer generated email. DO NOT REPLY to this email.\r\n";		
		 
		  struct upload_status *upload_ctx = (struct upload_status *)userp;
		   char *data;

		  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
			return 0;
		  }		  
				
				data = &email[upload_ctx->lines_read];
					  				
				  if(data) 
				  {					  
					size_t len = strlen(data);					
					memcpy(ptr, data, len);					
					upload_ctx->lines_read++;
					flag++;
					return len;
				  } 
	  }
		 
	return 0;
}

int main(void)
{
		CURL *curl;
		CURLcode res = CURLE_OK;
		struct curl_slist *recipients = NULL;
		struct upload_status upload_ctx;

		upload_ctx.lines_read = 0;

		TO = "xxx.xxx@gmail.com"; 
		FROM = "xxx.xxx@gmail.com"; 
		CC = "xxx.xxx@gmail.com"; 
    	Message = "Hi whats up?"; 
		 
		
		curl = curl_easy_init();
		if(curl) 
		{
	   
			curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com");
			
			
			curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM.c_str());
			recipients = curl_slist_append(recipients, TO.c_str());
			recipients = curl_slist_append(recipients, CC.c_str());
			curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);

			curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
			curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
			curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

			res = curl_easy_perform(curl);

			if(res != CURLE_OK)
			fprintf(stderr, "curl_easy_perform() failed: %s\n",
				  curl_easy_strerror(res));

			curl_slist_free_all(recipients);

			curl_easy_cleanup(curl);
		}

		  return (int)res;
}




Для запуска этой программы необходимо установить библиотеку libcurl в вашей системе.
Вы просто можете скомпилировать и запустить эту программу с помощью следующей команды:
comipile:g++ TestSMTP.cpp -lcurl
Запуск: ./а.из


Рейтинг:
1

perosoft

<pre>
// ---------------------------------------------------------
// Send text + n files attached
// 
// command line compile
//
// g++ -Wall -fexceptions -Wno-write-strings -DCURL_STATICLIB -I/usr/local/include -g  -c send_email.cpp -o send_email.o
// g++  -o send_email send_email.o  -lgthread-2.0 -pthread -lglib-2.0 -L/usr/local/lib -lcurl -lssh2 -lssl -lcrypto
//
// ---------------------------------------------------------



#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <curl/curl.h>

using namespace std;

#define __FILENAME 100
#define __BUFSIZ   512

static const int CHARS               = 256;  
static const int SEND_BUF_SIZE       = 54;
static       char (*fileBuf)[CHARS]  = NULL;
static const char cb64[]             ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


#define __MAIL_BUFSIZ 65536
typedef struct sMailFile sMAILFILE, *psMAILFILE;
struct sMailFile {
   FILE *pIn;
   char  szMailFile[ __FILENAME + 1 ];
   char  szBuffer  [ __BUFSIZ   + 1 ];
};

typedef class cSendMail cSENDMAIL, *pcSENDMAIL;
class cSendMail {
protected:
   char       *pszMailBuffer;
   psMAILFILE  psFile;
public:
   cSendMail( bool *pbInitStatus );
  ~cSendMail( void );

   char * MailBuffer( void ) {
      return( &pszMailBuffer[ 0 ] );
   }

   int SendMail( char *pszFrom,
                 char *pszPassword,
                 char *pszSMTP,
                 char *pszSender,
                 char *pszMailTo,
                 char *pszSubject,
                 char *pszText ... );
};

cSENDMAIL::cSendMail( bool *pbInitStatus ) {
   pszMailBuffer = NULL;
   psFile        = NULL;
   if (( pszMailBuffer = ( char * )malloc( __MAIL_BUFSIZ )) == NULL ) {
      *pbInitStatus = 0;
      return;
   }
   if (( psFile = ( psMAILFILE )malloc( sizeof( sMAILFILE ))) == NULL ) {
      *pbInitStatus = 0;
      return;
   }
   psFile->pIn = NULL;
   strcpy( psFile->szMailFile, "mail.txt" );
} // ***** Constructor cSENDMAIL::cSendMail ***** //

cSENDMAIL::~cSendMail( void ) {
   if ( pszMailBuffer != NULL ) free( pszMailBuffer );
   if ( psFile != NULL ) free( psFile );
} // ***** Destructor cSENDMAIL::cSendMail ***** //

static size_t my_payload_source( void   *ptr,
                                 size_t  size,
                                 size_t  nmemb,
                                 void   *userp ) {
  psMAILFILE psMailFile = ( psMAILFILE )userp;

  if ( psMailFile->pIn == NULL ) {
     if (( psMailFile->pIn = fopen( psMailFile->szMailFile, "rt" )) == NULL )
        return( 0 );
  }
  if ( fgets( psMailFile->szBuffer, __BUFSIZ, psMailFile->pIn ) != NULL ) {
     size_t len = strlen( psMailFile->szBuffer );

     memcpy( ptr, psMailFile->szBuffer, len );
     return( len );
  }
  fclose( psMailFile->pIn );
  return( 0 );
}

static void encodeblock( unsigned char in[ 3 ],
                         unsigned char out[ 4 ],
                         int len ) {
   out[0] = cb64[ in[0] >> 2 ];
   out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
   out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
   out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}

static void encode(          FILE *infile,
                    unsigned char *output_buf,
                             int rowcount ) {
    unsigned  char in[3], out[4];
              int i, len;
             *output_buf = 0;

    while( !feof( infile )) {
       len = 0;
       for ( i = 0; i < 3; i++ ) {
          in[i] = (unsigned char) getc(infile);
          if ( !feof( infile )) {
             len++;
          } else {
             in[i] = 0;
          }
      }
      if ( len ) {
         encodeblock(in, out, len);
         strncat((char*)output_buf, (char*)out, 4);
      }
   }
}

int cSENDMAIL::SendMail( char *pszFrom,
                         char *pszPassword,
                         char *pszSMTP,
                         char *pszSender,
                         char *pszMailTo,
                         char *pszSubject,
                         char *pszText ... ) {
            bool         bError = 0;
            CURL        *curl;
            CURLcode     res       = CURLE_OK;
     struct curl_slist *recipients = NULL;
            char        szFrom[ __BUFSIZ + 1 ];
            char        szTo  [ __BUFSIZ + 1 ];
            va_list     ArgsPointer;
            char       *file_name;
            FILE       *hFile;
            FILE       *hOut;
            size_t      fileSize(0);
            size_t      len(0);
            size_t      buffer_size(0);
            int         no_of_rows;
            int         charsize;
            int         j;
   unsigned char       *b64encode;
            string      encoded_buf;
            int         pos;
            string      sub_encoded_buf;

   va_start( ArgsPointer, pszText );
   file_name = ( char * )va_arg( ArgsPointer, char * );

   sprintf( szFrom, "<%s>", pszFrom );
   sprintf( szTo  , "<%s>", pszMailTo );

   hOut = fopen( psFile->szMailFile, "wt" );
   fprintf( hOut, "To: <%s>%s\r\n", pszMailTo, pszSender );
   fprintf( hOut, "From: <%s>\r\n", pszFrom );
   fprintf( hOut, "Sender_Email: <%s>\r\n", pszFrom );
   fprintf( hOut, "Return-Path: <%s>\r\n", pszFrom );
   fprintf( hOut, "Reply-To: <%s>\r\n", pszFrom );
   fprintf( hOut, "Subject: %s\r\n", pszSubject );
   if ( file_name != NULL ) {
      fprintf( hOut, "Content-Type: multipart/mixed; boundary=\"MyBoundaryString\"\r\n" );
      fprintf( hOut, "\r\n" );
      fprintf( hOut, "--MyBoundaryString\r\n" );
      fprintf( hOut, "Content-Type: text/plain; charset=UTF-8\r\n" );
      fprintf( hOut, "\r\n" );
   } else {
      fprintf( hOut, "Content-Type: text/plain; charset=UTF-8\r\n" );
      fprintf( hOut, "\r\n" );
   }
   fprintf( hOut, "%s\r\n", pszText );
   if ( file_name != NULL )
      do {
         fileSize    = 0;
         len         = 0;
         buffer_size = 0;

         fprintf( hOut, "--MyBoundaryString\r\n" );
         fprintf( hOut, "Content-Type: application/x-msdownload; name=\"%s\"\r\n", file_name );
         fprintf( hOut, "Content-Transfer-Encoding: base64\r\n" );
         fprintf( hOut, "Content-Disposition: attachment; filename=\"%s\"\r\n", file_name );
         fprintf( hOut, "\r\n" );

         if (( hFile = fopen( file_name, "rb" )) != NULL ) {
            fseek( hFile, 0, SEEK_END );
            fileSize = +ftell( hFile );
            fseek( hFile, 0, SEEK_SET );

            no_of_rows = fileSize / SEND_BUF_SIZE + 1;
            charsize   = ( no_of_rows*72 ) + ( no_of_rows*2 );
            b64encode  = new unsigned char[charsize];
            *b64encode = 0;
            encode( hFile, b64encode, no_of_rows );
            encoded_buf = ( char * )b64encode;

            fileBuf = new char[no_of_rows][CHARS];

            pos = 0;
            for ( j = 0; j <= no_of_rows - 1; j++ )  {
               sub_encoded_buf = encoded_buf.substr( pos*72, 72 );
               sub_encoded_buf += "\r\n";
               strcpy(fileBuf [len++ ], sub_encoded_buf.c_str());
               buffer_size += sub_encoded_buf.size();
               pos++;
            }
            for ( j = 0; j < no_of_rows; j++ )
               fprintf( hOut, "%s", fileBuf[ j ] );

            delete[] fileBuf;
            delete[] b64encode;
         } else {
            printf( "File not found: %s\n", file_name );
            bError = 1;
            break;
         }
      } while (( file_name = ( char * )va_arg( ArgsPointer, char * )) != NULL );
   va_end( ArgsPointer );
   if ( file_name != NULL )
      fprintf( hOut, "--MyBoundaryString--\r\n" );
   fclose( hOut );
   if ( !bError ) {
      curl = curl_easy_init();
      if(curl) {
         curl_easy_setopt(curl, CURLOPT_USERNAME, pszFrom );
         curl_easy_setopt(curl, CURLOPT_PASSWORD, pszPassword );
         curl_easy_setopt(curl, CURLOPT_URL, pszSMTP );
         curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
         //    curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");
         curl_easy_setopt(curl, CURLOPT_MAIL_FROM, szFrom );
         recipients = curl_slist_append( recipients, szTo );
         curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients );
         curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_payload_source);
         curl_easy_setopt(curl, CURLOPT_READDATA, psFile );
         curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
         res = curl_easy_perform(curl);
         if(res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror( res ));
         curl_slist_free_all(recipients);
      }
      curl_easy_cleanup(curl);
   }
   return (int)res;
} // ***** Function cSENDMAIL::SendMail ***** //

char *pszFrom     = "sender_email@gmail.com";
char *pszPassword = "sender_pasword";
char *pszSMTP     = "smtp.gmail.com:587";
char *pszSender   = "Send by Me";
char *pszTo       = "send_to_e-mail";
char *pszSubject  = "Subject";


void main( void ) {
   bool      bInitStatus = 1;
   cSENDMAIL cSend( &bInitStatus );

   if ( bInitStatus ) {
      char *pszFormat = "Send by me: %s\r\n";

      sprintf( cSend.MailBuffer(), pszFormat, "My Name" );
      cSend.SendMail( pszFrom,
                      pszPassword,
                      pszSMTP,
                      pszSender,
                      pszTo,
                      pszSubject,
                      cSend.MailBuffer(),
/*
                      "file_1",
                      "file_2",
                        .
                        .
                        .
  


Maciej Los

4 года слишком поздно!

perosoft

извините, но теперь мне это было нужно, и мне повезло, что я нашел решение гэвинсимпсона.

CHill60

Так зачем же публиковать свой собственный код, если вам посчастливилось найти решение гэвинсимпсона??

perosoft

из-за вложения текстовых + n файлов

Рейтинг:
0

gavinsimpson

Просто небольшое изменение в решении 7, чтобы разрешить отправку основного текста письма и вложения. Ключ находится в граница

#include <cstring> 
#include <iostream>
#include <stdlib.h>
#include <curses.h>
#include <curl/curl.h>

using namespace std;

#ifdef _DEBUG
        #pragma comment(lib, "libcurl_a_debug.lib")
#else
        #pragma comment(lib, "libcurl_a.lib")
#endif
 
#pragma warning(disable: 4996)
 
#define FROM    "<xxxxx@xxxx.com>"
#define TO      "<xxxxxx@gmail.com>"
#define FILENAME "temp.jpg"
//#define FILENAME "mail.txt"
 
static const int CHARS= 76;
static const int ADD_SIZE= 16;
static const int SEND_BUF_SIZE= 54;
static char (*fileBuf)[CHARS] = NULL;
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
using namespace std;
 
bool LARGEFILE = false;
int status = 0;
int percent2 = 0;
int percent3 = 0;
int percent4 = 0;
int percent5 = 0;

void LargeFilePercent(int rowcount)
{
        int percent = rowcount/100;
        if(LARGEFILE == true) {
                status++;
                percent2++;
                if(percent2 == 18)
                {
                        percent3++;
                        percent2 = 0;
                }
                if(percent3 == percent)
                {
                        percent4++;
                        percent3 = 0;
                }
                if(percent4 == 10)
                {
                        cout << "Larger Files take longer to encode, Please be patient." << endl
                             << endl << "Encoding " FILENAME " please be patient..." << endl;
                        cout << percent5 << "%";
                        percent5 += 10;
                        percent4 = 0;
                }
                if(status == 10000) {
                        if(percent5 == 0){cout << " 0%"; percent5 = 10;}
                        cout << ".";
                        status = 0;
                }
        }
}
 
void encodeblock(unsigned char in[3], unsigned char out[4], int len)
{
    out[0] = cb64[ in[0] >> 2 ];
    out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
    out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
    out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}
 
void encode(FILE *infile, unsigned char *output_buf, int rowcount/*For Percent*/)
{
    unsigned char in[3], out[4];
        int i, len;
        *output_buf = 0;
 
    while(!feof(infile)) {
        len = 0;
        for(i = 0; i < 3; i++) {
            in[i] = (unsigned char) getc(infile);
            if(!feof(infile) ) {
                len++;
            }
            else {
                in[i] = 0;
            }
        }
        if(len)
        {
            encodeblock(in, out, len);
            strncat((char*)output_buf, (char*)out, 4);
        }
            LargeFilePercent(rowcount);
        }
}
 
 
struct fileBuf_upload_status
{
  int lines_read;
};
 
size_t read_file()
{
        FILE* hFile=NULL;
        size_t fileSize(0),len(0),buffer_size(0);
        hFile = fopen(FILENAME,"rb");
        if(!hFile)
        {
                cout << "File not found!!!" << endl;
                exit (EXIT_FAILURE);
        }
		fseek(hFile,0,SEEK_END);
        fileSize = ftell(hFile);
        fseek(hFile,0,SEEK_SET);
        if(fileSize > 256000)
        {
                cout << "Larger Files take longer to encode, Please be patient." << endl;
                LARGEFILE = true;
        }
        cout << endl << "Encoding " FILENAME " please be patient..." << endl;
        int no_of_rows = fileSize/SEND_BUF_SIZE + 1;
        int charsize = (no_of_rows*72)+(no_of_rows*2);
        unsigned char* b64encode = new unsigned char[charsize];
        *b64encode = 0;
        encode(hFile, b64encode, no_of_rows);
        string encoded_buf = (char*)b64encode;
        if(LARGEFILE == true) cout << endl << endl;
        fileBuf = new char[ADD_SIZE + no_of_rows][CHARS];
        strcpy(fileBuf[len++],"To: " TO "\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        
        strcpy(fileBuf[len++],"From: " FROM "\r\n");
        buffer_size += strlen(fileBuf[len-1]);

        strcpy(fileBuf[len++],"Subject: gsimSecurity Photo\r\n");
        buffer_size += strlen(fileBuf[len-1]);

        strcpy(fileBuf[len++],"Content-Type: multipart/mixed;\r\n boundary=\"XXXXXMyBoundry\"\r\n");
        buffer_size += strlen(fileBuf[len-1]);

        strcpy(fileBuf[len++],"Mime-Version: 1.0\r\n\r\n");
        buffer_size += strlen(fileBuf[len-1]);

        strcpy(fileBuf[len++],"This is a multi-part message in MIME format.\r\n\r\n");
        buffer_size += strlen(fileBuf[len-1]);

		strcpy(fileBuf[len++],"--XXXXXMyBoundry\r\n");
		buffer_size += strlen(fileBuf[len-1]);
		
		strcpy(fileBuf[len++],"Content-Type: text/plain; charset=\"UTF-8\"\r\n");
		buffer_size += strlen(fileBuf[len-1]);
		
		strcpy(fileBuf[len++],"Content-Transfer-Encoding: quoted-printable\r\n\r\n");
		buffer_size += strlen(fileBuf[len-1]);

        strcpy(fileBuf[len++],"The body of the message starts here\r\nLet's add to the body!\r\n\r\n");
        buffer_size += strlen(fileBuf[len-1]);

		strcpy(fileBuf[len++],"--XXXXXMyBoundry\r\n");
		buffer_size += strlen(fileBuf[len-1]);
     
        strcpy(fileBuf[len++],"Content-Type: application/x-msdownload; name=\"" FILENAME "\"\r\n");
        buffer_size += strlen(fileBuf[len-1]);


        strcpy(fileBuf[len++],"Content-Transfer-Encoding: base64\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"Content-Disposition: attachment; filename=\"" FILENAME "\"\r\n");
        buffer_size += strlen(fileBuf[len-1]);
        strcpy(fileBuf[len++],"\r\n");
        buffer_size += strlen(fileBuf[len-1]);
   
        int pos = 0;
        string sub_encoded_buf;
        for(int i = 0; i <= no_of_rows-1; i++)
        {
                sub_encoded_buf = encoded_buf.substr(pos*72,72);
                sub_encoded_buf += "\r\n";
                strcpy(fileBuf[len++], sub_encoded_buf.c_str());
                buffer_size += sub_encoded_buf.size();
                pos++;
        }

		strcpy(fileBuf[len++],"\r\n--XXXXXMyBoundry--\r\n");
		buffer_size += strlen(fileBuf[len-1]);

        delete[] b64encode;
        return buffer_size;
}
static size_t fileBuf_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
        struct fileBuf_upload_status *upload_ctx = (struct fileBuf_upload_status *)userp;
        const char *fdata;
 
        if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1))
        {
                return 0;
        }
 
        fdata = fileBuf[upload_ctx->lines_read];
 
        if(strcmp(fdata,""))
        {
                size_t len = strlen(fdata);
                memcpy(ptr, fdata, len);
                upload_ctx->lines_read++;
                return len;
        }
        return 0;
}
 
int main()
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct curl_slist *recipients = NULL;
  struct fileBuf_upload_status file_upload_ctx;
  size_t file_size(0);
 
  file_upload_ctx.lines_read = 0;
 
  curl = curl_easy_init();
  file_size = read_file();
  if(curl)
  {
    curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.xxxxxxxx.com");
    curl_easy_setopt(curl, CURLOPT_USE_SSL, (long) CURLUSESSL_ALL);
    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
    recipients = curl_slist_append(recipients, TO);
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
    curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size);
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, fileBuf_source);
    curl_easy_setopt(curl, CURLOPT_READDATA, &file_upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
 
    res = curl_easy_perform(curl);
 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    curl_slist_free_all(recipients);
    curl_easy_cleanup(curl);
  }
  delete[] fileBuf;
  return (int)res;
}