remove classic smtp client. we're over this.
[citadel.git] / citadel / modules / smtp / serv_smtpeventclient.c
index 2e1dcbbed148ecb9f6d98e773b594f67addef786..22c18628a455b694d210e43299b016c2a745085d 100644 (file)
@@ -90,7 +90,6 @@
 #include "smtpqueue.h"
 #include "smtp_clienthandlers.h"
 
-#ifdef EXPERIMENTAL_SMTP_EVENT_CLIENT
 const unsigned short DefaultMXPort = 25;
 void DeleteSmtpOutMsg(void *v)
 {
@@ -99,8 +98,10 @@ void DeleteSmtpOutMsg(void *v)
        ares_free_data(Msg->AllMX);
        if (Msg->HostLookup.VParsedDNSReply != NULL)
                Msg->HostLookup.DNSReplyFree(Msg->HostLookup.VParsedDNSReply);
+       FreeURL(&Msg->Relay);
        FreeStrBuf(&Msg->msgtext);
        FreeAsyncIOContents(&Msg->IO);
+       memset (Msg, 0, sizeof(SmtpOutMsg)); /* just to be shure... */
        free(Msg);
 }
 
@@ -112,6 +113,9 @@ eNextState SMTP_C_DispatchWriteDone(AsyncIO *IO);
 eNextState SMTP_C_Terminate(AsyncIO *IO);
 eReadState SMTP_C_ReadServerStatus(AsyncIO *IO);
 
+eNextState mx_connect_ip(AsyncIO *IO);
+eNextState get_one_mx_host_ip(AsyncIO *IO);
+
 /******************************************************************************
  * So, we're finished with sending (regardless of success or failure)         *
  * This Message might be referenced by several Queue-Items, if we're the last,*
@@ -120,7 +124,7 @@ eReadState SMTP_C_ReadServerStatus(AsyncIO *IO);
  ******************************************************************************/
 void FinalizeMessageSend(SmtpOutMsg *Msg)
 {
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        
        if (DecreaseQReference(Msg->MyQItem)) 
        {
@@ -155,20 +159,32 @@ void FinalizeMessageSend(SmtpOutMsg *Msg)
 
                RemoveQItem(Msg->MyQItem);
        }
+
+       RemoveContext(Msg->IO.CitContext);
        DeleteSmtpOutMsg(Msg);
 }
 
 eNextState FailOneAttempt(AsyncIO *IO)
 {
+       SmtpOutMsg *SendMsg = IO->Data;
        /* 
         * possible ways here: 
         * - connection timeout 
         * - 
-        */     
+        */
+       StopClientWatchers(IO);
+
+       if (SendMsg->pCurrRelay != NULL)
+               SendMsg->pCurrRelay = SendMsg->pCurrRelay->Next;
+
+       if (SendMsg->pCurrRelay == NULL)
+               return eAbort;
+       if (SendMsg->pCurrRelay->IsIP)
+               return mx_connect_ip(IO);
+       else
+               return get_one_mx_host_ip(IO);
 }
 
