Back to index

citadel  8.12
Classes | Defines | Typedefs | Functions | Variables
smtpqueue.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _mailq_entry
struct  queueitem
struct  __QItemHandlerStruct

Defines

#define MaxAttempts   15

Typedefs

typedef struct _mailq_entry MailQEntry
typedef struct queueitem OneQueItem
typedef void(* QItemHandler )(OneQueItem *Item, StrBuf *Line, const char **Pos)
typedef struct __QItemHandlerStruct QItemHandlerStruct

Functions

int DecreaseQReference (OneQueItem *MyQItem)
void DecreaseShutdownDeliveries (OneQueItem *MyQItem)
int GetShutdownDeliveries (OneQueItem *MyQItem)
void RemoveQItem (OneQueItem *MyQItem)
int CountActiveQueueEntries (OneQueItem *MyQItem)
StrBuf * SerializeQueueItem (OneQueItem *MyQItem)
void smtpq_do_bounce (OneQueItem *MyQItem, StrBuf *OMsgTxt)
int CheckQEntryIsBounce (MailQEntry *ThisItem)

Variables

const unsigned short DefaultMXPort

Class Documentation

struct _mailq_entry

Definition at line 27 of file smtpqueue.h.

Class Members
int Active
int n
StrBuf * Recipient
int Status 0 = No delivery has yet been attempted 2 = Delivery was successful 3 = Transient error like connection problem. Try next remote if available. 4 = A transient error was experienced ... try again later 5 = Delivery to this address failed permanently. The error message should be placed in the fourth field so that a bounce message may be generated.
StrBuf * StatusMessage
struct queueitem

Definition at line 45 of file smtpqueue.h.

Collaboration diagram for queueitem:
Class Members
long ActiveDeliveries
StrBuf * BounceTo
MailQEntry * Current
StrBuf * EnvelopeFrom
int FailNow
ParsedURL * FallBackHost
HashList * MailQEntries
long MessageID
long NotYetShutdownDeliveries
long QueMsgID
time_t ReattemptWhen
time_t Retry
long SendBounceMail
StrBuf * SenderRoom
long Submitted
ParsedURL * URL
struct __QItemHandlerStruct

Definition at line 71 of file smtpqueue.h.

Collaboration diagram for __QItemHandlerStruct:
Class Members
QItemHandler H

Define Documentation

#define MaxAttempts   15

Definition at line 24 of file smtpqueue.h.


Typedef Documentation

typedef struct _mailq_entry MailQEntry
typedef struct queueitem OneQueItem
typedef void(* QItemHandler)(OneQueItem *Item, StrBuf *Line, const char **Pos)

Definition at line 68 of file smtpqueue.h.


Function Documentation

int CheckQEntryIsBounce ( MailQEntry ThisItem)

Definition at line 237 of file serv_smtpqueue.c.

{
       if ((ThisItem->Status == 3) ||
           (ThisItem->Status == 4) ||
           (ThisItem->Status == 5))
       {
              return 1;
       }
       else
              return 0;
}      

Here is the caller graph for this function:

int CountActiveQueueEntries ( OneQueItem MyQItem)

Definition at line 249 of file serv_smtpqueue.c.

{
       HashPos  *It;
       long len;
       long ActiveDeliveries;
       const char *Key;
       void *vQE;

       ActiveDeliveries = 0;
       It = GetNewHashPos(MyQItem->MailQEntries, 0);
       while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE))
       {
              MailQEntry *ThisItem = vQE;

              if (CheckQEntryActive(ThisItem))
              {
                     ActiveDeliveries++;
                     ThisItem->Active = 1;
              }
              else
                     ThisItem->Active = 0;
       }
       DeleteHashPos(&It);
       return ActiveDeliveries;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int DecreaseQReference ( OneQueItem MyQItem)

Definition at line 135 of file serv_smtpqueue.c.

{
       int IDestructQueItem;

       pthread_mutex_lock(&ActiveQItemsLock);
       MyQItem->ActiveDeliveries--;
       IDestructQueItem = MyQItem->ActiveDeliveries == 0;
       pthread_mutex_unlock(&ActiveQItemsLock);
       return IDestructQueItem;
}

