/*
- * $Id$
- *
* This module is an SMTP and ESMTP implementation for the Citadel system.
* It is compliant with all of the following:
*
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <pwd.h>
int run_queue_now = 0; /* Set to 1 to ignore SMTP send retry times */
-citthread_mutex_t smtp_send_lock;
-
/*****************************************************************************/
/* SMTP SERVER (INBOUND) STUFF */
/* Load the message out of the database */
CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
- CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, ESC_DOT);
+ CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, (ESC_DOT|SUPPRESS_ENV_TO) );
msg_size = StrLength(CC->redirect_buffer);
msgtext = SmashStrBuf(&CC->redirect_buffer);
strcpy(mx_port, "25");
}
CtdlLogPrintf(CTDL_DEBUG, "SMTP client: connecting to %s : %s ...\n", mx_host, mx_port);
- sock = sock_connect(mx_host, mx_port, "tcp");
+ 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");
+ if (sock >= 0)
+ {
+ CtdlLogPrintf(CTDL_DEBUG, "SMTP client: connected!\n");
+ int fdflags;
+ fdflags = fcntl(sock, F_GETFL);
+ if (fdflags < 0)
+ CtdlLogPrintf(CTDL_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,
+ "unable to set SMTP-Client socket nonblocking flags! %s \n",
+ strerror(errno));
+ }
if (sock < 0) {
if (errno > 0) {
snprintf(dsn, SIZ, "%s", strerror(errno));
CCC->sPos = NULL;
/* Process the SMTP greeting from the server */
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP conversation");
goto bail;
snprintf(buf, sizeof buf, "EHLO %s\r\n", config.c_fqdn);
CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP HELO");
goto bail;
snprintf(buf, sizeof buf, "HELO %s\r\n", config.c_fqdn);
CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP HELO");
goto bail;
snprintf(buf, sizeof buf, "AUTH PLAIN %s\r\n", encoded);
CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP AUTH");
goto bail;
snprintf(buf, sizeof buf, "MAIL FROM:<%s>\r\n", envelope_from);
CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP MAIL");
goto bail;
snprintf(buf, sizeof buf, "RCPT TO:<%s@%s>\r\n", user, node);
CtdlLogPrintf(CTDL_DEBUG, ">%s", buf);
sock_write(&sock, buf, strlen(buf));
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP RCPT");
goto bail;
/* RCPT succeeded, now try the DATA command */
CtdlLogPrintf(CTDL_DEBUG, ">DATA\n");
sock_write(&sock, "DATA\r\n", 6);
- if (ml_sock_gets(&sock, buf) < 0) {
+ if (ml_sock_gets(&sock, buf, 5) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP DATA");
goto bail;
}
sock_write(&sock, ".\r\n", 3);
- if (ml_sock_gets(&sock, buf) < 0) {
+ tcdrain(sock);
+ if (ml_sock_gets(&sock, buf, 90) < 0) {
*status = 4;
strcpy(dsn, "Connection broken during SMTP message transmit");
goto bail;
CtdlLogPrintf(CTDL_DEBUG, ">QUIT\n");
sock_write(&sock, "QUIT\r\n", 6);
- ml_sock_gets(&sock, buf);
+ ml_sock_gets(&sock, buf, 1);
CtdlLogPrintf(CTDL_DEBUG, "<%s\n", buf);
CtdlLogPrintf(CTDL_INFO, "SMTP client: delivery to <%s> @ <%s> (%s) succeeded\n",
user, node, name);
/*
- * smtp_do_queue()
+ * smtp_queue_thread()
*
* Run through the queue sending out messages.
*/
-void *smtp_do_queue(void *arg) {
+void *smtp_queue_thread(void *arg) {
int num_processed = 0;
struct CitContext smtp_queue_CC;
CtdlFillSystemContext(&smtp_queue_CC, "SMTP Send");
- citthread_setspecific(MyConKey, (void *)&smtp_queue_CC );
- CtdlLogPrintf(CTDL_INFO, "SMTP client: processing outbound queue\n");
+ citthread_setspecific(MyConKey, (void *)&smtp_queue_CC);
+ CtdlLogPrintf(CTDL_DEBUG, "smtp_queue_thread() initializing\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);
- }
+ while (!CtdlThreadCheckStop()) {
+
+ CtdlLogPrintf(CTDL_INFO, "SMTP client: processing outbound queue\n");
- citthread_mutex_unlock (&smtp_send_lock);
- CtdlLogPrintf(CTDL_INFO, "SMTP client: queue run completed; %d messages processed\n", num_processed);
+ 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);
+ }
CtdlClearSystemContext();
return(NULL);
-/*
- * smtp_queue_thread
- *
- * Create a thread to run the SMTP queue
- *
- * This was created as a response to a situation seen on Uncensored where a bad remote was holding
- * up SMTP sending for long times.
- * Converting to a thread does not fix the problem caused by the bad remote but it does prevent
- * the SMTP sending from stopping housekeeping and the EVT_TIMER event system which in turn prevented
- * other things from happening.
- */
-void smtp_queue_thread (void)
-{
- if (citthread_mutex_trylock (&smtp_send_lock)) {
- CtdlLogPrintf(CTDL_DEBUG, "SMTP queue run already in progress\n");
- }
- else {
- CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, smtp_do_queue, NULL);
- }
-}
-
-
-
-void smtp_server_going_down (void)
-{
- CtdlLogPrintf(CTDL_DEBUG, "SMTP module clean up for shutdown.\n");
-
- citthread_mutex_destroy (&smtp_send_lock);
-}
-
-
-
/*****************************************************************************/
/* SMTP UTILITY COMMANDS */
/*****************************************************************************/
CitadelServiceSMTP_LMTP_UNF);
smtp_init_spoolout();
- CtdlRegisterSessionHook(smtp_queue_thread, EVT_TIMER);
CtdlRegisterSessionHook(smtp_cleanup_function, EVT_STOP);
CtdlRegisterProtoHook(cmd_smtp, "SMTP", "SMTP utility commands");
- CtdlRegisterCleanupHook (smtp_server_going_down);
- citthread_mutex_init (&smtp_send_lock, NULL);
+ CtdlThreadCreate("SMTP Send", CTDLTHREAD_BIGSTACK, smtp_queue_thread, NULL);
}
/* return our Subversion id for the Log */
- return "$Id$";
+ return "smtp";
}