#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,
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 */
--- /dev/null
+/*
+ * Copyright (C) 2004, 2003, 2004 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2021 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * 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
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 \
#include "incindexfile.h"
#include "chomp.h"
#include "checkwait_smtpreply.h"
-#include "init_sockfd.h"
#include "strgen.h"
#include "log_error.h"
#include "mygetline.h"
#include "mylocking.h"
#include "getaddrsfromfd.h"
#include "utils.h"
+#include "send_mails.h"
static int addtohdr = 0;
static int prepmailinmem = 0;
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 <CR><LF>.<CR><LF>\n");
- return retval;
- }
-
- reply = checkwait_smtpreply(sockfd, MLMMJ_DOT);
- if(reply) {
- log_error(LOG_ARGS, "Mailserver did not ack end of mail.\n"
- "<CR><LF>.<CR><LF> 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,
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) {
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 */
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 */
--- /dev/null
+/*
+ * Copyright (C) 2004, 2003, 2004 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2021 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * 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 <fcntl.h>
+#include <unistd.h>
+
+#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 <CR><LF>.<CR><LF>\n");
+ return retval;
+ }
+
+ reply = checkwait_smtpreply(sockfd, MLMMJ_DOT);
+ if(reply) {
+ log_error(LOG_ARGS, "Mailserver did not ack end of mail.\n"
+ "<CR><LF>.<CR><LF> 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;
+}