Here is the caller graph for this function:

Definition at line 146 of file serv_smtpqueue.c.

{
       pthread_mutex_lock(&ActiveQItemsLock);
       MyQItem->NotYetShutdownDeliveries--;
       pthread_mutex_unlock(&ActiveQItemsLock);
}
int GetShutdownDeliveries ( OneQueItem MyQItem)

Definition at line 153 of file serv_smtpqueue.c.

{
       int DestructNow;

       pthread_mutex_lock(&ActiveQItemsLock);
       DestructNow = MyQItem->ActiveDeliveries == 0;
       pthread_mutex_unlock(&ActiveQItemsLock);
       return DestructNow;
}
void RemoveQItem ( OneQueItem MyQItem)

Definition at line 162 of file serv_smtpqueue.c.

{
       long len;
       const char* Key;
       void *VData;
       HashPos  *It;

       pthread_mutex_lock(&ActiveQItemsLock);
       It = GetNewHashPos(ActiveQItems, 0);
       if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It))
              DeleteEntryFromHash(ActiveQItems, It);
       else
       {
              SMTPC_syslog(LOG_WARNING,
                          "unable to find QItem with ID[%ld]",
                          MyQItem->MessageID);
              while (GetNextHashPos(ActiveQItems, It, &len, &Key, &VData))
                     SMTPC_syslog(LOG_WARNING,
                                 "have_: ID[%ld]",
                                 ((OneQueItem *)VData)->MessageID);
       }
       pthread_mutex_unlock(&ActiveQItemsLock);
       DeleteHashPos(&It);
}

Here is the caller graph for this function:

StrBuf* SerializeQueueItem ( OneQueItem MyQItem)

Definition at line 333 of file serv_smtpqueue.c.

{
       StrBuf *QMessage;
       HashPos  *It;
       const char *Key;
       long len;
       void *vQE;

       QMessage = NewStrBufPlain(NULL, SIZ);
       StrBufPrintf(QMessage, "Content-type: %s\n", SPOOLMIME);
//     "attempted|%ld\n"  "retry|%ld\n",, (long)time(NULL), (long)retry );
       StrBufAppendBufPlain(QMessage, HKEY("\nmsgid|"), 0);
       StrBufAppendPrintf(QMessage, "%ld", MyQItem->MessageID);

       StrBufAppendBufPlain(QMessage, HKEY("\nsubmitted|"), 0);
       StrBufAppendPrintf(QMessage, "%ld", MyQItem->Submitted);

       if (StrLength(MyQItem->BounceTo) > 0) {
              StrBufAppendBufPlain(QMessage, HKEY("\nbounceto|"), 0);
              StrBufAppendBuf(QMessage, MyQItem->BounceTo, 0);
       }

       if (StrLength(MyQItem->EnvelopeFrom) > 0) {
              StrBufAppendBufPlain(QMessage, HKEY("\nenvelope_from|"), 0);
              StrBufAppendBuf(QMessage, MyQItem->EnvelopeFrom, 0);
       }

       if (StrLength(MyQItem->SenderRoom) > 0) {
              StrBufAppendBufPlain(QMessage, HKEY("\nsource_room|"), 0);
              StrBufAppendBuf(QMessage, MyQItem->SenderRoom, 0);
       }

       StrBufAppendBufPlain(QMessage, HKEY("\nretry|"), 0);
       StrBufAppendPrintf(QMessage, "%ld",
                        MyQItem->Retry);

       StrBufAppendBufPlain(QMessage, HKEY("\nattempted|"), 0);
       StrBufAppendPrintf(QMessage, "%ld",
                        time(NULL) /*ctdl_ev_now()*/ + MyQItem->Retry);

       It = GetNewHashPos(MyQItem->MailQEntries, 0);
       while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE))
       {
              MailQEntry *ThisItem = vQE;

              StrBufAppendBufPlain(QMessage, HKEY("\nremote|"), 0);
              StrBufAppendBuf(QMessage, ThisItem->Recipient, 0);
              StrBufAppendBufPlain(QMessage, HKEY("|"), 0);
              StrBufAppendPrintf(QMessage, "%d", ThisItem->Status);
              StrBufAppendBufPlain(QMessage, HKEY("|"), 0);
              StrBufAppendBuf(QMessage, ThisItem->StatusMessage, 0);
       }
       DeleteHashPos(&It);
       StrBufAppendBufPlain(QMessage, HKEY("\n"), 0);
       return QMessage;
}

