diff options
-rw-r--r-- | win32/sendmail.c | 177 | ||||
-rw-r--r-- | win32/sendmail.h | 2 |
2 files changed, 117 insertions, 62 deletions
diff --git a/win32/sendmail.c b/win32/sendmail.c index a799a979ab..e47dc9c249 100644 --- a/win32/sendmail.c +++ b/win32/sendmail.c @@ -123,6 +123,7 @@ int TSendMail(char *host, int *error, char **error_message, { int ret; char *RPath = NULL; + char *headers_lc = NULL; /* headers_lc is only created if we've a header at all */ WinsockStarted = FALSE; @@ -139,14 +140,26 @@ int TSendMail(char *host, int *error, char **error_message, /* use from address as return path (if specified in headers) */ if (headers) { char *pos = NULL; - /* Try to match 'From:' only at start of the string or after following a \r\n */ - if (strstr(headers, "\r\nFrom:")) { - pos = strstr(headers, "\r\nFrom:") + 7; - } else if (!strncmp(headers, "From:", 5)) { - pos = headers + 5; + size_t i; + /* Create a lowercased header for all the searches so we're finally case + * insensitive when searching for a pattern. */ + if (NULL == (headers_lc = estrdup(headers))) { + *error = OUT_OF_MEMORY; + return FAILURE; + } + for (i = 0; i < strlen(headers_lc); i++) { + headers_lc[i] = tolower(headers_lc[i]); + } + /* Try to match 'from:' only at start of the string or after following a \r\n */ + if (strstr(headers_lc, "\r\nfrom:")) { + pos = strstr(headers_lc, "\r\nfrom:") + 7; /* Jump over the string "\r\nfrom:", hence the 7 */ + } else if (!strncmp(headers_lc, "from:", 5)) { + pos = headers + 5; /* Jump over the string "from:", hence the 5 */ } if (pos) { char *pos_end; + /* Let pos point to the real header string */ + pos = headers + (pos - headers_lc); /* Ignore any whitespaces */ while (pos && ((*pos == ' ' || *pos == '\t'))) pos++; @@ -164,6 +177,9 @@ int TSendMail(char *host, int *error, char **error_message, if (INI_STR("sendmail_from")) { RPath = estrdup(INI_STR("sendmail_from")); } else { + if (headers_lc) { + efree(headers_lc); + } *error = W32_SM_SENDMAIL_FROM_NOT_SET; return FAILURE; } @@ -175,6 +191,9 @@ int TSendMail(char *host, int *error, char **error_message, if (RPath) { efree(RPath); } + if (headers_lc) { + efree(headers_lc); + } /* 128 is safe here, the specifier in snprintf isn't longer than that */ if (NULL == (*error_message = ecalloc(1, HOST_NAME_LEN + 128))) { return FAILURE; @@ -182,11 +201,14 @@ int TSendMail(char *host, int *error, char **error_message, snprintf(*error_message, HOST_NAME_LEN + 128, "Failed to connect to mailserver at \"%s\", verify your \"SMTP\" setting in php.ini", MailHost); return FAILURE; } else { - ret = SendText(RPath, Subject, mailTo, data, headers, error_message); + ret = SendText(RPath, Subject, mailTo, data, headers, headers_lc, error_message); TSMClose(); if (RPath) { efree(RPath); } + if (headers_lc) { + efree(headers_lc); + } if (ret != SUCCESS) { *error = ret; return FAILURE; @@ -246,12 +268,16 @@ char *GetSMErrorText(int index) // the subject is set to "No Subject" // 3) mailTo: Destination address // 4) data: Null terminated string containing the data to be send. +// 5,6) headers of the message. Note that the second +// parameter, headers_lc, is actually a lowercased version of +// headers. The should match exactly (in terms of length), +// only differ in case // Output: Error code or SUCCESS // Description: // Author/Date: jcar 20/9/96 // History: //*******************************************************************/ -int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers, char **error_message) +int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers, char *headers_lc, char **error_message) { int res, i; char *p; @@ -316,8 +342,11 @@ int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers efree(tempMailTo); /* Send mail to all Cc rcpt's */ - if (headers && (pos1 = strstr(headers, "Cc:"))) { - pos1 += 3; /* Jump over Cc: */ + if (headers && (pos1 = strstr(headers_lc, "cc:"))) { + /* Real offset is memaddress from the original headers + difference of + * string found in the lowercase headrs + 3 characters to jump over + * the cc: */ + pos1 = headers + (pos1 - headers_lc) + 3; if (NULL == (pos2 = strstr(pos1, "\r\n"))) { tempMailTo = estrndup(pos1, strlen(pos1)); @@ -345,56 +374,61 @@ int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers /* Send mail to all Bcc rcpt's This is basically a rip of the Cc code above. Just don't forget to remove the Bcc: from the header afterwards. */ - if (headers && (pos1 = strstr(headers, "Bcc:"))) { - pos1 += 4; /* Jump over Bcc: */ - if (NULL == (pos2 = strstr(pos1, "\r\n"))) { - int foo = strlen(pos1); - tempMailTo = estrndup(pos1, strlen(pos1)); - /* Later, when we remove the Bcc: out of the - header we know it was the last thing. */ - pos2 = pos1; - } else { - tempMailTo = estrndup(pos1, pos2 - pos1); - } - - token = strtok(tempMailTo, ","); - while(token != NULL) - { - sprintf(Buffer, "RCPT TO:<%s>\r\n", token); - if ((res = Post(Buffer)) != SUCCESS) { - return (res); + if (headers) { + if (pos1 = strstr(headers_lc, "bcc:")) { + /* Real offset is memaddress from the original headers + difference of + * string found in the lowercase headrs + 4 characters to jump over + * the bcc: */ + pos1 = headers + (pos1 - headers_lc) + 4; + if (NULL == (pos2 = strstr(pos1, "\r\n"))) { + int foo = strlen(pos1); + tempMailTo = estrndup(pos1, strlen(pos1)); + /* Later, when we remove the Bcc: out of the + header we know it was the last thing. */ + pos2 = pos1; + } else { + tempMailTo = estrndup(pos1, pos2 - pos1); } - if ((res = Ack(&server_response)) != SUCCESS) { - SMTP_ERROR_RESPONSE(server_response); - return (res); + + token = strtok(tempMailTo, ","); + while(token != NULL) + { + sprintf(Buffer, "RCPT TO:<%s>\r\n", token); + if ((res = Post(Buffer)) != SUCCESS) { + return (res); + } + if ((res = Ack(&server_response)) != SUCCESS) { + SMTP_ERROR_RESPONSE(server_response); + return (res); + } + token = strtok(NULL, ","); } - token = strtok(NULL, ","); - } - efree(tempMailTo); + efree(tempMailTo); - /* Now that we've identified that we've a Bcc list, - remove it from the current header. */ - if (NULL == (stripped_header = ecalloc(1, strlen(headers)))) { - return OUT_OF_MEMORY; - } - /* headers = point to string start of header - pos1 = pointer IN headers where the Bcc starts - '4' = Length of the characters 'Bcc:' - Because we've added +4 above for parsing the Emails - we've to substract them here. */ - memcpy(stripped_header, headers, pos1 - headers - 4); - if (pos1 != pos2) { - /* if pos1 != pos2 , pos2 points to the rest of the headers. - Since pos1 != pos2 if "\r\n" was found, we know those characters - are there and so we jump over them (else we would generate a new header - which would look like "\r\n\r\n". */ - memcpy(stripped_header + (pos1 - headers - 4), pos2 + 2, strlen(pos2) - 2); - } - } else { - /* Simplify the code that we create a copy of stripped_header no matter if - we actually strip something or not. So we've a single efree() later. */ - if (NULL == (stripped_header = estrndup(headers, strlen(headers)))) { - return OUT_OF_MEMORY; + /* Now that we've identified that we've a Bcc list, + remove it from the current header. */ + if (NULL == (stripped_header = ecalloc(1, strlen(headers)))) { + return OUT_OF_MEMORY; + } + /* headers = point to string start of header + pos1 = pointer IN headers where the Bcc starts + '4' = Length of the characters 'bcc:' + Because we've added +4 above for parsing the Emails + we've to substract them here. */ + memcpy(stripped_header, headers, pos1 - headers - 4); + if (pos1 != pos2) { + /* if pos1 != pos2 , pos2 points to the rest of the headers. + Since pos1 != pos2 if "\r\n" was found, we know those characters + are there and so we jump over them (else we would generate a new header + which would look like "\r\n\r\n". */ + memcpy(stripped_header + (pos1 - headers - 4), pos2 + 2, strlen(pos2) - 2); + } + } else { + /* Simplify the code that we create a copy of stripped_header no matter if + we actually strip something or not. So we've a single efree() later. */ + if (NULL == (stripped_header = estrndup(headers, strlen(headers)))) { + return OUT_OF_MEMORY; + } } } @@ -415,7 +449,9 @@ int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers } else { res = PostHeader(RPath, Subject, mailTo, stripped_header, NULL); } - efree(stripped_header); + if (stripped_header) { + efree(stripped_header); + } if (res != SUCCESS) { return (res); } @@ -482,12 +518,23 @@ int PostHeader(char *RPath, char *Subject, char *mailTo, char *xheaders, char *m int zoneh = abs(_timezone); int zonem, res; char *p; + char *headers_lc = NULL; + size_t i; + + if (xheaders) { + if (NULL == (headers_lc = estrdup(xheaders))) { + return OUT_OF_MEMORY; + } + for (i = 0; i < strlen(headers_lc); i++) { + headers_lc[i] = tolower(headers_lc[i]); + } + } p = Buffer; zoneh /= (60 * 60); zonem = (abs(_timezone) / 60) - (zoneh * 60); - if(!xheaders || !strstr(xheaders, "Date:")){ + if(!xheaders || !strstr(headers_lc, "date:")){ p += sprintf(p, "Date: %s, %02d %s %04d %02d:%02d:%02d %s%02d%02d\r\n", days[tm->tm_wday], tm->tm_mday, @@ -501,7 +548,7 @@ int PostHeader(char *RPath, char *Subject, char *mailTo, char *xheaders, char *m zonem); } - if(!xheaders || !strstr(xheaders, "From:")){ + if(!headers_lc || !strstr(headers_lc, "from:")){ p += sprintf(p, "From: %s\r\n", RPath); } p += sprintf(p, "Subject: %s\r\n", Subject); @@ -513,11 +560,19 @@ int PostHeader(char *RPath, char *Subject, char *mailTo, char *xheaders, char *m p += sprintf(p, "%s\r\n", xheaders); } - if ((res = Post(Buffer)) != SUCCESS) + if ((res = Post(Buffer)) != SUCCESS) { + if (headers_lc) { + efree(headers_lc); + } return (res); + } - if ((res = Post("\r\n")) != SUCCESS) + if ((res = Post("\r\n")) != SUCCESS) { + if (headers_lc) { + efree(headers_lc); + } return (res); + } return (SUCCESS); } diff --git a/win32/sendmail.h b/win32/sendmail.h index dcead800cd..6da0cd9bc4 100644 --- a/win32/sendmail.h +++ b/win32/sendmail.h @@ -34,7 +34,7 @@ int TSendMail(char *smtpaddr, int *returnerror, char **error_message, char *RPath, char *Subject, char *mailTo, char *data); void TSMClose(void); -int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers, char **error_message); +int SendText(char *RPath, char *Subject, char *mailTo, char *data, char *headers, char *headers_lc, char **error_message); char *GetSMErrorText(int index); int MailConnect(); |