X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fsmtp%2Fsmtp_util.c;h=589f8855305f4eb889d087a745e598d10cfba435;hb=573281fcad13fe840b7f0795ff36be5cfc5b420a;hp=fa59255eb04c29f8681ab5ce7b11d7a4fc447014;hpb=f4693017e0e3eca231dad3b67cc4a6211f522343;p=citadel.git diff --git a/citadel/modules/smtp/smtp_util.c b/citadel/modules/smtp/smtp_util.c index fa59255eb..589f88553 100644 --- a/citadel/modules/smtp/smtp_util.c +++ b/citadel/modules/smtp/smtp_util.c @@ -20,21 +20,21 @@ * 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-2012 by the citadel.org team * - * This program is free 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. + * 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. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * */ #include "sysdep.h" @@ -96,3 +96,230 @@ const char *smtp_get_Recipients(void) return NULL; else return sSMTP->from; } + + +/* + * smtp_do_bounce() is caled by smtp_do_procmsg() to scan a set of delivery + * instructions for "5" codes (permanent fatal errors) and produce/deliver + * a "bounce" message (delivery status notification). + */ +void smtp_do_bounce(char *instr, StrBuf *OMsgTxt) +{ + int i; + int lines; + int status; + char buf[1024]; + char key[1024]; + char addr[1024]; + char dsn[1024]; + char bounceto[1024]; + StrBuf *boundary; + int num_bounces = 0; + int bounce_this = 0; + time_t submitted = 0L; + struct CtdlMessage *bmsg = NULL; + int give_up = 0; + struct recptypes *valid; + int successful_bounce = 0; + static int seq = 0; + StrBuf *BounceMB; + long omsgid = (-1); + + 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); + + lines = num_tokens(instr, '\n'); + + /* See if it's time to give up on delivery of this message */ + for (i=0; i SMTP_GIVE_UP ) { + give_up = 1; + } + + /* Start building our bounce message */ + + bmsg = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage)); + if (bmsg == NULL) return; + memset(bmsg, 0, sizeof(struct CtdlMessage)); + BounceMB = NewStrBufPlain(NULL, 1024); + + 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)"); + 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\ndue 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); + } + + /* + * Now go through the instructions checking for stuff. + */ + for (i=0; i addr=<%s> status=%d dsn=<%s>\n", + key, addr, status, dsn); + + if (!strcasecmp(key, "bounceto")) { + strcpy(bounceto, addr); + } + + if (!strcasecmp(key, "msgid")) { + omsgid = atol(addr); + } + + if (!strcasecmp(key, "remote")) { + if (status == 5) bounce_this = 1; + if (give_up) bounce_this = 1; + } + + if (bounce_this) { + ++num_bounces; + + StrBufAppendBufPlain(BounceMB, addr, addrlen, 0); + StrBufAppendBufPlain(BounceMB, HKEY(": "), 0); + StrBufAppendBufPlain(BounceMB, dsn, dsnlen, 0); + StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); + + remove_token(instr, i, '\n'); + --i; + --lines; + } + } + + /* Attach the original message */ + if (omsgid >= 0) { + StrBufAppendBufPlain(BounceMB, HKEY("--"), 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); + + if (OMsgTxt == NULL) { + CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); + CtdlOutputMsg(omsgid, + MT_RFC822, + HEADERS_ALL, + 0, 1, NULL, 0, + NULL, NULL); + + StrBufAppendBuf(BounceMB, CC->redirect_buffer, 0); + FreeStrBuf(&CC->redirect_buffer); + } + else { + StrBufAppendBuf(BounceMB, OMsgTxt, 0); + } + } + + /* Close the multipart MIME scope */ + StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); + StrBufAppendBuf(BounceMB, boundary, 0); + StrBufAppendBufPlain(BounceMB, HKEY("--\r\n"), 0); + if (bmsg->cm_fields['A'] != NULL) + free(bmsg->cm_fields['A']); + bmsg->cm_fields['A'] = SmashStrBuf(&BounceMB); + /* Deliver the bounce if there's anything worth mentioning */ + syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces); + if (num_bounces > 0) { + + /* First try the user who sent the message */ + if (IsEmptyStr(bounceto)) + syslog(LOG_ERR, "No bounce address specified\n"); + else + syslog(LOG_DEBUG, "bounce to user <%s>\n", bounceto); + /* Can we deliver the bounce to the original sender? */ + valid = validate_recipients(bounceto, + smtp_get_Recipients (), + 0); + if (valid != NULL) { + if (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 */ + if (valid != NULL) { + free_recipients(valid); + } + } + FreeStrBuf(&boundary); + CtdlFreeMessage(bmsg); + syslog(LOG_DEBUG, "Done processing bounces\n"); +}