Here is the caller graph for this function:

void smtpq_do_bounce ( OneQueItem MyQItem,
StrBuf *  OMsgTxt 
)

Definition at line 508 of file serv_smtpqueue.c.

{
       static int seq = 0;

       struct CtdlMessage *bmsg = NULL;
       StrBuf *boundary;
       StrBuf *Msg = NULL;
       StrBuf *BounceMB;
       struct recptypes *valid;
       time_t now;

       HashPos *It;
       void *vQE;
       long len;
       const char *Key;

       int first_attempt = 0;
       int successful_bounce = 0;
       int num_bounces = 0;
       int give_up = 0;

       SMTPCM_syslog(LOG_DEBUG, "smtp_do_bounce() called\n");

       if (MyQItem->SendBounceMail == 0)
              return;

       now = time (NULL); //ev_time();

       if ( (now - MyQItem->Submitted) > SMTP_GIVE_UP ) {
              give_up = 1;
       }

       if (MyQItem->Retry == SMTP_RETRY_INTERVAL) {
              first_attempt = 1;
       }

       /*
        * Now go through the instructions checking for stuff.
        */
       Msg = NewStrBufPlain(NULL, 1024);
       It = GetNewHashPos(MyQItem->MailQEntries, 0);
       while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE))
       {
              MailQEntry *ThisItem = vQE;
              if ((ThisItem->Active && (ThisItem->Status == 5)) || /* failed now? */
                  ((give_up == 1) && (ThisItem->Status != 2)) ||
                  ((first_attempt == 1) && (ThisItem->Status != 2)))
                     /* giving up after failed attempts... */
              {
                     ++num_bounces;

                     StrBufAppendBuf(Msg, ThisItem->Recipient, 0);
                     StrBufAppendBufPlain(Msg, HKEY(": "), 0);
                     StrBufAppendBuf(Msg, ThisItem->StatusMessage, 0);
                     StrBufAppendBufPlain(Msg, HKEY("\r\n"), 0);
              }
       }
       DeleteHashPos(&It);

       /* Deliver the bounce if there's anything worth mentioning */
       SMTPC_syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces);

       if (num_bounces == 0) {
              FreeStrBuf(&Msg);
              return;
       }

       boundary = NewStrBufPlain(HKEY("=_Citadel_Multipart_"));
       StrBufAppendPrintf(boundary,
                        "%s_%04x%04x",
                        config.c_fqdn,
                        getpid(),
                        ++seq);

       /* Start building our bounce message; go shopping for memory first. */
       BounceMB = NewStrBufPlain(
              NULL,
              1024 + /* mime stuff.... */
              StrLength(Msg) +  /* the bounce information... */
              StrLength(OMsgTxt)); /* the original message */
       if (BounceMB == NULL) {
              FreeStrBuf(&boundary);
              SMTPCM_syslog(LOG_ERR, "Failed to alloc() bounce message.\n");

              return;
       }

       bmsg = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage));
       if (bmsg == NULL) {
              FreeStrBuf(&boundary);
              FreeStrBuf(&BounceMB);
              SMTPCM_syslog(LOG_ERR, "Failed to alloc() bounce message.\n");

              return;
       }
       memset(bmsg, 0, sizeof(struct CtdlMessage));


       StrBufAppendBufPlain(BounceMB, HKEY("Content-type: multipart/mixed; boundary=\""), 0);
       StrBufAppendBuf(BounceMB, boundary, 0);
       StrBufAppendBufPlain(BounceMB, HKEY("\"\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("MIME-Version: 1.0\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("X-Mailer: " CITADEL "\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("\r\nThis is a multipart message in MIME format.\r\n\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("--"), 0);
       StrBufAppendBuf(BounceMB, boundary, 0);
       StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("Content-type: text/plain\r\n\r\n"), 0);

       if (give_up)
              StrBufAppendBufPlain(
                     BounceMB,
                     HKEY(
                            "A message you sent could not be delivered "
                            "to some or all of its recipients\n"
                            "due to prolonged unavailability "
                            "of its destination(s).\n"
                            "Giving up on the following addresses:\n\n"
                            ), 0);
       else
              StrBufAppendBufPlain(
                     BounceMB,
                     HKEY(
                            "A message you sent could not be delivered "
                            "to some or all of its recipients.\n"
                            "The following addresses "
                            "were undeliverable:\n\n"
                            ), 0);

       StrBufAppendBuf(BounceMB, Msg, 0);
       FreeStrBuf(&Msg);

       if (StrLength(MyQItem->SenderRoom) > 0)
       {
              StrBufAppendBufPlain(
                     BounceMB,
                     HKEY("The message was originaly posted in: "), 0);
              StrBufAppendBuf(BounceMB, MyQItem->SenderRoom, 0);
              StrBufAppendBufPlain(
                     BounceMB,
                     HKEY("\n"), 0);
       }

       /* Attach the original message */
       StrBufAppendBufPlain(BounceMB, HKEY("\r\n--"), 0);
       StrBufAppendBuf(BounceMB, boundary, 0);
       StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0);
       StrBufAppendBufPlain(BounceMB,
                          HKEY("Content-type: message/rfc822\r\n"), 0);
       StrBufAppendBufPlain(BounceMB,
                          HKEY("Content-Transfer-Encoding: 7bit\r\n"), 0);
       StrBufAppendBufPlain(BounceMB,
                          HKEY("Content-Disposition: inline\r\n"), 0);
       StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0);
       StrBufAppendBuf(BounceMB, OMsgTxt, 0);

       /* Close the multipart MIME scope */
       StrBufAppendBufPlain(BounceMB, HKEY("--"), 0);
       StrBufAppendBuf(BounceMB, boundary, 0);
       StrBufAppendBufPlain(BounceMB, HKEY("--\r\n"), 0);

       bmsg->cm_magic = CTDLMESSAGE_MAGIC;
       bmsg->cm_anon_type = MES_NORMAL;
       bmsg->cm_format_type = FMT_RFC822;

       bmsg->cm_fields['O'] = strdup(MAILROOM);
       bmsg->cm_fields['A'] = strdup("Citadel");
       bmsg->cm_fields['N'] = strdup(config.c_nodename);
       bmsg->cm_fields['U'] = strdup("Delivery Status Notification (Failure)");
       bmsg->cm_fields['M'] = SmashStrBuf(&BounceMB);

       /* First try the user who sent the message */
       if (StrLength(MyQItem->BounceTo) == 0) {
              SMTPCM_syslog(LOG_ERR, "No bounce address specified\n");
       }
       else {
              SMTPC_syslog(LOG_DEBUG, "bounce to user? <%s>\n",
                     ChrPtr(MyQItem->BounceTo));
       }

       /* Can we deliver the bounce to the original sender? */
       valid = validate_recipients(ChrPtr(MyQItem->BounceTo), NULL, 0);
       if ((valid != NULL) && (valid->num_error == 0)) {
              CtdlSubmitMsg(bmsg, valid, "", QP_EADDR);
              successful_bounce = 1;
       }

       /* If not, post it in the Aide> room */
       if (successful_bounce == 0) {
              CtdlSubmitMsg(bmsg, NULL, config.c_aideroom, QP_EADDR);
       }

       /* Free up the memory we used */
       free_recipients(valid);
       FreeStrBuf(&boundary);
       CtdlFreeMessage(bmsg);
       SMTPCM_syslog(LOG_DEBUG, "Done processing bounces\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const unsigned short DefaultMXPort

Definition at line 97 of file serv_smtpqueue.c.