-////TODO
-
 
 void SetConnectStatus(AsyncIO *IO)
 {
@@ -179,70 +195,50 @@ void SetConnectStatus(AsyncIO *IO)
 
        buf[0] = '\0';
 
-       if (IO->IP6) {
-               src = &IO->Addr.sin6_addr;
+       if (IO->ConnectMe->IPv6) {
+               src = &IO->ConnectMe->Addr.sin6_addr;
        }
        else {
-               struct sockaddr_in *addr = (struct sockaddr_in *)&IO->Addr;
+               struct sockaddr_in *addr = (struct sockaddr_in *)&IO->ConnectMe->Addr;
 
                src = &addr->sin_addr.s_addr;
        }
 
-       inet_ntop((IO->IP6)?AF_INET6:AF_INET,
+       inet_ntop((IO->ConnectMe->IPv6)?AF_INET6:AF_INET,
                  src,
-                 buf, sizeof(buf));
+                 buf, 
+                 sizeof(buf));
+
        if (SendMsg->mx_host == NULL)
-               SendMsg->mx_host = "<no name>";
+               SendMsg->mx_host = "<no MX-Record>";
 
-       CtdlLogPrintf(CTDL_DEBUG, 
-                     "SMTP client[%ld]: connecting to %s [%s]:%d ...\n", 
-                     SendMsg->n, 
-                     SendMsg->mx_host, 
-                     buf,
-                     SendMsg->IO.dport);
+       syslog(LOG_DEBUG,
+              "SMTP client[%ld]: connecting to %s [%s]:%d ...\n", 
+              SendMsg->n, 
+              SendMsg->mx_host, 
+              buf,
+              SendMsg->IO.ConnectMe->Port);
 
        SendMsg->MyQEntry->Status = 5; 
        StrBufPrintf(SendMsg->MyQEntry->StatusMessage, 
                     "Timeout while connecting %s [%s]:%d ", 
                     SendMsg->mx_host,
                     buf,
-                    SendMsg->IO.dport);
+                    SendMsg->IO.ConnectMe->Port);
+       SendMsg->IO.NextState = eConnect;
 }
 
 /*****************************************************************************
  * So we connect our Relay IP here.                                          *
  *****************************************************************************/
