* The VRFY and EXPN commands have been removed from this implementation
* because nobody uses these commands anymore, except for spammers.
*
- * Copyright (c) 1998-2009 by the citadel.org team
+ * Copyright (c) 1998-2011 by the citadel.org team
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is open source software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
#include "ctdl_module.h"
#include "smtp_util.h"
+#ifndef EXPERIMENTAL_SMTP_EVENT_CLIENT
int run_queue_now = 0; /* Set to 1 to ignore SMTP send retry times */
/* Parse out the host portion of the recipient address */
process_rfc822_addr(addr, user, node, name);
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: Attempting delivery to <%s> @ <%s> (%s)\n",
+ syslog(LOG_DEBUG, "SMTP client: Attempting delivery to <%s> @ <%s> (%s)\n",
user, node, name);
/* Load the message out of the database */
}
if ( (lp>=0) && (rp>lp) ) {
mailfrom[rp] = 0;
- strcpy(mailfrom, &mailfrom[lp]);
+ strcpy(mailfrom, &mailfrom[lp + 1]);
}
scan_done = 1;
}
} while (scan_done == 0);
- if (IsEmptyStr(mailfrom)) strcpy(mailfrom, "someone@somewhere.org");
+ if (IsEmptyStr(mailfrom)) {
+ char badmail_filename[128];
+ snprintf(badmail_filename, sizeof badmail_filename, "/tmp/badmail.%d.%ld",
+ getpid, time(NULL)
+ );
+ FILE *badmail_fp = fopen(badmail_filename, "w");
+ fwrite(msgtext, msg_size, 1, badmail_fp);
+ fclose(badmail_fp);
+ }
stripallbut(mailfrom, '<', '>');
envelope_from = mailfrom;
}
/* Figure out what mail exchanger host we have to connect to */
num_mxhosts = getmx(mxhosts, node);
- CtdlLogPrintf(CTDL_DEBUG, "Number of MX hosts for <%s> is %d [%s]\n", node, num_mxhosts, mxhosts);
+ syslog(LOG_DEBUG, "Number of MX hosts for <%s> is %d [%s]\n", node, num_mxhosts, mxhosts);
if (num_mxhosts < 1) {
*status = 5;
snprintf(dsn, SIZ, "No MX hosts found for <%s>", node);
else {
strcpy(mx_port, "25");
}
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: connecting to %s : %s ...\n", mx_host, mx_port);
+ syslog(LOG_DEBUG, "SMTP client: connecting to %s : %s ...\n", mx_host, mx_port);
sock = sock_connect(mx_host, mx_port);
snprintf(dsn, SIZ, "Could not connect: %s", strerror(errno));
if (sock >= 0)
{
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: connected!\n");
+ syslog(LOG_DEBUG, "SMTP client: connected!\n");
int fdflags;
fdflags = fcntl(sock, F_GETFL);
if (fdflags < 0)
- CtdlLogPrintf(CTDL_DEBUG,
+ syslog(LOG_DEBUG,
"unable to get SMTP-Client socket flags! %s \n",
strerror(errno));
fdflags = fdflags | O_NONBLOCK;
if (fcntl(sock, F_SETFL, fdflags) < 0)
- CtdlLogPrintf(CTDL_DEBUG,
+ syslog(LOG_DEBUG,
"unable to set SMTP-Client socket nonblocking flags! %s \n",
strerror(errno));
}
strcpy(dsn, "Connection broken during SMTP conversation");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* Do a EHLO command. If it fails, try the HELO command. */
snprintf(buf, sizeof buf, "EHLO %s\r\n", config.c_fqdn);
- CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
+ syslog(LOG_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP HELO");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
snprintf(buf, sizeof buf, "HELO %s\r\n", config.c_fqdn);
- CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
+ syslog(LOG_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
sprintf(buf, "%s%c%s%c%s", mx_user, '\0', mx_user, '\0', mx_pass);
CtdlEncodeBase64(encoded, buf, strlen(mx_user) + strlen(mx_user) + strlen(mx_pass) + 2, 0);
snprintf(buf, sizeof buf, "AUTH PLAIN %s\r\n", encoded);
- CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
+ syslog(LOG_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP AUTH");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* previous command succeeded, now try the MAIL FROM: command */
snprintf(buf, sizeof buf, "MAIL FROM:<%s>\r\n", envelope_from);
- CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
+ syslog(LOG_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP MAIL");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
/* MAIL succeeded, now try the RCPT To: command */
snprintf(buf, sizeof buf, "RCPT TO:<%s@%s>\r\n", user, node);
- CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
+ syslog(LOG_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP RCPT");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
}
/* RCPT succeeded, now try the DATA command */
- CtdlLogPrintf(CTDL_DEBUG, ">DATA\n");
+ syslog(LOG_DEBUG, ">DATA\n");
sock_write(&sock, "DATA\r\n", 6);
if (ml_sock_gets(&sock, buf, 30) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP DATA");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
+ syslog(LOG_DEBUG, "<%s\n", buf);
if (buf[0] != '3') {
if (buf[0] == '4') {
*status = 3;
msg_size,
(msg_size / 128) + 50);
if (msgtext[msg_size-1] != 10) {
- CtdlLogPrintf(CTDL_WARNING, "Possible problem: message did not "
+ syslog(LOG_WARNING, "Possible problem: message did not "
"correctly terminate. (expecting 0x10, got 0x%02x)\n",
buf[msg_size-1]);
sock_write(&sock, "\r\n", 2);
strcpy(dsn, "Connection broken during SMTP message transmit");
goto bail;
}
- CtdlLogPrintf(CTDL_DEBUG, "%s\n", buf);
+ syslog(LOG_DEBUG, "%s\n", buf);
if (buf[0] != '2') {
if (buf[0] == '4') {
*status = 4;
safestrncpy(dsn, &buf[4], 1023);
*status = 2;
- CtdlLogPrintf(CTDL_DEBUG, ">QUIT\n");
+ syslog(LOG_DEBUG, ">QUIT\n");
sock_write(&sock, "QUIT\r\n", 6);
ml_sock_gets(&sock, buf, 30);
- CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
- CtdlLogPrintf(CTDL_INFO, "SMTP client: delivery to <%s> @ <%s> (%s) succeeded\n",
+ syslog(LOG_DEBUG, "<%s\n", buf);
+ syslog(LOG_INFO, "SMTP client: delivery to <%s> @ <%s> (%s) succeeded\n",
user, node, name);
bail: free(msgtext);
if (sock != -1)
sock_close(sock);
- /* Write something to the syslog (which may or may not be where the
+ /* Write something to the syslog(which may or may not be where the
* rest of the Citadel logs are going; some sysadmins want LOG_MAIL).
*/
- if (enable_syslog) {
- syslog((LOG_MAIL | LOG_INFO),
- "%ld: to=<%s>, relay=%s, stat=%s",
- msgnum,
- addr,
- mx_host,
- dsn
- );
- }
+ syslog((LOG_MAIL | LOG_INFO),
+ "%ld: to=<%s>, relay=%s, stat=%s",
+ msgnum,
+ addr,
+ mx_host,
+ dsn
+ );
return;
}
StrBuf *BounceMB;
long omsgid = (-1);
- CtdlLogPrintf(CTDL_DEBUG, "smtp_do_bounce() called\n");
+ syslog(LOG_DEBUG, "smtp_do_bounce() called\n");
strcpy(bounceto, "");
boundary = NewStrBufPlain(HKEY("=_Citadel_Multipart_"));
StrBufAppendPrintf(boundary, "%s_%04x%04x", config.c_fqdn, getpid(), ++seq);
dsnlen = extract_token(dsn, buf, 3, '|', sizeof dsn);
bounce_this = 0;
- CtdlLogPrintf(CTDL_DEBUG, "key=<%s> addr=<%s> status=%d dsn=<%s>\n",
+ syslog(LOG_DEBUG, "key=<%s> addr=<%s> status=%d dsn=<%s>\n",
key, addr, status, dsn);
if (!strcasecmp(key, "bounceto")) {
free(bmsg->cm_fields['A']);
bmsg->cm_fields['A'] = SmashStrBuf(&BounceMB);
/* Deliver the bounce if there's anything worth mentioning */
- CtdlLogPrintf(CTDL_DEBUG, "num_bounces = %d\n", num_bounces);
+ syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces);
if (num_bounces > 0) {
/* First try the user who sent the message */
- CtdlLogPrintf(CTDL_DEBUG, "bounce to user? <%s>\n", bounceto);
+ syslog(LOG_DEBUG, "bounce to user? <%s>\n", bounceto);
if (IsEmptyStr(bounceto)) {
- CtdlLogPrintf(CTDL_ERR, "No bounce address specified\n");
+ syslog(LOG_ERR, "No bounce address specified\n");
bounce_msgid = (-1L);
}
}
FreeStrBuf(&boundary);
CtdlFreeMessage(bmsg);
- CtdlLogPrintf(CTDL_DEBUG, "Done processing bounces\n");
+ syslog(LOG_DEBUG, "Done processing bounces\n");
}
time_t last_attempted = 0L;
time_t retry = SMTP_RETRY_INTERVAL;
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: smtp_do_procmsg(%ld)\n", msgnum);
+ syslog(LOG_DEBUG, "SMTP client: smtp_do_procmsg(%ld)\n", msgnum);
strcpy(envelope_from, "");
msg = CtdlFetchMessage(msgnum, 1);
if (msg == NULL) {
- CtdlLogPrintf(CTDL_ERR, "SMTP client: tried %ld but no such message!\n", msgnum);
+ syslog(LOG_ERR, "SMTP client: tried %ld but no such message!\n", msgnum);
return;
}
* Postpone delivery if we've already tried recently.
*/
if (((time(NULL) - last_attempted) < retry) && (run_queue_now == 0)) {
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: Retry time not yet reached.\n");
+ syslog(LOG_DEBUG, "SMTP client: Retry time not yet reached.\n");
free(instr);
return;
}
* Bail out if there's no actual message associated with this
*/
if (text_msgid < 0L) {
- CtdlLogPrintf(CTDL_ERR, "SMTP client: no 'msgid' directive found!\n");
+ syslog(LOG_ERR, "SMTP client: no 'msgid' directive found!\n");
free(instr);
return;
}
--i;
--lines;
- CtdlLogPrintf(CTDL_DEBUG, "SMTP client: Trying <%s>\n", addr);
+ syslog(LOG_DEBUG, "SMTP client: Trying <%s>\n", addr);
smtp_try(key, addr, &status, dsn, sizeof dsn, text_msgid, envelope_from);
if (status != 2) {
if (results == NULL) {
*
* Run through the queue sending out messages.
*/
-void *smtp_queue_thread(void *arg) {
+void smtp_do_queue(void) {
+ static int is_running = 0;
int num_processed = 0;
- struct CitContext smtp_queue_CC;
- CtdlFillSystemContext(&smtp_queue_CC, "SMTP Send");
- citthread_setspecific(MyConKey, (void *)&smtp_queue_CC);
- CtdlLogPrintf(CTDL_DEBUG, "smtp_queue_thread() initializing\n");
+ if (is_running) return; /* Concurrency check - only one can run */
+ is_running = 1;
- while (!CtdlThreadCheckStop()) {
-
- CtdlLogPrintf(CTDL_INFO, "SMTP client: processing outbound queue\n");
+ syslog(LOG_INFO, "SMTP client: processing outbound queue\n");
- if (CtdlGetRoom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) {
- CtdlLogPrintf(CTDL_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
- }
- else {
- num_processed = CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, NULL);
- }
- CtdlLogPrintf(CTDL_INFO, "SMTP client: queue run completed; %d messages processed\n", num_processed);
- CtdlThreadSleep(60);
+ if (CtdlGetRoom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) {
+ syslog(LOG_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
}
-
- CtdlClearSystemContext();
- return(NULL);
+ else {
+ num_processed = CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, NULL);
+ }
+ syslog(LOG_INFO, "SMTP client: queue run completed; %d messages processed\n", num_processed);
+ is_running = 0;
}
}
-
+#endif
CTDL_MODULE_INIT(smtp_client)
{
+#ifndef EXPERIMENTAL_SMTP_EVENT_CLIENT
if (!threading)
{
smtp_init_spoolout();
- CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, smtp_queue_thread, NULL);
+ CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);
CtdlRegisterProtoHook(cmd_smtp, "SMTP", "SMTP utility commands");
}
+#endif
/* return our Subversion id for the Log */
- return "smtp";
+ return "smtpclient";
}
+