Search code examples
c++arrayscharconcatenationmime

Composing MIME headers from scratch


I am trying to figure out how to dynamically change information inside of a MIME header (which will be sent via SMTP) in C++ on Win7.

The below is the basic layout for a MIME header I am using.

char *payload_text[]={

  "Date: Sun, 14 Oct 2012 12:59:19 +1000\n",
  "To: " TO "\n",
  "From: " FROM "\n",
  "Cc: " CC "\n",
  "Message-ID: <sender@greenearth.com>\n",
  "Subject: This is a test with the payload as char\n",
  "\n",
  "Here is where the info goes\n",
  "\n ",
  NULL
  };

I would like to create a function that can change, for example, the subject of the header file when it is called, and return a char array (to my understanding). Here is how I am attempting this.

char *part1[]={

  "Date: Sun, 14 Oct 2012 12:59:19 +1000\n",
  "To: " TO "\n",
  "From: " FROM "\n",
  "Cc: " CC "\n",
  "Message-ID: <sender@greenearth.com>\n",
  "Subject: This is a test with the payload as char\n",
  "\n"
};

char *body [] = { "Test information.", 
                   "More test info" };

char *full_payload [ strlen(*part1) + strlen(*body) + 1 ];

strcat( *full_payload, *part1 );

strcat( *full_payload, *body );

cout << *full_payload;

When the payload is viewed, only the first string from both parts are shown

Output on console:

[several junk bytes]Date: Sun, 14 Oct 2012 12:59:19 +1000
Test information.

Whereas there should be an entire MIME header shown.

I cannot understand why this will not work. I believe the problem could be in that I do not understand the behaviour of {} in C++ nor can I find tutorials/example code that fall in this context (most seem to only address char arrays that don't have multiple strings seperated by commas inside of curved brackets).

Simply put, how can I append a string to the end of an existing chracter array of strings enclosed in curved brackets?

Thank you for reading, and advice would be recieved warmly.

Follow up:

Using the function to create a std::string and then converting it to a const char * it formats the MIME message as desired but fails to work with the libraries I am using for SMTP.

The final result must be in the form of char* payload[] = {"strings, seperated, by, comma"}; and not char *payload = "strings\nseperated\nby\ncommas" which is what the .c_str() seems to do.

Does anyone know how to convert a std::string or char* array[] to a char* payload[] = {"strings, seperated, by, comma"}; ? I think the brackets are the important part.


Simple question:

char *first_array[]  = { "one", "two" };

char *second_array[] = { "three", "four"};

char *final_array[ strlen(*first_array) + strlen(*second_array) + 1];

strcpy( *final_array, *second_array );

cout << *final_array;

How do I combine first_array and second_array into final_array? strcopy() and strcat() cause the program to crash when implemented like this. I think all I need to do is this basic operation.


Solution

  • In part1 and body, you are creating an array of strings, not a single string. This is similar to doing:

    int values[] = { 1, 2, 3, 4 };
    

    The {} in this context are defining the items in the array. Thus *part1 and *body only refer to the first line of each -- your code is copying the content of the first string in part1 and body.

    As for the junk bytes, strcat looks for the first null character and starts from there, replacing the null. Therefore, the first string should be appended using strcpy.

    To properly handle this, note that std::vector<const char *> mime will have the same layout as const char * mime[], so you can use this to build your array of strings:

    void send_smtp_message(const char **message);
    
    void build_mime_header(std::vector<const char *> &mime)
    {
        mime.push_back("Date: ...");
        mime.push_back("From: " FROM);
        // ...
        mime.push_back(""); // for the newline between header and body
    }
    
    void main()
    {
        std::vector<const char *> mime;
        build_mime_header(mime);
        mime.push_back("This is a test.");
        mime.push_back(NULL); // if the API requires this for end-of-data.
        send_smtp_message(&mime[0]);
    }