-eNextState mx_connect_relay_ip(AsyncIO *IO)
+eNextState mx_connect_ip(AsyncIO *IO)
 {
-       
        SmtpOutMsg *SendMsg = IO->Data;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
-
-       IO->IP6 = SendMsg->pCurrRelay->af == AF_INET6;
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        
-       if (SendMsg->pCurrRelay->Port != 0)
-               IO->dport = SendMsg->pCurrRelay->Port;
-
-       memset(&IO->Addr, 0, sizeof(struct sockaddr_in6));
-       if (IO->IP6) {
-               memcpy(&IO->Addr.sin6_addr.s6_addr, 
-                      &SendMsg->pCurrRelay->Addr,
-                      sizeof(struct in6_addr));
-
-               IO->Addr.sin6_family = AF_INET6;
-               IO->Addr.sin6_port   = htons(IO->dport);
-       }
-       else {
-               struct sockaddr_in *addr = (struct sockaddr_in*) &IO->Addr;
-               /* Bypass the ns lookup result like this: IO->Addr.sin_addr.s_addr = inet_addr("127.0.0.1"); */
-               memcpy(&addr->sin_addr,///.s_addr, 
-                      &SendMsg->pCurrRelay->Addr,
-                      sizeof(struct in_addr));
-               
-               addr->sin_family = AF_INET;
-               addr->sin_port   = htons(IO->dport);
-       }
+       IO->ConnectMe = SendMsg->pCurrRelay;
+       /*  Bypass the ns lookup result like this: IO->Addr.sin_addr.s_addr = inet_addr("127.0.0.1"); */
 
        SetConnectStatus(IO);
 
@@ -262,21 +258,17 @@ eNextState get_one_mx_host_ip_done(AsyncIO *IO)
        hostent = SendMsg->HostLookup.VParsedDNSReply;
        if ((SendMsg->HostLookup.DNSStatus == ARES_SUCCESS) && 
            (hostent != NULL) ) {
-               
-               IO->IP6  = hostent->h_addrtype == AF_INET6;
-               ////IO->HEnt = hostent;
-
-               memset(&IO->Addr, 0, sizeof(struct in6_addr));
-               if (IO->IP6) {
-                       memcpy(&IO->Addr.sin6_addr.s6_addr, 
+               memset(&SendMsg->pCurrRelay->Addr, 0, sizeof(struct in6_addr));
+               if (SendMsg->pCurrRelay->IPv6) {
+                       memcpy(&SendMsg->pCurrRelay->Addr.sin6_addr.s6_addr, 
                               &hostent->h_addr_list[0],
                               sizeof(struct in6_addr));
                        
-                       IO->Addr.sin6_family = hostent->h_addrtype;
-                       IO->Addr.sin6_port   = htons(IO->dport);
+                       SendMsg->pCurrRelay->Addr.sin6_family = hostent->h_addrtype;
+                       SendMsg->pCurrRelay->Addr.sin6_port   = htons(DefaultMXPort);
                }
                else {
-                       struct sockaddr_in *addr = (struct sockaddr_in*) &IO->Addr;
+                       struct sockaddr_in *addr = (struct sockaddr_in*) &SendMsg->pCurrRelay->Addr;
                        /* Bypass the ns lookup result like this: IO->Addr.sin_addr.s_addr = inet_addr("127.0.0.1"); */
 //                     addr->sin_addr.s_addr = htonl((uint32_t)&hostent->h_addr_list[0]);
                        memcpy(&addr->sin_addr.s_addr, 
@@ -284,37 +276,19 @@ eNextState get_one_mx_host_ip_done(AsyncIO *IO)
                               sizeof(uint32_t));
                        
                        addr->sin_family = hostent->h_addrtype;
-                       addr->sin_port   = htons(IO->dport);
+                       addr->sin_port   = htons(DefaultMXPort);
                        
                }
-               ////SendMsg->IO.HEnt = hostent;
-               SetConnectStatus(IO);
-               return InitEventIO(IO, 
-                                  SendMsg, 
-                                  SMTP_C_ConnTimeout, 
-                                  SMTP_C_ReadTimeouts[0],
-                                  1);
+               SendMsg->mx_host = SendMsg->pCurrRelay->Host;
+               return mx_connect_ip(IO);
        }
        else // TODO: here we need to find out whether there are more mx'es, backup relay, and so on
-               return SMTP_C_Terminate(IO);
+               return FailOneAttempt(IO);
 }
 
-/*
-
-       if (SendMsg->pCurrRelay != NULL) {
-               SendMsg->mx_host = Hostname = SendMsg->pCurrRelay->Host;
-               if (SendMsg->pCurrRelay->Port != 0)
-                       SendMsg->IO.dport = SendMsg->pCurrRelay->Port;
-       }
-               else
-*/
 eNextState get_one_mx_host_ip(AsyncIO *IO)
 {
        SmtpOutMsg * SendMsg = IO->Data;
-       const char *Hostname;
-       //char *endpart;
-       //char buf[SIZ];
-
        /* 
         * here we start with the lookup of one host. it might be...
         * - the relay host *sigh*
@@ -324,19 +298,17 @@ eNextState get_one_mx_host_ip(AsyncIO *IO)
 
        InitC_ares_dns(IO);
 
-       if (SendMsg->mx_host != NULL) Hostname = SendMsg->mx_host;
-       else Hostname = SendMsg->node;
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, 
+              "SMTP client[%ld]: looking up %s-Record %s : %d ...\n", 
+              SendMsg->n, 
+              (SendMsg->pCurrRelay->IPv6)? "aaaa": "a",
+              SendMsg->pCurrRelay->Host, 
+              SendMsg->pCurrRelay->Port);
 
-       CtdlLogPrintf(CTDL_DEBUG, 
-                     "SMTP client[%ld]: looking up %s : %d ...\n", 
-                     SendMsg->n, 
-                     Hostname, 
-                     SendMsg->IO.dport);
-// TODO: ns_t_aaaa
-       if (!QueueQuery(ns_t_a, 
-                       Hostname, 
+       if (!QueueQuery((SendMsg->pCurrRelay->IPv6)? ns_t_aaaa : ns_t_a, 
+                       SendMsg->pCurrRelay->Host, 
                        &SendMsg->IO, 
                        &SendMsg->HostLookup, 
                        get_one_mx_host_ip_done))
@@ -344,8 +316,10 @@ eNextState get_one_mx_host_ip(AsyncIO *IO)
                SendMsg->MyQEntry->Status = 5;
                StrBufPrintf(SendMsg->MyQEntry->StatusMessage, 
                             "No MX hosts found for <%s>", SendMsg->node);
+               SendMsg->IO.NextState = eTerminateConnection;
                return IO->NextState;
        }
+       IO->NextState = eReadDNSReply;
        return IO->NextState;
 }
 
@@ -360,7 +334,7 @@ eNextState smtp_resolve_mx_record_done(AsyncIO *IO)
 
        QueryCbDone(IO);
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        pp = &SendMsg->Relay;
        while ((pp != NULL) && (*pp != NULL) && ((*pp)->Next != NULL))
                pp = &(*pp)->Next;
@@ -370,7 +344,6 @@ eNextState smtp_resolve_mx_record_done(AsyncIO *IO)
        { /* ok, we found mx records. */
                SendMsg->IO.ErrMsg = SendMsg->MyQEntry->StatusMessage;
                
-
                SendMsg->CurrMX    = SendMsg->AllMX 
                                   = IO->DNSQuery->VParsedDNSReply;
                while (SendMsg->CurrMX) {
@@ -381,17 +354,15 @@ eNextState smtp_resolve_mx_record_done(AsyncIO *IO)
                                p = (ParsedURL*) malloc(sizeof(ParsedURL));
                                memset(p, 0, sizeof(ParsedURL));
                                p->IsIP = 0;
-                               p->Port = 25; //// TODO define.
+                               p->Port = DefaultMXPort;
                                p->IPv6 = i == 1;
                                p->Host = SendMsg->CurrMX->host;
                                
                                *pp = p;
-                               pp = &p;
+                               pp = &p->Next;
                        }
                        SendMsg->CurrMX    = SendMsg->CurrMX->next;
                }
-//             SendMsg->mx_host   = SendMsg->CurrMX->host;
-//             SendMsg->CurrMX    = SendMsg->CurrMX->next;
                SendMsg->CXFlags   = SendMsg->CXFlags & F_HAVE_MX;
        }
        else { /* else fall back to the plain hostname */
@@ -402,17 +373,17 @@ eNextState smtp_resolve_mx_record_done(AsyncIO *IO)
                        p = (ParsedURL*) malloc(sizeof(ParsedURL));
                        memset(p, 0, sizeof(ParsedURL));
                        p->IsIP = 0;
-                       p->Port = 25; //// TODO define.
+                       p->Port = DefaultMXPort;
                        p->IPv6 = i == 1;
                        p->Host = SendMsg->node;
                                
                        *pp = p;
                        pp = &p;
                }
-               ///     SendMsg->mx_host   = SendMsg->node;
                SendMsg->CXFlags   = SendMsg->CXFlags & F_DIRECT;
        }
