- instr = strdup(msg->cm_fields['M']);
- CtdlFreeMessage(msg);
-
- /* Strip out the headers amd any other non-instruction line */
- lines = num_tokens(instr, '\n');
- for (i=0; i<lines; ++i) {
- extract_token(buf, instr, i, '\n', sizeof buf);
- if (num_tokens(buf, '|') < 2) {
- remove_token(instr, i, '\n');
- --lines;
- --i;
- }
- }
-
- /* Learn the message ID and find out about recent delivery attempts */
- lines = num_tokens(instr, '\n');
- for (i=0; i<lines; ++i) {
- extract_token(buf, instr, i, '\n', sizeof buf);
- extract_token(key, buf, 0, '|', sizeof key);
- if (!strcasecmp(key, "msgid")) {
- text_msgid = extract_long(buf, 1);
- }
- if (!strcasecmp(key, "envelope_from")) {
- extract_token(envelope_from, buf, 1, '|', sizeof envelope_from);
- }
- if (!strcasecmp(key, "retry")) {
- /* double the retry interval after each attempt */
- retry = extract_long(buf, 1) * 2L;
- if (retry > SMTP_RETRY_MAX) {
- retry = SMTP_RETRY_MAX;
- }
- remove_token(instr, i, '\n');
- }
- if (!strcasecmp(key, "attempted")) {
- attempted = extract_long(buf, 1);
- if (attempted > last_attempted)
- last_attempted = attempted;
- }
- }
-
- /*
- * Postpone delivery if we've already tried recently.
- */
- if (((time(NULL) - last_attempted) < retry) && (run_queue_now == 0)) {
- syslog(LOG_DEBUG, "SMTP client: Retry time not yet reached.");
- free(instr);
- return;
- }
-
-
- /*
- * Bail out if there's no actual message associated with this
- */
- if (text_msgid < 0L) {
- syslog(LOG_ERR, "SMTP client: no 'msgid' directive found!");
- free(instr);
- return;
- }
-
- /* Plow through the instructions looking for 'remote' directives and
- * a status of 0 (no delivery yet attempted) or 3/4 (transient errors
- * were experienced and it's time to try again)
- */
- lines = num_tokens(instr, '\n');
- for (i=0; i<lines; ++i) {
- extract_token(buf, instr, i, '\n', sizeof buf);
- extract_token(key, buf, 0, '|', sizeof key);
- extract_token(addr, buf, 1, '|', sizeof addr);
- status = extract_int(buf, 2);
- extract_token(dsn, buf, 3, '|', sizeof dsn);
- if ( (!strcasecmp(key, "remote"))
- && ((status==0)||(status==3)||(status==4)) ) {
-
- /* Remove this "remote" instruction from the set,
- * but replace the set's final newline if
- * remove_token() stripped it. It has to be there.
- */
- remove_token(instr, i, '\n');
- if (instr[strlen(instr)-1] != '\n') {
- strcat(instr, "\n");
- }
-
- --i;
- --lines;
- syslog(LOG_DEBUG, "SMTP client: Trying <%s>", addr);
- smtp_try(key, addr, &status, dsn, sizeof dsn, text_msgid, envelope_from);
- if (status != 2) {
- if (results == NULL) {
- results = malloc(1024);
- memset(results, 0, 1024);
- }
- else {
- results = realloc(results, strlen(results) + 1024);
+ instr = msg->cm_fields[eMesageText];
+ msg->cm_fields[eMesageText] = NULL;
+ CM_Free(msg);
+
+ // if the queue message has any CRLF's convert them to LF's
+ char *crlf = NULL;
+ while (crlf = strstr(instr, "\r\n"), crlf != NULL) {
+ strcpy(crlf, crlf + 1);
+ }
+
+ // Strip out the headers and we are now left with just the instructions.
+ char *soi = strstr(instr, "\n\n");
+ if (soi) {
+ strcpy(instr, soi + 2);
+ }
+
+ long msgid = 0;
+ time_t submitted = time(NULL);
+ time_t attempted = 0;
+ char *bounceto = NULL;
+ char *envelope_from = NULL;
+
+ char cfgline[SIZ];
+ for (i = 0; i < num_tokens(instr, '\n'); ++i) {
+ extract_token(cfgline, instr, i, '\n', sizeof cfgline);
+ if (!strncasecmp(cfgline, HKEY("msgid|")))
+ msgid = atol(&cfgline[6]);
+ if (!strncasecmp(cfgline, HKEY("submitted|")))
+ submitted = atol(&cfgline[10]);
+ if (!strncasecmp(cfgline, HKEY("attempted|")))
+ attempted = atol(&cfgline[10]);
+ if (!strncasecmp(cfgline, HKEY("bounceto|")))
+ bounceto = strdup(&cfgline[9]);
+ if (!strncasecmp(cfgline, HKEY("envelope_from|")))
+ envelope_from = strdup(&cfgline[14]);
+ }
+
+ int should_try_now = 0;
+ if (attempted < submitted) { // If no attempts have been made yet, try now
+ should_try_now = 1;
+ } else if ((attempted - submitted) <= 14400) {
+ if ((time(NULL) - attempted) > 1800) { // First four hours, retry every 30 minutes
+ should_try_now = 1;
+ }
+ } else {
+ if ((time(NULL) - attempted) > 14400) { // After that, retry once every 4 hours
+ should_try_now = 1;
+ }
+ }
+
+ if (should_try_now) {
+ syslog(LOG_DEBUG, "smtpclient: attempting delivery of message <%ld> now", qmsgnum);
+ StrBuf *NewInstr = NewStrBuf();
+ StrBufAppendPrintf(NewInstr, "Content-type: " SPOOLMIME "\n\n");
+ StrBufAppendPrintf(NewInstr, "msgid|%ld\n", msgid);
+ StrBufAppendPrintf(NewInstr, "submitted|%ld\n", submitted);
+ if (bounceto)
+ StrBufAppendPrintf(NewInstr, "bounceto|%s\n", bounceto);
+ if (envelope_from)
+ StrBufAppendPrintf(NewInstr, "envelope_from|%s\n", envelope_from);
+
+ for (i = 0; i < num_tokens(instr, '\n'); ++i) {
+ extract_token(cfgline, instr, i, '\n', sizeof cfgline);
+ if (!strncasecmp(cfgline, HKEY("remote|"))) {
+ char recp[SIZ];
+ int previous_result = extract_int(cfgline, 2);
+ if ((previous_result == 0)
+ || (previous_result == 4)) {
+ int new_result = 421;
+ extract_token(recp, cfgline, 1, '|', sizeof recp);
+ new_result = smtp_attempt_delivery(msgid, recp, envelope_from, server_response);
+ syslog(LOG_DEBUG,
+ "smtpclient: recp: <%s> , result: %d (%s)", recp, new_result, server_response);
+ if ((new_result / 100) == 2) {
+ ++num_success;
+ } else {
+ if ((new_result / 100) == 5) {
+ ++num_fail;
+ } else {
+ ++num_delayed;
+ }
+ StrBufAppendPrintf
+ (NewInstr,
+ "remote|%s|%ld|%ld (%s)\n",
+ recp, (new_result / 100), new_result, server_response);
+ }