/********************************************************************* // Name: SendText // Input: 1) RPath: return path of the message // Is used to fill the "Return-Path" and the // "X-Sender" fields of the message. // 2) Subject: Subject field of the message. If NULL is given // 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: //*******************************************************************/ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char *mailBcc, char *data, char *headers, char *headers_lc, char **error_message) { int res; char *p; char *tempMailTo, *token, *pos1, *pos2; char *server_response = NULL; char *stripped_header = NULL; zend_string *data_cln; /* check for NULL parameters */ if (data == NULL) return (BAD_MSG_CONTENTS); if (mailTo == NULL) return (BAD_MSG_DESTINATION); if (RPath == NULL) return (BAD_MSG_RPATH); /* simple checks for the mailto address */ /* have ampersand ? */ /* mfischer, 20020514: I commented this out because it really seems bogus. Only a username for example may still be a valid address at the destination system. if (strchr(mailTo, '@') == NULL) return (BAD_MSG_DESTINATION); */ snprintf(PW32G(mail_buffer), sizeof(PW32G(mail_buffer)), "HELO %s\r\n", PW32G(mail_local_host)); /* in the beginning of the dialog */ /* attempt reconnect if the first Post fail */ if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { int err = MailConnect(); if (0 != err) { return (FAILED_TO_SEND); } if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { return (res); } } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return (res); } SMTP_SKIP_SPACE(RPath); FormatEmailAddress(PW32G(mail_buffer), RPath, "MAIL FROM:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return W32_SM_SENDMAIL_FROM_MALFORMED; } tempMailTo = estrdup(mailTo); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); if (mailCc && *mailCc) { tempMailTo = estrdup(mailCc); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } /* Send mail to all Cc rcpt's */ else if (headers && (pos1 = strstr(headers_lc, "cc:")) && ((pos1 == headers_lc) || (*(pos1-1) == '\n'))) { /* 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)); } else { tempMailTo = estrndup(pos1, pos2 - pos1); } token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } /* 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 (mailBcc && *mailBcc) { tempMailTo = estrdup(mailBcc); /* Send mail to all rcpt's */ token = strtok(tempMailTo, ","); while (token != NULL) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); } else if (headers) { if ((pos1 = strstr(headers_lc, "bcc:")) && (pos1 == headers_lc || *(pos1-1) == '\n')) { /* 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"))) { 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) { SMTP_SKIP_SPACE(token); FormatEmailAddress(PW32G(mail_buffer), token, "RCPT TO:<%s>\r\n"); if ((res = Post(PW32G(mail_buffer))) != SUCCESS) { efree(tempMailTo); return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); efree(tempMailTo); return (res); } token = strtok(NULL, ","); } efree(tempMailTo); /* Now that we've identified that we've a Bcc list, remove it from the current header. */ stripped_header = ecalloc(1, strlen(headers)); /* 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 subtract 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); } } } /* 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 (headers && !stripped_header) { stripped_header = estrndup(headers, strlen(headers)); } if ((res = Post("DATA\r\n")) != SUCCESS) { if (stripped_header) { efree(stripped_header); } return (res); } if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); if (stripped_header) { efree(stripped_header); } return (res); } /* send message header */ if (Subject == NULL) { res = PostHeader(RPath, "No Subject", mailTo, stripped_header); } else { res = PostHeader(RPath, Subject, mailTo, stripped_header); } if (stripped_header) { efree(stripped_header); } if (res != SUCCESS) { return (res); } /* Escape \n. sequences * We use php_str_to_str() and not php_str_replace_in_subject(), since the latter * uses ZVAL as it's parameters */ data_cln = php_str_to_str(data, strlen(data), PHP_WIN32_MAIL_DOT_PATTERN, sizeof(PHP_WIN32_MAIL_DOT_PATTERN) - 1, PHP_WIN32_MAIL_DOT_REPLACE, sizeof(PHP_WIN32_MAIL_DOT_REPLACE) - 1); if (!data_cln) { data_cln = ZSTR_EMPTY_ALLOC(); } /* send message contents in 1024 chunks */ { char c, *e2, *e = ZSTR_VAL(data_cln) + ZSTR_LEN(data_cln); p = ZSTR_VAL(data_cln); while (e - p > 1024) { e2 = p + 1024; c = *e2; *e2 = '\0'; if ((res = Post(p)) != SUCCESS) { zend_string_free(data_cln); return(res); } *e2 = c; p = e2; } if ((res = Post(p)) != SUCCESS) { zend_string_free(data_cln); return(res); } } zend_string_free(data_cln); /*send termination dot */ if ((res = Post("\r\n.\r\n")) != SUCCESS) return (res); if ((res = Ack(&server_response)) != SUCCESS) { SMTP_ERROR_RESPONSE(server_response); return (res); } return (SUCCESS); }
//******************************************************************** // Name: TSendText // Input: 1) RPath: return path of the message // Is used to fill the "Return-Path" and the // "X-Sender" fields of the message. // 2) Subject: Subject field of the message. If NULL is given // the subject is set to "No Subject" // 3) mailTo: Destination address // 4) data: Null terminated string containing the data to be send. // 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) { int res, i; char *p; char *tempMailTo, *token, *pos1, *pos2; TLS_VARS; // check for NULL parameters if (data == NULL) return (BAD_MSG_CONTENTS); if (mailTo == NULL) return (BAD_MSG_DESTINATION); if (RPath == NULL) return (BAD_MSG_RPATH); // simple checks for the mailto address // have ampersand ? if (strchr(mailTo, '@') == NULL) return (BAD_MSG_DESTINATION); sprintf(GLOBAL(Buffer), "HELO %s\r\n", GLOBAL(LocalHost)); // in the beggining of the dialog // attempt reconnect if the first Post fail if ((res = Post(GLOBAL(Buffer))) != SUCCESS) { MailConnect(); if ((res = Post(GLOBAL(Buffer))) != SUCCESS) return (res); } if ((res = Ack()) != SUCCESS) return (res); sprintf(GLOBAL(Buffer), "MAIL FROM:<%s>\r\n", RPath); if ((res = Post(GLOBAL(Buffer))) != SUCCESS) return (res); if ((res = Ack()) != SUCCESS) return (res); tempMailTo = estrdup(mailTo); // Send mail to all rcpt's token = strtok(tempMailTo, ","); while(token != NULL) { sprintf(GLOBAL(Buffer), "RCPT TO:<%s>\r\n", token); if ((res = Post(GLOBAL(Buffer))) != SUCCESS) return (res); if ((res = Ack()) != SUCCESS) return (res); token = strtok(NULL, ","); } // Send mail to all Cc rcpt's efree(tempMailTo); if (headers && (pos1 = strstr(headers, "Cc:"))) { pos2 = strstr(pos1, "\r\n"); tempMailTo = estrndup(pos1, pos2-pos1); token = strtok(tempMailTo, ","); while(token != NULL) { sprintf(GLOBAL(Buffer), "RCPT TO:<%s>\r\n", token); if ((res = Post(GLOBAL(Buffer))) != SUCCESS) return (res); if ((res = Ack()) != SUCCESS) return (res); token = strtok(NULL, ","); } efree(tempMailTo); } if ((res = Post("DATA\r\n")) != SUCCESS) return (res); if ((res = Ack()) != SUCCESS) return (res); // send message header if (Subject == NULL) res = PostHeader(RPath, "No Subject", mailTo, headers); else res = PostHeader(RPath, Subject, mailTo, headers); if (res != SUCCESS) return (res); // send message contents in 1024 chunks if (strlen(data) <= 1024) { if ((res = Post(data)) != SUCCESS) return (res); } else { p = data; while (1) { if (*p == '\0') break; if (strlen(p) >= 1024) i = 1024; else i = strlen(p); // put next chunk in buffer strncpy(GLOBAL(Buffer), p, i); GLOBAL(Buffer)[i] = '\0'; p += i; // send chunk if ((res = Post(GLOBAL(Buffer))) != SUCCESS) return (res); } } //send termination dot if ((res = Post("\r\n.\r\n")) != SUCCESS) return (res); if ((res = Ack()) != SUCCESS) return (res); return (SUCCESS); }