-       (*pp)->Next = SendMsg->MyQItem->FallBackHost;
+       *pp = SendMsg->MyQItem->FallBackHost;
+       SendMsg->pCurrRelay = SendMsg->Relay;
        return get_one_mx_host_ip(IO);
 }
 
@@ -420,7 +391,7 @@ eNextState resolve_mx_records(AsyncIO *IO)
 {
        SmtpOutMsg * SendMsg = IO->Data;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        /* start resolving MX records here. */
        if (!QueueQuery(ns_t_mx, 
                        SendMsg->node, 
@@ -433,7 +404,8 @@ eNextState resolve_mx_records(AsyncIO *IO)
                             "No MX hosts found for <%s>", SendMsg->node);
                return IO->NextState;
        }
-       return eAbort;
+       SendMsg->IO.NextState = eReadDNSReply;
+       return IO->NextState;
 }
 
 
@@ -470,10 +442,8 @@ SmtpOutMsg *new_smtp_outmsg(OneQueItem *MyQItem,
        SendMsg->IO.RecvBuf.Buf   = NewStrBufPlain(NULL, 1024);
        SendMsg->IO.IOBuf         = NewStrBuf();
 
-       SendMsg->IO.sock          = (-1);
        SendMsg->IO.NextState     = eReadMessage;
-       SendMsg->IO.dport         = DefaultMXPort;
-
+       
        return SendMsg;
 }
 
