Merge branch 'master' of ssh://git.citadel.org/appl/gitroot/citadel
authorWilfried Goesgens <dothebart@citadel.org>
Thu, 12 Sep 2013 20:59:03 +0000 (22:59 +0200)
committerWilfried Goesgens <dothebart@citadel.org>
Thu, 12 Sep 2013 20:59:03 +0000 (22:59 +0200)
Conflicts:
citadel/modules/network/serv_network.c
citadel/modules/smtp/serv_smtp.c
citadel/modules/smtp/smtp_util.c

1  2 
citadel/modules/network/serv_netspool.c
citadel/modules/rssclient/serv_rssclient.c
citadel/modules/smtp/serv_smtp.c
citadel/modules/smtp/smtp_util.c

index 9394091754712c504b4471981402c8abcf2dc1d7,02dbcabb23f3f7664b95a45f63ca001daf57a1fe..be4da12af30317f19d422a5f1ee6f37edb809bcb
@@@ -160,23 -160,7 +160,23 @@@ int HaveSpoolConfig(OneRoomNetCfg* RNCf
        return interested;
  }
  
 +void Netmap_AddMe(struct CtdlMessage *msg, const char *defl, long defllen)
 +{
 +      long node_len;
 +      char buf[SIZ];
  
 +      /* prepend our node to the path */
 +      if (CM_IsEmpty(msg, eMessagePath)) {
 +              CM_SetField(msg, eMessagePath, defl, defllen);
 +      }
 +      node_len = strlen(config.c_nodename);
 +      if (node_len >= SIZ) 
 +              node_len = SIZ - 1;
 +      memcpy(buf, config.c_nodename, node_len);
 +      buf[node_len] = '!';
 +      buf[node_len + 1] = '\0';
 +      CM_PrependToField(msg, eMessagePath, buf, node_len + 1);
 +}
  
  void InspectQueuedRoom(SpoolControl **pSC,
                       RoomProcList *room_to_spool,     
@@@ -424,6 -408,7 +424,6 @@@ void network_process_buffer(char *buffe
        struct recptypes *recp = NULL;
        char target_room[ROOMNAMELEN];
        struct ser_ret sermsg;
 -      char *oldpath = NULL;
        char filename[PATH_MAX];
        FILE *fp;
        const StrBuf *nexthop = NULL;
        for (pos = 3; pos < size; ++pos) {
                field = buffer[pos];
                len = strlen(buffer + pos + 1);
 -              msg->cm_fields[field] = malloc(len + 1);
 -              memcpy (msg->cm_fields[field], buffer+ pos + 1, len + 1);
 +              CM_SetField(msg, field, buffer + pos + 1, len);
                pos = pos + len + 1;
        }
  
        /* Check for message routing */
 -      if (msg->cm_fields['D'] != NULL) {
 -              if (strcasecmp(msg->cm_fields['D'], config.c_nodename)) {
 +      if (!CM_IsEmpty(msg, eDestination)) {
 +              if (strcasecmp(msg->cm_fields[eDestination], config.c_nodename)) {
  
                        /* route the message */
 -                      Buf = NewStrBufPlain(msg->cm_fields['D'], -1);
 +                      Buf = NewStrBufPlain(msg->cm_fields[eDestination], -1);
                        if (CtdlIsValidNode(&nexthop, 
                                            NULL, 
                                            Buf, 
                                            working_ignetcfg, 
                                            the_netmap) == 0) 
                        {
 -                              /* prepend our node to the path */
 -                              if (msg->cm_fields['P'] != NULL) {
 -                                      oldpath = msg->cm_fields['P'];
 -                                      msg->cm_fields['P'] = NULL;
 -                              }
 -                              else {
 -                                      oldpath = strdup("unknown_user");
 -                              }
 -                              size = strlen(oldpath) + SIZ;
 -                              msg->cm_fields['P'] = malloc(size);
 -                              snprintf(msg->cm_fields['P'], size, "%s!%s",
 -                                      config.c_nodename, oldpath);
 -                              free(oldpath);
 +                              Netmap_AddMe(msg, HKEY("unknown_user"));
  
                                /* serialize the message */
 -                              serialize_message(&sermsg, msg);
 +                              CtdlSerializeMessage(&sermsg, msg);
  
                                /* now send it */
                                if (StrLength(nexthop) == 0) {
                                        QN_syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno));
                                }
                                free(sermsg.ser);
 -                              CtdlFreeMessage(msg);
 +                              CM_Free(msg);
                                FreeStrBuf(&Buf);
                                return;
                        }
         * connected that it's inevitable.)
         */
        if (network_usetable(msg) != 0) {
 -              CtdlFreeMessage(msg);
 +              CM_Free(msg);
                return;
        }
  
        /* Learn network topology from the path */
 -      if ((msg->cm_fields['N'] != NULL) && (msg->cm_fields['P'] != NULL)) {
 -              NetworkLearnTopology(msg->cm_fields['N'], 
 -                                   msg->cm_fields['P'], 
 +      if (!CM_IsEmpty(msg, eNodeName) && !CM_IsEmpty(msg, eMessagePath)) {
 +              NetworkLearnTopology(msg->cm_fields[eNodeName], 
 +                                   msg->cm_fields[eMessagePath], 
                                     the_netmap, 
                                     netmap_changed);
        }
        /* Is the sending node giving us a very persuasive suggestion about
         * which room this message should be saved in?  If so, go with that.
         */
 -      if (msg->cm_fields['C'] != NULL) {
 -              safestrncpy(target_room, msg->cm_fields['C'], sizeof target_room);
 +      if (!CM_IsEmpty(msg, eRemoteRoom)) {
 +              safestrncpy(target_room, msg->cm_fields[eRemoteRoom], sizeof target_room);
        }
  
        /* Otherwise, does it have a recipient?  If so, validate it... */
 -      else if (msg->cm_fields['R'] != NULL) {
 -              recp = validate_recipients(msg->cm_fields['R'], NULL, 0);
 +      else if (!CM_IsEmpty(msg, eRecipient)) {
 +              recp = validate_recipients(msg->cm_fields[eRecipient], NULL, 0);
                if (recp != NULL) if (recp->num_error != 0) {
                        network_bounce(msg,
                                "A message you sent could not be delivered due to an invalid address.\n"
        }
  
        /* Our last shot at finding a home for this message is to see if
 -       * it has the O field (Originating room) set.
 +       * it has the eOriginalRoom (O) field (Originating room) set.
         */
 -      else if (msg->cm_fields['O'] != NULL) {
 -              safestrncpy(target_room, msg->cm_fields['O'], sizeof target_room);
 +      else if (!CM_IsEmpty(msg, eOriginalRoom)) {
 +              safestrncpy(target_room, msg->cm_fields[eOriginalRoom], sizeof target_room);
        }
  
        /* Strip out fields that are only relevant during transit */
 -      if (msg->cm_fields['D'] != NULL) {
 -              free(msg->cm_fields['D']);
 -              msg->cm_fields['D'] = NULL;
 -      }
 -      if (msg->cm_fields['C'] != NULL) {
 -              free(msg->cm_fields['C']);
 -              msg->cm_fields['C'] = NULL;
 -      }
 +      CM_FlushField(msg, eDestination);
 +      CM_FlushField(msg, eRemoteRoom);
  
        /* save the message into a room */
        if (PerformNetprocHooks(msg, target_room) == 0) {
                msg->cm_flags = CM_SKIP_HOOKS;
                CtdlSubmitMsg(msg, recp, target_room, 0);
        }
 -      CtdlFreeMessage(msg);
 +      CM_Free(msg);
        free_recipients(recp);
  }
  
@@@ -624,7 -628,7 +624,7 @@@ void network_process_file(char *filenam
        long msgend = (-1L);
        long msgcur = 0L;
        int ch;
+       int nMessages = 0;
  
        fp = fopen(filename, "rb");
        if (fp == NULL) {
                }
  
                ++msgcur;
+               nMessages ++;
        }
  
        msgend = msgcur - 1;
                                        working_ignetcfg,
                                        the_netmap,
                                        netmap_changed);
+               nMessages ++;
        }
  
+       if (nMessages > 0)
+               QN_syslog(LOG_INFO,
+                         "network: processed %d messages in %s\n",
+                         nMessages,
+                         filename);
        fclose(fp);
        unlink(filename);
  }
index 374d53d4c0cc319d112bdbaca8ed40301ca89768,d31a59af4dbe19283cd31dd98217e7e9e128968f..701f9717b80cdfc8c95258c8aba847f74bc10619
@@@ -290,6 -290,6 +290,8 @@@ int rss_format_item(AsyncIO *IO, networ
                return 0;
        }
  
++      memset(&SaveMsg->Msg, 0, sizeof (struct CtdlMessage));
++
        if (SaveMsg->author_or_creator != NULL) {
  
                char *From;
                if (!FromAt && StrLength (SaveMsg->author_email) > 0)
                {
                        StrBufRFC2047encode(&Encoded, SaveMsg->author_or_creator);
 -                      SaveMsg->Msg.cm_fields['A'] = SmashStrBuf(&Encoded);
 -                      SaveMsg->Msg.cm_fields['P'] =
 -                              SmashStrBuf(&SaveMsg->author_email);
 +                      CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &Encoded);
 +                      CM_SetAsFieldSB(&SaveMsg->Msg, eMessagePath, &SaveMsg->author_email);
                }
                else
                {
                        if (FromAt)
                        {
 -                              SaveMsg->Msg.cm_fields['A'] =
 -                                      SmashStrBuf(&SaveMsg->author_or_creator);
 -                              SaveMsg->Msg.cm_fields['P'] =
 -                                      strdup(SaveMsg->Msg.cm_fields['A']);
 +                              CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &SaveMsg->author_or_creator);
 +                              CM_CopyField(&SaveMsg->Msg, eMessagePath, eAuthor);
                        }
                        else
                        {
                                StrBufRFC2047encode(&Encoded,
                                                    SaveMsg->author_or_creator);
 -                              SaveMsg->Msg.cm_fields['A'] =
 -                                      SmashStrBuf(&Encoded);
 -                              SaveMsg->Msg.cm_fields['P'] =
 -                                      strdup("rss@localhost");
 +                              CM_SetAsFieldSB(&SaveMsg->Msg, eAuthor, &Encoded);
 +                              CM_SetField(&SaveMsg->Msg, eMessagePath, HKEY("rss@localhost"));
  
                        }
                }
        }
        else {
 -              SaveMsg->Msg.cm_fields['A'] = strdup("rss");
 +              CM_SetField(&SaveMsg->Msg, eAuthor, HKEY("rss"));
        }
  
 -      SaveMsg->Msg.cm_fields['N'] = strdup(NODENAME);
 +      CM_SetField(&SaveMsg->Msg, eNodeName, NODENAME, strlen(NODENAME));
        if (SaveMsg->title != NULL) {
                long len;
                char *Sbj;
                StrBufTrim(Encoded);
                StrBufRFC2047encode(&QPEncoded, Encoded);
  
 -              SaveMsg->Msg.cm_fields['U'] = SmashStrBuf(&QPEncoded);
 +              CM_SetAsFieldSB(&SaveMsg->Msg, eMsgSubject, &QPEncoded);
                FreeStrBuf(&Encoded);
        }
        if (SaveMsg->link == NULL)
@@@ -393,8 -398,8 +395,8 @@@ eNextState RSSSaveMessage(AsyncIO *IO
  
        if (rss_format_item(IO, RSSAggr->ThisMsg))
        {
 -              RSSAggr->ThisMsg->Msg.cm_fields['M'] =
 -                      SmashStrBuf(&RSSAggr->ThisMsg->Message);
 +              CM_SetAsFieldSB(&RSSAggr->ThisMsg->Msg, eMesageText,
 +                                     &RSSAggr->ThisMsg->Message);
  
                CtdlSubmitMsg(&RSSAggr->ThisMsg->Msg, &RSSAggr->recp, NULL, 0);
                
index d96cda9bd84eb8b1d3870b75bea230b32df0960d,be6347466270576c957d1610d8c29e1d3b5a961c..4eec7e85d5852400de7e4cb750b189082c7eef48
   * The VRFY and EXPN commands have been removed from this implementation
   * because nobody uses these commands anymore, except for spammers.
   *
-  * Copyright (c) 1998-2012 by the citadel.org team
+  * Copyright (c) 1998-2013 by the citadel.org team
   *
-  *  This program is open source software; you can redistribute it and/or modify
-  *  it under the terms of the GNU General Public License version 3.
+  * This program is open source software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 3.
   *  
-  *  This program is distributed in the hope that it will be useful,
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  *  GNU General Public License for more details.
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
   */
  
  #include "sysdep.h"
@@@ -69,7 -69,6 +69,7 @@@
  #include "config.h"
  #include "control.h"
  #include "user_ops.h"
 +#include "room_ops.h"
  #include "database.h"
  #include "msgbase.h"
  #include "internet_addressing.h"
@@@ -148,6 -147,8 +148,8 @@@ void smtp_greeting(int is_msa
        sSMTP->from = NewStrBufPlain(NULL, SIZ);
        sSMTP->recipients = NewStrBufPlain(NULL, SIZ);
        sSMTP->OneRcpt = NewStrBufPlain(NULL, SIZ);
+       sSMTP->preferred_sender_email = NULL;
+       sSMTP->preferred_sender_name = NULL;
  
        /* If this config option is set, reject connections from problem
         * addresses immediately instead of after they execute a RCPT
@@@ -321,14 -322,12 +323,14 @@@ void smtp_webcit_preferences_hack_backe
                return;
        }
  
 -      if ( (msg->cm_fields['U']) && (!strcasecmp(msg->cm_fields['U'], "__ WebCit Preferences __")) ) {
 +      if ( !CM_IsEmpty(msg, eMsgSubject) &&
 +           (!strcasecmp(msg->cm_fields[eMsgSubject], "__ WebCit Preferences __")))
 +      {
                /* This is it!  Change ownership of the message text so it doesn't get freed. */
 -              *webcit_conf = (char *)msg->cm_fields['M'];
 -              msg->cm_fields['M'] = NULL;
 +              *webcit_conf = (char *)msg->cm_fields[eMesageText];
 +              msg->cm_fields[eMesageText] = NULL;
        }
 -      CtdlFreeMessage(msg);
 +      CM_Free(msg);
  }
  
  
  void smtp_webcit_preferences_hack(void) {
        char config_roomname[ROOMNAMELEN];
        char *webcit_conf = NULL;
+       citsmtp *sSMTP = SMTP;
  
        snprintf(config_roomname, sizeof config_roomname, "%010ld.%s", CC->user.usernum, USERCONFIGROOM);
        if (CtdlGetRoom(&CC->room, config_roomname) != 0) {
                return;
        }
  
-       /* FIXME : now do something with this data */
+       /* Parse the webcit configuration and attempt to do something useful with it */
+       char *str = webcit_conf;
+       char *saveptr = str;
+       char *this_line = NULL;
+       while (this_line = strtok_r(str, "\n", &saveptr), this_line != NULL) {
+               str = NULL;
+               if (!strncasecmp(this_line, "defaultfrom|", 12)) {
+                       sSMTP->preferred_sender_email = NewStrBufPlain(&this_line[12], -1);
+               }
+               if (!strncasecmp(this_line, "defaultname|", 12)) {
+                       sSMTP->preferred_sender_name = NewStrBufPlain(&this_line[12], -1);
+               }
+               if ((!strncasecmp(this_line, "defaultname|", 12)) && (sSMTP->preferred_sender_name == NULL)) {
+                       sSMTP->preferred_sender_name = NewStrBufPlain(&this_line[12], -1);
+               }
  
+       }
        free(webcit_conf);
-       abort();
  }
  
  
@@@ -447,7 -461,7 +464,7 @@@ void smtp_try_plain(long offset, long F
  
        if (result == login_ok) {
                if (CtdlTryPassword(pass, len) == pass_ok) {
////                  smtp_webcit_preferences_hack();
                      smtp_webcit_preferences_hack();
                        smtp_auth_greeting(offset, Flags);
                        return;
                }
@@@ -816,12 -830,12 +833,12 @@@ void smtp_data(long offset, long flags
        if ( (CCC->logged_in) && (config.c_rfc822_strict_from != CFG_SMTP_FROM_NOFILTER) ) {
                int validemail = 0;
                
 -              if (!IsEmptyStr(msg->cm_fields['F'])       &&
 +              if (!CM_IsEmpty(msg, erFc822Addr)       &&
                    ((config.c_rfc822_strict_from == CFG_SMTP_FROM_CORRECT) || 
                     (config.c_rfc822_strict_from == CFG_SMTP_FROM_REJECT)    )  )
                {
                        if (!IsEmptyStr(CCC->cs_inet_email))
 -                              validemail = strcmp(CCC->cs_inet_email, msg->cm_fields['F']) == 0;
 +                              validemail = strcmp(CCC->cs_inet_email, msg->cm_fields[erFc822Addr]) == 0;
                        if ((!validemail) && 
                            (!IsEmptyStr(CCC->cs_inet_other_emails)))
                        {
                                for (i=0; i < num_secondary_emails && !validemail; ++i) {
                                        char buf[256];
                                        extract_token(buf, CCC->cs_inet_other_emails,i,'|',sizeof CCC->cs_inet_other_emails);
 -                                      validemail = strcmp(buf, msg->cm_fields['F']) == 0;
 +                                      validemail = strcmp(buf, msg->cm_fields[erFc822Addr]) == 0;
                                }
                        }
                }
  
                if (!validemail && (config.c_rfc822_strict_from == CFG_SMTP_FROM_REJECT)) {
 -                      syslog(LOG_ERR, "invalid sender '%s' - rejecting this message", msg->cm_fields['F']);
 -                      cprintf("550 Invalid sender '%s' - rejecting this message.\r\n", msg->cm_fields['F']);
 +                      syslog(LOG_ERR, "invalid sender '%s' - rejecting this message", msg->cm_fields[erFc822Addr]);
 +                      cprintf("550 Invalid sender '%s' - rejecting this message.\r\n", msg->cm_fields[erFc822Addr]);
                        return;
                }
  
-               CM_SetField(msg, eAuthor, CCC->user.fullname, strlen(CCC->user.fullname));
 -              if (msg->cm_fields['A'] != NULL) free(msg->cm_fields['A']);
 -              if (msg->cm_fields['N'] != NULL) free(msg->cm_fields['N']);
 -              if (msg->cm_fields['H'] != NULL) free(msg->cm_fields['H']);
 -              if (msg->cm_fields['O'] != NULL) free(msg->cm_fields['O']);
 -              msg->cm_fields['N'] = strdup(config.c_nodename);
 -              msg->cm_fields['H'] = strdup(config.c_humannode);
 -              msg->cm_fields['O'] = strdup(MAILROOM);
 -
 -              msg->cm_fields['A'] =
 -                      ((sSMTP->preferred_sender_name != NULL)
 -                      ? strdup(ChrPtr(sSMTP->preferred_sender_name)) 
 -                      : strdup(CCC->user.fullname)
 -              );
 +              CM_SetField(msg, eNodeName, config.c_nodename, strlen(config.c_nodename));
 +              CM_SetField(msg, eHumanNode, config.c_humannode, strlen(config.c_humannode));
 +              CM_SetField(msg, eOriginalRoom, HKEY(MAILROOM));
++              if (sSMTP->preferred_sender_name != NULL)
++                      CM_SetFieldSB(msg, eAuthor, sSMTP->preferred_sender_name);
++              else 
++                      CM_SetField(msg, eAuthor, CCC->user.fullname, strlen(CCC->user.fullname));
  
                if (!validemail) {
-                       CM_SetField(msg, erFc822Addr, CCC->cs_inet_email, strlen(CCC->cs_inet_email));
 -                      if (msg->cm_fields['F'] != NULL) free(msg->cm_fields['F']);
 -                      msg->cm_fields['F'] = 
 -                              ((sSMTP->preferred_sender_email != NULL)
 -                              ? strdup(ChrPtr(sSMTP->preferred_sender_email)) 
 -                              : strdup(CCC->cs_inet_email)
 -                      );
++                      if((sSMTP->preferred_sender_email != NULL)
++                              CM_SetFieldSB(msg, erFc822Addr, sSMTP->preferred_sender_email)) 
++                      else
++                              CM_SetField(msg, erFc822Addr, CCC->cs_inet_email, strlen(CCC->cs_inet_email));
                }
        }
  
        /* Set the "envelope from" address */
 -      if (msg->cm_fields['P'] != NULL) {
 -              free(msg->cm_fields['P']);
 -      }
 -      msg->cm_fields['P'] = strdup(ChrPtr(sSMTP->from));
 +      CM_SetField(msg, eMessagePath, SKEY(sSMTP->from));
  
        /* Set the "envelope to" address */
 -      if (msg->cm_fields['V'] != NULL) {
 -              free(msg->cm_fields['V']);
 -      }
 -      msg->cm_fields['V'] = strdup(ChrPtr(sSMTP->recipients));
 +      CM_SetField(msg, eenVelopeTo, SKEY(sSMTP->recipients));
  
        /* Submit the message into the Citadel system. */
        valid = validate_recipients(
  
        if (scan_errors > 0) {  /* We don't want this message! */
  
 -              if (msg->cm_fields['0'] == NULL) {
 -                      msg->cm_fields['0'] = strdup("Message rejected by filter");
 +              if (CM_IsEmpty(msg, eErrorMsg)) {
 +                      CM_SetField(msg, eErrorMsg, HKEY("Message rejected by filter"));
                }
  
 -              StrBufPrintf(sSMTP->OneRcpt, "550 %s\r\n", msg->cm_fields['0']);
 +              StrBufPrintf(sSMTP->OneRcpt, "550 %s\r\n", msg->cm_fields[eErrorMsg]);
        }
        
        else {                  /* Ok, we'll accept this message. */
        );
  
        /* Clean up */
 -      CtdlFreeMessage(msg);
 +      CM_Free(msg);
        free_recipients(valid);
        smtp_data_clear(0, 0);  /* clear out the buffers now */
  }
@@@ -1048,6 -1082,8 +1071,8 @@@ void smtp_cleanup_function(void
        FreeStrBuf(&sSMTP->from);
        FreeStrBuf(&sSMTP->recipients);
        FreeStrBuf(&sSMTP->OneRcpt);
+       FreeStrBuf(&sSMTP->preferred_sender_email);
+       FreeStrBuf(&sSMTP->preferred_sender_name);
  
        free(sSMTP);
  }
index d6633fb564799bc3051fa614a021b95c9b663c54,1c57d99595de161d134ac06a597fe3b5ac30c4a5..dae60b6daf14a8d46f2c457d9fbcfd69ddca4302
@@@ -161,10 -161,10 +161,10 @@@ void smtp_do_bounce(char *instr, StrBu
        bmsg->cm_magic = CTDLMESSAGE_MAGIC;
        bmsg->cm_anon_type = MES_NORMAL;
        bmsg->cm_format_type = FMT_RFC822;
 -      bmsg->cm_fields['A'] = strdup("Citadel");
 -      bmsg->cm_fields['O'] = strdup(MAILROOM);
 -      bmsg->cm_fields['N'] = strdup(config.c_nodename);
 -      bmsg->cm_fields['U'] = strdup("Delivery Status Notification (Failure)");
 +      CM_SetField(bmsg, eAuthor, HKEY("Citadel"));
 +      CM_SetField(bmsg, eOriginalRoom, HKEY(MAILROOM));
 +      CM_SetField(bmsg, eNodeName, config.c_nodename, strlen(config.c_nodename));
 +      CM_SetField(bmsg, eMsgSubject, HKEY("Delivery Status Notification (Failure)"));
        StrBufAppendBufPlain(
                BounceMB,
                HKEY("Content-type: multipart/mixed; boundary=\""), 0);
        StrBufAppendBufPlain(BounceMB, HKEY("--"), 0);
        StrBufAppendBuf(BounceMB, boundary, 0);
        StrBufAppendBufPlain(BounceMB, HKEY("--\r\n"), 0);
 -      if (bmsg->cm_fields['M'] != NULL)
 -              free(bmsg->cm_fields['M']);
 -      bmsg->cm_fields['M'] = SmashStrBuf(&BounceMB);
 +      CM_SetAsFieldSB(bmsg, eMesageText, &BounceMB);
++
        /* Deliver the bounce if there's anything worth mentioning */
        syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces);
        if (num_bounces > 0) {
                }
        }
        FreeStrBuf(&boundary);
 -      CtdlFreeMessage(bmsg);
 +      CM_Free(bmsg);
        syslog(LOG_DEBUG, "Done processing bounces\n");
  }