From: Baptiste Daroussin Date: Fri, 5 Nov 2021 09:17:45 +0000 (+0100) Subject: send_mails: extract code from mlmmj-send X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cefd1ebb8bd583e7cf760f8cb31e3b194c20b6a;p=thirdparty%2Fmlmmj.git send_mails: extract code from mlmmj-send Prepare the land for a refactoring of the send emails function, to avoid having to call the mlmmj-send binary. --- diff --git a/include/mlmmj-send.h b/include/mlmmj-send.h index 47db0bdc..90e33681 100644 --- a/include/mlmmj-send.h +++ b/include/mlmmj-send.h @@ -26,11 +26,6 @@ #include "mlmmj.h" -int send_mail(int sockfd, const char *from, const char *to, - const char *replyto, char *mailmap, size_t mailsize, - struct mlmmj_list *, const char *mlmmjbounce, - const char *hdrs, size_t hdrslen, const char *body, - size_t bodylen); int send_mail_many_fd(int sockfd, const char *from, const char *replyto, char *mailmap, size_t mailsize, int subfd, const char *archivefilename, struct mlmmj_list *list, @@ -45,7 +40,5 @@ int send_mail_verp(int sockfd, struct strlist *addrs, char *mailmap, size_t mailsize, const char *from, struct mlmmj_list *list, const char *hdrs, size_t hdrslen, const char *body, size_t bodylen, const char *extra); -int initsmtp(int *sockfd, const char *relayhost, unsigned short port, const char *heloname); -int endsmtp(int *sockfd); #endif /* MMJML_SEND_H */ diff --git a/include/send_mails.h b/include/send_mails.h new file mode 100644 index 00000000..c190fd36 --- /dev/null +++ b/include/send_mails.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2004, 2003, 2004 Mads Martin Joergensen + * Copyright (C) 2021 Baptiste Daroussin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef SEND_MAILS_H +#define SEND_MAILS_H + +int initsmtp(int *sockfd, const char *relayhost, unsigned short port, const char *heloname); +int endsmtp(int *sockfd); +int send_mail(int sockfd, const char *from, const char *to, const char *replyto, char *mailmap, size_t mailsize, struct mlmmj_list *list, const char *mlmmjbounce, const char *hdrs, size_t hdrslen, const char *body, size_t bodylen, bool addtohdr, bool prepmailinmem); +int bouncemail(struct mlmmj_list *list, const char *mlmmjbounce, const char *from); +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 0a67dcdc..a8a59e41 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ mlmmj_send_SOURCES = mlmmj.c mlmmj-send.c mail-functions.c itoa.c chomp.c \ incindexfile.c checkwait_smtpreply.c utils.c \ mylocking.c init_sockfd.c strgen.c random-int.c \ print-version.c log_error.c mygetline.c memory.c \ - controls.c getaddrsfromfd.c readn.c + controls.c getaddrsfromfd.c readn.c send_mails.c mlmmj_receive_SOURCES = mlmmj-receive.c random-int.c strgen.c \ print-version.c log_error.c dumpfd2fd.c memory.c \ diff --git a/src/mlmmj-send.c b/src/mlmmj-send.c index d2d7cd06..fd781310 100644 --- a/src/mlmmj-send.c +++ b/src/mlmmj-send.c @@ -50,7 +50,6 @@ #include "incindexfile.h" #include "chomp.h" #include "checkwait_smtpreply.h" -#include "init_sockfd.h" #include "strgen.h" #include "log_error.h" #include "mygetline.h" @@ -60,6 +59,7 @@ #include "mylocking.h" #include "getaddrsfromfd.h" #include "utils.h" +#include "send_mails.h" static int addtohdr = 0; static int prepmailinmem = 0; @@ -190,328 +190,6 @@ char *bounce_from_adr(const char *recipient, const char *mailfilename, return bounceaddr; } -int bouncemail(struct mlmmj_list *list, const char *mlmmjbounce, const char *from) -{ - char *myfrom = mystrdup(from); - char *addr, *num, *c; - size_t len; - pid_t pid = 0; - - if((c = strchr(myfrom, '@')) == NULL) { - myfree(myfrom); - return 0; /* Success when malformed 'from' */ - } - *c = '\0'; - num = strrchr(myfrom, '-'); - num++; - c = strstr(myfrom, list->delim); - myfrom = strchr(c, '-'); - myfrom++; - len = num - myfrom - 1; - addr = mymalloc(len + 1); - addr[len] = '\0'; - strncpy(addr, myfrom, len); - - pid = fork(); - - if(pid < 0) { - log_error(LOG_ARGS, "fork() failed!"); - return 1; - } - - if(pid > 0) - return 0; - - execlp(mlmmjbounce, mlmmjbounce, - "-L", list->dir, - "-a", num, - "-n", addr, (char *)NULL); - - log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjbounce); - - return 1; -} - -int send_mail(int sockfd, const char *from, const char *to, - const char *replyto, char *mailmap, size_t mailsize, - struct mlmmj_list *list, const char *mlmmjbounce, - const char *hdrs, size_t hdrslen, const char *body, - size_t bodylen) -{ - int retval = 0; - char *reply, *reply2, *tohdr; - - if(sockfd == -1) - return EBADF; - - if(strchr(to, '@') == NULL) { - errno = 0; - log_error(LOG_ARGS, "No @ in address, ignoring %s", - to); - return 0; - } - - retval = write_mail_from(sockfd, from, ""); - if(retval) { - log_error(LOG_ARGS, "Could not write MAIL FROM\n"); - return retval; - } - reply = checkwait_smtpreply(sockfd, MLMMJ_FROM); - if(reply) { - log_error(LOG_ARGS, "Error in MAIL FROM. Reply = [%s]", - reply); - myfree(reply); - write_rset(sockfd); - reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); - if (reply2 != NULL) myfree(reply2); - return MLMMJ_FROM; - } - retval = write_rcpt_to(sockfd, to); - if(retval) { - log_error(LOG_ARGS, "Could not write RCPT TO:\n"); - return retval; - } - - reply = checkwait_smtpreply(sockfd, MLMMJ_RCPTTO); - if(reply) { - write_rset(sockfd); - reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); - if (reply2 != NULL) myfree(reply2); - if(mlmmjbounce && ((reply[0] == '4') || (reply[0] == '5')) - && (reply[1] == '5')) { - myfree(reply); - return bouncemail(list, mlmmjbounce, from); - } else { - log_error(LOG_ARGS, "Error in RCPT TO. Reply = [%s]", - reply); - myfree(reply); - return MLMMJ_RCPTTO; - } - } - - retval = write_data(sockfd); - if(retval) { - log_error(LOG_ARGS, "Could not write DATA\b"); - return retval; - } - - reply = checkwait_smtpreply(sockfd, MLMMJ_DATA); - if(reply) { - log_error(LOG_ARGS, "Error with DATA. Reply = [%s]", reply); - myfree(reply); - write_rset(sockfd); - reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); - if (reply2 != NULL) myfree(reply2); - return MLMMJ_DATA; - } - - if(replyto) { - retval = write_replyto(sockfd, replyto); - if(retval) { - log_error(LOG_ARGS, "Could not write reply-to addr.\n"); - return retval; - } - } - - if(addtohdr) - tohdr = concatstr(3, "To: ", to, "\r\n"); - else - tohdr = NULL; - - if(prepmailinmem) { - retval = dprintf(sockfd, "%.*s", (int) hdrslen, hdrs); - if(retval < 0) { - log_error(LOG_ARGS, "Could not write mailheaders.\n"); - return retval; - } - if(tohdr) { - retval = dprintf(sockfd, "%s", tohdr); - if(retval < 0) { - log_error(LOG_ARGS, "Could not write To:.\n"); - return retval; - } - myfree(tohdr); - } - retval = dprintf(sockfd, "%.*s", (int)bodylen, body); - if(retval < 0) { - log_error(LOG_ARGS, "Could not write mailbody.\n"); - return retval; - } - } else { - retval = write_mailbody_from_map(sockfd, mailmap, mailsize, - tohdr); - if(retval) { - log_error(LOG_ARGS, "Could not write mail\n"); - return retval; - } - } - - retval = write_dot(sockfd); - if(retval) { - log_error(LOG_ARGS, "Could not write .\n"); - return retval; - } - - reply = checkwait_smtpreply(sockfd, MLMMJ_DOT); - if(reply) { - log_error(LOG_ARGS, "Mailserver did not ack end of mail.\n" - ". was written, to no" - "avail. Reply = [%s]", reply); - myfree(reply); - write_rset(sockfd); - reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); - if (reply2 != NULL) myfree(reply2); - return MLMMJ_DOT; - } - - return 0; -} - -int initsmtp(int *sockfd, const char *relayhost, unsigned short port, const char *heloname) -{ - int retval = 0; - int try_ehlo = 1; - char *reply = NULL; - - do { - init_sockfd(sockfd, relayhost, port); - - if(*sockfd == -1) { - retval = EBADF; - break; - } - - if((reply = checkwait_smtpreply(*sockfd, MLMMJ_CONNECT)) != NULL) { - log_error(LOG_ARGS, "No proper greeting to our connect" - "Reply: [%s]", reply); - myfree(reply); - retval = MLMMJ_CONNECT; - /* FIXME: Queue etc. */ - break; - } - - if (try_ehlo) { - write_ehlo(*sockfd, heloname); - if((reply = checkwait_smtpreply(*sockfd, MLMMJ_EHLO)) - == NULL) { - /* EHLO successful don't try more */ - break; - } - - /* RFC 1869 - 4.5. - In the case of any error response, - * the client SMTP should issue either the HELO or QUIT - * command. - * RFC 1869 - 4.5. - If the server SMTP recognizes the - * EHLO command, but the command argument is - * unacceptable, it will return code 501. - */ - if (strncmp(reply, "501", 3) == 0) { - myfree(reply); - /* Commmand unacceptable; we choose to QUIT but - * ignore any QUIT errors; return that EHLO was - * the error. - */ - endsmtp(sockfd); - retval = MLMMJ_EHLO; - break; - } - - /* RFC 1869 - 4.6. - A server SMTP that conforms to RFC - * 821 but does not support the extensions specified - * here will not recognize the EHLO command and will - * consequently return code 500, as specified in RFC - * 821. The server SMTP should stay in the same state - * after returning this code (see section 4.1.1 of RFC - * 821). The client SMTP may then issue either a HELO - * or a QUIT command. - */ - - if (reply[0] != '5') { - myfree(reply); - /* Server doesn't understand EHLO, but gives a - * broken response. Try with new connection. - */ - endsmtp(sockfd); - try_ehlo = 0; - continue; - } - - myfree(reply); - - /* RFC 1869 - 4.7. - Other improperly-implemented - * servers will not accept a HELO command after EHLO has - * been sent and rejected. In some cases, this problem - * can be worked around by sending a RSET after the - * failure response to EHLO, then sending the HELO. - */ - write_rset(*sockfd); - reply = checkwait_smtpreply(*sockfd, MLMMJ_RSET); - - /* RFC 1869 - 4.7. - Clients that do this should be - * aware that many implementations will return a failure - * code (e.g., 503 Bad sequence of commands) in response - * to the RSET. This code can be safely ignored. - */ - myfree(reply); - - /* Try HELO on the same connection - */ - } - - write_helo(*sockfd, heloname); - if((reply = checkwait_smtpreply(*sockfd, MLMMJ_HELO)) - == NULL) { - /* EHLO successful don't try more */ - break; - } - if (try_ehlo) { - myfree(reply); - /* We reused a connection we tried EHLO on. Maybe - * that's why it failed. Try with new connection. - */ - endsmtp(sockfd); - try_ehlo = 0; - continue; - } - - log_error(LOG_ARGS, "Error with HELO. Reply: " - "[%s]", reply); - myfree(reply); - /* FIXME: quit and tell admin to configure - * correctly */ - retval = MLMMJ_HELO; - break; - - } while (1); - - return retval; -} - -int endsmtp(int *sockfd) -{ - int retval = 0; - char *reply = NULL; - - if(*sockfd == -1) - return retval; - - write_quit(*sockfd); - reply = checkwait_smtpreply(*sockfd, MLMMJ_QUIT); - if(reply) { - printf("reply from quit: %s\n", reply); - log_error(LOG_ARGS, "Mailserver would not let us QUIT. " - "We close the socket anyway though. " - "Mailserver reply = [%s]", reply); - myfree(reply); - retval = MLMMJ_QUIT; - } - - close(*sockfd); - *sockfd = -1; - - return retval; -} - int send_mail_verp(int sockfd, struct strlist *addrs, char *mailmap, size_t mailsize, const char *from, struct mlmmj_list *list, const char *hdrs, size_t hdrslen, const char *body, @@ -742,12 +420,12 @@ int send_mail_many_list(int sockfd, const char *from, const char *replyto, if(from) { res = send_mail(sockfd, from, addr, replyto, mailmap, mailsize, list, NULL, - hdrs, hdrslen, body, bodylen); + hdrs, hdrslen, body, bodylen, addtohdr, prepmailinmem); } else { bounceaddr = bounce_from_adr(addr, archivefilename, list); res = send_mail(sockfd, bounceaddr, addr, replyto, mailmap, mailsize, list, mlmmjbounce, - hdrs, hdrslen, body, bodylen); + hdrs, hdrslen, body, bodylen, addtohdr, prepmailinmem); myfree(bounceaddr); } if(res && list->addr && archivefilename) { @@ -1077,7 +755,7 @@ int main(int argc, char **argv) initsmtp(&sockfd, relay, smtpport, smtphelo); if(send_mail(sockfd, bounceaddr, to_addr, replyto, mailmap, st.st_size, &list, NULL, - hdrs, hdrslen, body, bodylen)) { + hdrs, hdrslen, body, bodylen, addtohdr, prepmailinmem)) { close(sockfd); sockfd = -1; /* error, so keep it in the queue */ @@ -1169,7 +847,7 @@ int main(int argc, char **argv) initsmtp(&sockfd, relay, smtpport, smtphelo); if(send_mail(sockfd, bounceaddr, to_addr, replyto, mailmap, st.st_size, &list, NULL, - hdrs, hdrslen, body, bodylen)) { + hdrs, hdrslen, body, bodylen, addtohdr, prepmailinmem)) { close(sockfd); sockfd = -1; /* error, so remove the probefile */ diff --git a/src/send_mails.c b/src/send_mails.c new file mode 100644 index 00000000..306166bd --- /dev/null +++ b/src/send_mails.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2004, 2003, 2004 Mads Martin Joergensen + * Copyright (C) 2021 Baptiste Daroussin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include + +#include "mlmmj.h" +#include "send_mails.h" +#include "log_error.h" +#include "init_sockfd.h" +#include "checkwait_smtpreply.h" +#include "memory.h" +#include "mail-functions.h" + +int +initsmtp(int *sockfd, const char *relayhost, unsigned short port, const char *heloname) +{ + int retval = 0; + int try_ehlo = 1; + char *reply = NULL; + + do { + init_sockfd(sockfd, relayhost, port); + + if(*sockfd == -1) { + retval = EBADF; + break; + } + + if((reply = checkwait_smtpreply(*sockfd, MLMMJ_CONNECT)) != NULL) { + log_error(LOG_ARGS, "No proper greeting to our connect" + "Reply: [%s]", reply); + myfree(reply); + retval = MLMMJ_CONNECT; + /* FIXME: Queue etc. */ + break; + } + + if (try_ehlo) { + write_ehlo(*sockfd, heloname); + if((reply = checkwait_smtpreply(*sockfd, MLMMJ_EHLO)) + == NULL) { + /* EHLO successful don't try more */ + break; + } + + /* RFC 1869 - 4.5. - In the case of any error response, + * the client SMTP should issue either the HELO or QUIT + * command. + * RFC 1869 - 4.5. - If the server SMTP recognizes the + * EHLO command, but the command argument is + * unacceptable, it will return code 501. + */ + if (strncmp(reply, "501", 3) == 0) { + myfree(reply); + /* Commmand unacceptable; we choose to QUIT but + * ignore any QUIT errors; return that EHLO was + * the error. + */ + endsmtp(sockfd); + retval = MLMMJ_EHLO; + break; + } + + /* RFC 1869 - 4.6. - A server SMTP that conforms to RFC + * 821 but does not support the extensions specified + * here will not recognize the EHLO command and will + * consequently return code 500, as specified in RFC + * 821. The server SMTP should stay in the same state + * after returning this code (see section 4.1.1 of RFC + * 821). The client SMTP may then issue either a HELO + * or a QUIT command. + */ + + if (reply[0] != '5') { + myfree(reply); + /* Server doesn't understand EHLO, but gives a + * broken response. Try with new connection. + */ + endsmtp(sockfd); + try_ehlo = 0; + continue; + } + + myfree(reply); + + /* RFC 1869 - 4.7. - Other improperly-implemented + * servers will not accept a HELO command after EHLO has + * been sent and rejected. In some cases, this problem + * can be worked around by sending a RSET after the + * failure response to EHLO, then sending the HELO. + */ + write_rset(*sockfd); + reply = checkwait_smtpreply(*sockfd, MLMMJ_RSET); + + /* RFC 1869 - 4.7. - Clients that do this should be + * aware that many implementations will return a failure + * code (e.g., 503 Bad sequence of commands) in response + * to the RSET. This code can be safely ignored. + */ + myfree(reply); + + /* Try HELO on the same connection + */ + } + + write_helo(*sockfd, heloname); + if((reply = checkwait_smtpreply(*sockfd, MLMMJ_HELO)) + == NULL) { + /* EHLO successful don't try more */ + break; + } + if (try_ehlo) { + myfree(reply); + /* We reused a connection we tried EHLO on. Maybe + * that's why it failed. Try with new connection. + */ + endsmtp(sockfd); + try_ehlo = 0; + continue; + } + + log_error(LOG_ARGS, "Error with HELO. Reply: " + "[%s]", reply); + myfree(reply); + /* FIXME: quit and tell admin to configure + * correctly */ + retval = MLMMJ_HELO; + break; + + } while (1); + + return retval; +} + +int +endsmtp(int *sockfd) +{ + int retval = 0; + char *reply = NULL; + + if(*sockfd == -1) + return retval; + + write_quit(*sockfd); + reply = checkwait_smtpreply(*sockfd, MLMMJ_QUIT); + if(reply) { + printf("reply from quit: %s\n", reply); + log_error(LOG_ARGS, "Mailserver would not let us QUIT. " + "We close the socket anyway though. " + "Mailserver reply = [%s]", reply); + myfree(reply); + retval = MLMMJ_QUIT; + } + + close(*sockfd); + *sockfd = -1; + + return retval; +} + +int +send_mail(int sockfd, const char *from, const char *to, + const char *replyto, char *mailmap, size_t mailsize, + struct mlmmj_list *list, const char *mlmmjbounce, + const char *hdrs, size_t hdrslen, const char *body, + size_t bodylen, bool addtohdr, bool prepmailinmem) +{ + int retval = 0; + char *reply, *reply2, *tohdr; + + if(sockfd == -1) + return EBADF; + + if(strchr(to, '@') == NULL) { + errno = 0; + log_error(LOG_ARGS, "No @ in address, ignoring %s", + to); + return 0; + } + + retval = write_mail_from(sockfd, from, ""); + if(retval) { + log_error(LOG_ARGS, "Could not write MAIL FROM\n"); + return retval; + } + reply = checkwait_smtpreply(sockfd, MLMMJ_FROM); + if(reply) { + log_error(LOG_ARGS, "Error in MAIL FROM. Reply = [%s]", + reply); + myfree(reply); + write_rset(sockfd); + reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); + if (reply2 != NULL) myfree(reply2); + return MLMMJ_FROM; + } + retval = write_rcpt_to(sockfd, to); + if(retval) { + log_error(LOG_ARGS, "Could not write RCPT TO:\n"); + return retval; + } + + reply = checkwait_smtpreply(sockfd, MLMMJ_RCPTTO); + if(reply) { + write_rset(sockfd); + reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); + if (reply2 != NULL) myfree(reply2); + if(mlmmjbounce && ((reply[0] == '4') || (reply[0] == '5')) + && (reply[1] == '5')) { + myfree(reply); + return bouncemail(list, mlmmjbounce, from); + } else { + log_error(LOG_ARGS, "Error in RCPT TO. Reply = [%s]", + reply); + myfree(reply); + return MLMMJ_RCPTTO; + } + } + + retval = write_data(sockfd); + if(retval) { + log_error(LOG_ARGS, "Could not write DATA\b"); + return retval; + } + + reply = checkwait_smtpreply(sockfd, MLMMJ_DATA); + if(reply) { + log_error(LOG_ARGS, "Error with DATA. Reply = [%s]", reply); + myfree(reply); + write_rset(sockfd); + reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); + if (reply2 != NULL) myfree(reply2); + return MLMMJ_DATA; + } + + if(replyto) { + retval = write_replyto(sockfd, replyto); + if(retval) { + log_error(LOG_ARGS, "Could not write reply-to addr.\n"); + return retval; + } + } + + if(addtohdr) + myasprintf(&tohdr, "To: %s\r\n", to); + else + tohdr = NULL; + + if(prepmailinmem) { + retval = dprintf(sockfd, "%.*s", (int) hdrslen, hdrs); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write mailheaders.\n"); + return retval; + } + if(tohdr) { + retval = dprintf(sockfd, "%s", tohdr); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write To:.\n"); + return retval; + } + myfree(tohdr); + } + retval = dprintf(sockfd, "%.*s", (int)bodylen, body); + if(retval < 0) { + log_error(LOG_ARGS, "Could not write mailbody.\n"); + return retval; + } + } else { + retval = write_mailbody_from_map(sockfd, mailmap, mailsize, + tohdr); + if(retval) { + log_error(LOG_ARGS, "Could not write mail\n"); + return retval; + } + } + + retval = write_dot(sockfd); + if(retval) { + log_error(LOG_ARGS, "Could not write .\n"); + return retval; + } + + reply = checkwait_smtpreply(sockfd, MLMMJ_DOT); + if(reply) { + log_error(LOG_ARGS, "Mailserver did not ack end of mail.\n" + ". was written, to no" + "avail. Reply = [%s]", reply); + myfree(reply); + write_rset(sockfd); + reply2 = checkwait_smtpreply(sockfd, MLMMJ_RSET); + if (reply2 != NULL) myfree(reply2); + return MLMMJ_DOT; + } + + return 0; +} + +int +bouncemail(struct mlmmj_list *list, const char *mlmmjbounce, const char *from) +{ + char *myfrom = mystrdup(from); + char *addr, *num, *c; + size_t len; + pid_t pid = 0; + + if((c = strchr(myfrom, '@')) == NULL) { + myfree(myfrom); + return 0; /* Success when malformed 'from' */ + } + *c = '\0'; + num = strrchr(myfrom, '-'); + num++; + c = strstr(myfrom, list->delim); + myfrom = strchr(c, '-'); + myfrom++; + len = num - myfrom - 1; + addr = mymalloc(len + 1); + addr[len] = '\0'; + strncpy(addr, myfrom, len); + + pid = fork(); + + if(pid < 0) { + log_error(LOG_ARGS, "fork() failed!"); + return 1; + } + + if(pid > 0) + return 0; + + execlp(mlmmjbounce, mlmmjbounce, + "-L", list->dir, + "-a", num, + "-n", addr, (char *)NULL); + + log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjbounce); + + return 1; +}