@@ -485,20 +455,25 @@ void smtp_try_one_queue_entry(OneQueItem *MyQItem,
 {
        SmtpOutMsg *SendMsg;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
 
        SendMsg = new_smtp_outmsg(MyQItem, MyQEntry, MsgCount);
        if (KeepMsgText) SendMsg->msgtext = MsgText;
        else             SendMsg->msgtext = NewStrBufDup(MsgText);
        
        if (smtp_resolve_recipients(SendMsg)) {
+               CitContext *SubC;
+               SubC = CloneContext (CC);
+               SubC->session_specific_data = (char*) SendMsg;
+               SendMsg->IO.CitContext = SubC;
+
                if (SendMsg->pCurrRelay == NULL)
                        QueueEventContext(&SendMsg->IO,
                                          resolve_mx_records);
                else { /* oh... via relay host */
                        if (SendMsg->pCurrRelay->IsIP) {
                                QueueEventContext(&SendMsg->IO,
-                                                 mx_connect_relay_ip);
+                                                 mx_connect_ip);
                        }
                        else { /* uneducated admin has chosen to add DNS to the equation... */
                                QueueEventContext(&SendMsg->IO,
@@ -529,8 +504,10 @@ void smtp_try_one_queue_entry(OneQueItem *MyQItem,
 
 void SMTPSetTimeout(eNextState NextTCPState, SmtpOutMsg *pMsg)
 {
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
-       double Timeout;
+       double Timeout = 0.0;
+
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
+
        switch (NextTCPState) {
        case eSendReply:
        case eSendMore:
@@ -550,6 +527,12 @@ void SMTPSetTimeout(eNextState NextTCPState, SmtpOutMsg *pMsg)
                        Timeout += StrLength(pMsg->msgtext) / 1024;
                }
                break;
+       case eSendDNSQuery:
+       case eReadDNSReply:
+       case eDBQuery:
+       case eReadMore:
+       case eReadPayload:
+       case eConnect:
        case eTerminateConnection:
        case eAbort:
                return;
@@ -558,7 +541,7 @@ void SMTPSetTimeout(eNextState NextTCPState, SmtpOutMsg *pMsg)
 }
 eNextState SMTP_C_DispatchReadDone(AsyncIO *IO)
 {
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        SmtpOutMsg *pMsg = IO->Data;
        eNextState rc;
 
@@ -569,7 +552,7 @@ eNextState SMTP_C_DispatchReadDone(AsyncIO *IO)
 }
 eNextState SMTP_C_DispatchWriteDone(AsyncIO *IO)
 {
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        SmtpOutMsg *pMsg = IO->Data;
        eNextState rc;
 
@@ -586,7 +569,7 @@ eNextState SMTP_C_Terminate(AsyncIO *IO)
 {
        SmtpOutMsg *pMsg = IO->Data;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        FinalizeMessageSend(pMsg);
        return eAbort;
 }
@@ -594,7 +577,7 @@ eNextState SMTP_C_Timeout(AsyncIO *IO)
 {
        SmtpOutMsg *pMsg = IO->Data;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        StrBufPlain(IO->ErrMsg, CKEY(ReadErrors[pMsg->State]));
        return FailOneAttempt(IO);
 }
@@ -602,13 +585,13 @@ eNextState SMTP_C_ConnFail(AsyncIO *IO)
 {
        SmtpOutMsg *pMsg = IO->Data;
 
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        StrBufPlain(IO->ErrMsg, CKEY(ReadErrors[pMsg->State]));
        return FailOneAttempt(IO);
 }
 eNextState SMTP_C_Shutdown(AsyncIO *IO)
 {
-       CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__);
+       syslog(LOG_DEBUG, "SMTP: %s\n", __FUNCTION__);
        SmtpOutMsg *pMsg = IO->Data;
 
        pMsg->MyQEntry->Status = 3;
@@ -649,7 +632,6 @@ eReadState SMTP_C_ReadServerStatus(AsyncIO *IO)
        return Finished;
 }
 
-#endif
 CTDL_MODULE_INIT(smtp_eventclient)
 {
        return "smtpeventclient";